8#ifndef SkJSONWriter_DEFINED
9#define SkJSONWriter_DEFINED
58 : fBlock(new char[kBlockSize])
60 , fBlockEnd(fBlock + kBlockSize)
63 , fState(
State::kStart) {
79 if (fWrite != fBlock) {
80 fStream->
write(fBlock, fWrite - fBlock);
94 SkASSERT(Scope::kObject == this->scope());
95 SkASSERT(State::kObjectBegin == fState || State::kObjectValue == fState);
96 if (State::kObjectValue == fState) {
99 this->separator(this->multiline());
100 this->write(
"\"", 1);
102 this->write(
"\":", 2);
103 fState = State::kObjectName;
116 this->beginValue(
true);
120 fState = State::kObjectBegin;
127 SkASSERT(Scope::kObject == this->scope());
128 SkASSERT(State::kObjectBegin == fState || State::kObjectValue == fState);
129 bool emptyObject = State::kObjectBegin == fState;
130 bool wasMultiline = this->multiline();
133 this->separator(wasMultiline);
148 this->beginValue(
true);
152 fState = State::kArrayBegin;
159 SkASSERT(Scope::kArray == this->scope());
160 SkASSERT(State::kArrayBegin == fState || State::kArrayValue == fState);
161 bool emptyArray = State::kArrayBegin == fState;
162 bool wasMultiline = this->multiline();
165 this->separator(wasMultiline);
178 this->write(
"\"", 1);
180 char const *
const end =
value + size;
185 case '"': this->write(
"\\\"", 2);
break;
186 case '\\': this->write(
"\\\\", 2);
break;
187 case '\b': this->write(
"\\b", 2);
break;
188 case '\f': this->write(
"\\f", 2);
break;
189 case '\n': this->write(
"\\n", 2);
break;
190 case '\r': this->write(
"\\r", 2);
break;
191 case '\t': this->write(
"\\t", 2);
break;
196 s.appendHex((
unsigned char)*
value, 4);
197 this->write(
s.c_str(),
s.size());
198 }
else if (u < 0x20) {
201 this->write(
s.c_str(),
s.size());
210 this->write(
"\"", 1);
216 template <
class T, std::enable_if_t<std::is_same_v<T,std::
string>,
bool> = false>
221 static_assert(
N > 0);
232 this->write(
"true", 4);
234 this->write(
"false", 5);
237 void appendS32(int32_t value) { this->beginValue(); this->appendf(
"%d",
value); }
239 void appendU32(uint32_t value) { this->beginValue(); this->appendf(
"%u",
value); }
245 this->appendf(
"%.*g", digits,
value);
249 this->appendf(
"%.*g", digits,
value);
263 template <
class T, std::enable_if_t<std::is_same_v<T,std::
string>,
bool> = false>
269 static_assert(
N > 0);
277#define DEFINE_NAMED_APPEND(function, type) \
278 void function(const char* name, type value) { this->appendName(name); this->function(value); }
295#undef DEFINE_NAMED_APPEND
311 kBlockSize = 32 * 1024,
332 void beginValue(
bool structure = false) {
333 SkASSERT(State::kObjectName == fState ||
334 State::kArrayBegin == fState ||
335 State::kArrayValue == fState ||
336 (structure && State::kStart == fState));
337 if (State::kArrayValue == fState) {
340 if (Scope::kArray == this->scope()) {
341 this->separator(this->multiline());
342 }
else if (Scope::kObject == this->scope() &&
Mode::kPretty == fMode) {
348 fState = Scope::kArray == this->scope() ? State::kArrayValue : State::kObjectValue;
352 void separator(
bool multiline) {
355 this->write(
"\n", 1);
356 for (
int i = 0; i < fScopeStack.
size() - 1; ++i) {
365 void write(
const char* buf,
size_t length) {
366 if (
static_cast<size_t>(fBlockEnd - fWrite) <
length) {
370 if (length > kBlockSize) {
374 memcpy(fWrite, buf,
length);
379 Scope scope()
const {
381 return fScopeStack.
back();
384 bool multiline()
const {
386 return fNewlineStack.
back();
392 switch (this->scope()) {
394 fState = State::kEnd;
397 fState = State::kObjectValue;
400 fState = State::kArrayValue;
static float next(float f)
#define SkDEBUGFAIL(message)
#define SK_PRINTF_LIKE(A, B)
#define DEFINE_NAMED_APPEND(function, type)
void appendS32(int32_t value)
void appendNString(char const (&value)[N])
SkJSONWriter(SkWStream *stream, Mode mode=Mode::kFast)
void appendFloatDigits(float value, int digits)
void appendString(const T &value)
void beginArray(const char *name=nullptr, bool multiline=true)
void appendDouble(double value)
void appendNString(const char *name, char const (&value)[N])
void appendString(const char *name, const SkString &value)
void appendU32(uint32_t value)
void appendDoubleDigits(const char *name, double value, int digits)
void beginObject(const char *name=nullptr, bool multiline=true)
void appendU64(uint64_t value)
void appendFloat(float value)
void appendPointer(const void *value)
void appendS64(int64_t value)
void appendCString(const char *name, const char *value)
void appendBool(bool value)
void appendName(const char *name)
void appendCString(const char *value)
void appendString(const SkString &value)
void appendString(const char *name, const T &value)
void appendHexU64(uint64_t value)
void appendString(const char *value, size_t size)
void appendDoubleDigits(double value, int digits)
void appendHexU32(uint32_t value)
void appendFloatDigits(const char *name, float value, int digits)
void appendString(const char *name, const char *value, size_t size)
const char * c_str() const
virtual bool write(const void *buffer, size_t size)=0
SK_SPI SkUnichar NextUTF8(const char **ptr, const char *end)
static SkString fmt(SkColor4f c)