GDevelop Core
Core library for developing platforms and tools compatible with GDevelop.
writer.h
1 // Tencent is pleased to support the open source community by making RapidJSON available.
2 //
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 //
5 // Licensed under the MIT License (the "License"); you may not use this file except
6 // in compliance with the License. You may obtain a copy of the License at
7 //
8 // http://opensource.org/licenses/MIT
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 // specific language governing permissions and limitations under the License.
14 
15 #ifndef RAPIDJSON_WRITER_H_
16 #define RAPIDJSON_WRITER_H_
17 
18 #include "stream.h"
19 #include "internal/stack.h"
20 #include "internal/strfunc.h"
21 #include "internal/dtoa.h"
22 #include "internal/itoa.h"
23 #include "stringbuffer.h"
24 #include <new> // placement new
25 
26 #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
27 #include <intrin.h>
28 #pragma intrinsic(_BitScanForward)
29 #endif
30 #ifdef RAPIDJSON_SSE42
31 #include <nmmintrin.h>
32 #elif defined(RAPIDJSON_SSE2)
33 #include <emmintrin.h>
34 #endif
35 
36 #ifdef _MSC_VER
37 RAPIDJSON_DIAG_PUSH
38 RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
39 #endif
40 
41 #ifdef __clang__
42 RAPIDJSON_DIAG_PUSH
43 RAPIDJSON_DIAG_OFF(padded)
44 RAPIDJSON_DIAG_OFF(unreachable-code)
45 #endif
46 
48 
50 // WriteFlag
51 
58 #ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
59 #define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
60 #endif
61 
63 enum WriteFlag {
64  kWriteNoFlags = 0,
65  kWriteValidateEncodingFlag = 1,
66  kWriteNanAndInfFlag = 2,
67  kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS
68 };
69 
71 
86 template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
87 class Writer {
88 public:
89  typedef typename SourceEncoding::Ch Ch;
90 
91  static const int kDefaultMaxDecimalPlaces = 324;
92 
94 
98  explicit
99  Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
100  os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
101 
102  explicit
103  Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
104  os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
105 
107 
124  void Reset(OutputStream& os) {
125  os_ = &os;
126  hasRoot_ = false;
127  level_stack_.Clear();
128  }
129 
131 
134  bool IsComplete() const {
135  return hasRoot_ && level_stack_.Empty();
136  }
137 
138  int GetMaxDecimalPlaces() const {
139  return maxDecimalPlaces_;
140  }
141 
143 
163  void SetMaxDecimalPlaces(int maxDecimalPlaces) {
164  maxDecimalPlaces_ = maxDecimalPlaces;
165  }
166 
171 
172  bool Null() { Prefix(kNullType); return EndValue(WriteNull()); }
173  bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
174  bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); }
175  bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); }
176  bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
177  bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
178 
180 
184  bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
185 
186  bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
187  (void)copy;
188  Prefix(kNumberType);
189  return EndValue(WriteString(str, length));
190  }
191 
192  bool String(const Ch* str, SizeType length, bool copy = false) {
193  (void)copy;
194  Prefix(kStringType);
195  return EndValue(WriteString(str, length));
196  }
197 
198 #if RAPIDJSON_HAS_STDSTRING
199  bool String(const std::basic_string<Ch>& str) {
200  return String(str.data(), SizeType(str.size()));
201  }
202 #endif
203 
204  bool StartObject() {
205  Prefix(kObjectType);
206  new (level_stack_.template Push<Level>()) Level(false);
207  return WriteStartObject();
208  }
209 
210  bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
211 
212  bool EndObject(SizeType memberCount = 0) {
213  (void)memberCount;
214  RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
215  RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
216  level_stack_.template Pop<Level>(1);
217  return EndValue(WriteEndObject());
218  }
219 
220  bool StartArray() {
221  Prefix(kArrayType);
222  new (level_stack_.template Push<Level>()) Level(true);
223  return WriteStartArray();
224  }
225 
226  bool EndArray(SizeType elementCount = 0) {
227  (void)elementCount;
228  RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
229  RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
230  level_stack_.template Pop<Level>(1);
231  return EndValue(WriteEndArray());
232  }
234 
237 
239  bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
240  bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
241 
243 
245 
252  bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return EndValue(WriteRawValue(json, length)); }
253 
254 protected:
256  struct Level {
257  Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
258  size_t valueCount;
259  bool inArray;
260  };
261 
262  static const size_t kDefaultLevelDepth = 32;
263 
264  bool WriteNull() {
265  PutReserve(*os_, 4);
266  PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
267  }
268 
269  bool WriteBool(bool b) {
270  if (b) {
271  PutReserve(*os_, 4);
272  PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
273  }
274  else {
275  PutReserve(*os_, 5);
276  PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
277  }
278  return true;
279  }
280 
281  bool WriteInt(int i) {
282  char buffer[11];
283  const char* end = internal::i32toa(i, buffer);
284  PutReserve(*os_, static_cast<size_t>(end - buffer));
285  for (const char* p = buffer; p != end; ++p)
286  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
287  return true;
288  }
289 
290  bool WriteUint(unsigned u) {
291  char buffer[10];
292  const char* end = internal::u32toa(u, buffer);
293  PutReserve(*os_, static_cast<size_t>(end - buffer));
294  for (const char* p = buffer; p != end; ++p)
295  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
296  return true;
297  }
298 
299  bool WriteInt64(int64_t i64) {
300  char buffer[21];
301  const char* end = internal::i64toa(i64, buffer);
302  PutReserve(*os_, static_cast<size_t>(end - buffer));
303  for (const char* p = buffer; p != end; ++p)
304  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
305  return true;
306  }
307 
308  bool WriteUint64(uint64_t u64) {
309  char buffer[20];
310  char* end = internal::u64toa(u64, buffer);
311  PutReserve(*os_, static_cast<size_t>(end - buffer));
312  for (char* p = buffer; p != end; ++p)
313  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
314  return true;
315  }
316 
317  bool WriteDouble(double d) {
318  if (internal::Double(d).IsNanOrInf()) {
319  if (!(writeFlags & kWriteNanAndInfFlag))
320  return false;
321  if (internal::Double(d).IsNan()) {
322  PutReserve(*os_, 3);
323  PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
324  return true;
325  }
326  if (internal::Double(d).Sign()) {
327  PutReserve(*os_, 9);
328  PutUnsafe(*os_, '-');
329  }
330  else
331  PutReserve(*os_, 8);
332  PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
333  PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
334  return true;
335  }
336 
337  char buffer[25];
338  char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
339  PutReserve(*os_, static_cast<size_t>(end - buffer));
340  for (char* p = buffer; p != end; ++p)
341  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
342  return true;
343  }
344 
345  bool WriteString(const Ch* str, SizeType length) {
346  static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
347  static const char escape[256] = {
348 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
349  //0 1 2 3 4 5 6 7 8 9 A B C D E F
350  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
351  'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
352  0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
353  Z16, Z16, // 30~4F
354  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
355  Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
356 #undef Z16
357  };
358 
359  if (TargetEncoding::supportUnicode)
360  PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
361  else
362  PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
363 
364  PutUnsafe(*os_, '\"');
366  while (ScanWriteUnescapedString(is, length)) {
367  const Ch c = is.Peek();
368  if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
369  // Unicode escaping
370  unsigned codepoint;
371  if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
372  return false;
373  PutUnsafe(*os_, '\\');
374  PutUnsafe(*os_, 'u');
375  if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
376  PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
377  PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
378  PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
379  PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
380  }
381  else {
382  RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
383  // Surrogate pair
384  unsigned s = codepoint - 0x010000;
385  unsigned lead = (s >> 10) + 0xD800;
386  unsigned trail = (s & 0x3FF) + 0xDC00;
387  PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
388  PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
389  PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
390  PutUnsafe(*os_, hexDigits[(lead ) & 15]);
391  PutUnsafe(*os_, '\\');
392  PutUnsafe(*os_, 'u');
393  PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
394  PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
395  PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
396  PutUnsafe(*os_, hexDigits[(trail ) & 15]);
397  }
398  }
399  else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
400  is.Take();
401  PutUnsafe(*os_, '\\');
402  PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
403  if (escape[static_cast<unsigned char>(c)] == 'u') {
404  PutUnsafe(*os_, '0');
405  PutUnsafe(*os_, '0');
406  PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
407  PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
408  }
409  }
410  else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
413  return false;
414  }
415  PutUnsafe(*os_, '\"');
416  return true;
417  }
418 
419  bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
420  return RAPIDJSON_LIKELY(is.Tell() < length);
421  }
422 
423  bool WriteStartObject() { os_->Put('{'); return true; }
424  bool WriteEndObject() { os_->Put('}'); return true; }
425  bool WriteStartArray() { os_->Put('['); return true; }
426  bool WriteEndArray() { os_->Put(']'); return true; }
427 
428  bool WriteRawValue(const Ch* json, size_t length) {
429  PutReserve(*os_, length);
430  for (size_t i = 0; i < length; i++) {
431  RAPIDJSON_ASSERT(json[i] != '\0');
432  PutUnsafe(*os_, json[i]);
433  }
434  return true;
435  }
436 
437  void Prefix(Type type) {
438  (void)type;
439  if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
440  Level* level = level_stack_.template Top<Level>();
441  if (level->valueCount > 0) {
442  if (level->inArray)
443  os_->Put(','); // add comma if it is not the first element in array
444  else // in object
445  os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
446  }
447  if (!level->inArray && level->valueCount % 2 == 0)
448  RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
449  level->valueCount++;
450  }
451  else {
452  RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
453  hasRoot_ = true;
454  }
455  }
456 
457  // Flush the value if it is the top level one.
458  bool EndValue(bool ret) {
459  if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
460  os_->Flush();
461  return ret;
462  }
463 
464  OutputStream* os_;
465  internal::Stack<StackAllocator> level_stack_;
466  int maxDecimalPlaces_;
467  bool hasRoot_;
468 
469 private:
470  // Prohibit copy constructor & assignment operator.
471  Writer(const Writer&);
472  Writer& operator=(const Writer&);
473 };
474 
475 // Full specialization for StringStream to prevent memory copying
476 
477 template<>
478 inline bool Writer<StringBuffer>::WriteInt(int i) {
479  char *buffer = os_->Push(11);
480  const char* end = internal::i32toa(i, buffer);
481  os_->Pop(static_cast<size_t>(11 - (end - buffer)));
482  return true;
483 }
484 
485 template<>
486 inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
487  char *buffer = os_->Push(10);
488  const char* end = internal::u32toa(u, buffer);
489  os_->Pop(static_cast<size_t>(10 - (end - buffer)));
490  return true;
491 }
492 
493 template<>
494 inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
495  char *buffer = os_->Push(21);
496  const char* end = internal::i64toa(i64, buffer);
497  os_->Pop(static_cast<size_t>(21 - (end - buffer)));
498  return true;
499 }
500 
501 template<>
502 inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
503  char *buffer = os_->Push(20);
504  const char* end = internal::u64toa(u, buffer);
505  os_->Pop(static_cast<size_t>(20 - (end - buffer)));
506  return true;
507 }
508 
509 template<>
510 inline bool Writer<StringBuffer>::WriteDouble(double d) {
511  if (internal::Double(d).IsNanOrInf()) {
512  // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
513  if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
514  return false;
515  if (internal::Double(d).IsNan()) {
516  PutReserve(*os_, 3);
517  PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
518  return true;
519  }
520  if (internal::Double(d).Sign()) {
521  PutReserve(*os_, 9);
522  PutUnsafe(*os_, '-');
523  }
524  else
525  PutReserve(*os_, 8);
526  PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
527  PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
528  return true;
529  }
530 
531  char *buffer = os_->Push(25);
532  char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
533  os_->Pop(static_cast<size_t>(25 - (end - buffer)));
534  return true;
535 }
536 
537 #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
538 template<>
539 inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
540  if (length < 16)
541  return RAPIDJSON_LIKELY(is.Tell() < length);
542 
543  if (!RAPIDJSON_LIKELY(is.Tell() < length))
544  return false;
545 
546  const char* p = is.src_;
547  const char* end = is.head_ + length;
548  const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
549  const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
550  if (nextAligned > end)
551  return true;
552 
553  while (p != nextAligned)
554  if (*p < 0x20 || *p == '\"' || *p == '\\') {
555  is.src_ = p;
556  return RAPIDJSON_LIKELY(is.Tell() < length);
557  }
558  else
559  os_->PutUnsafe(*p++);
560 
561  // The rest of string using SIMD
562  static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
563  static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
564  static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
565  const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
566  const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
567  const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
568 
569  for (; p != endAligned; p += 16) {
570  const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
571  const __m128i t1 = _mm_cmpeq_epi8(s, dq);
572  const __m128i t2 = _mm_cmpeq_epi8(s, bs);
573  const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
574  const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
575  unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
576  if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
577  SizeType len;
578 #ifdef _MSC_VER // Find the index of first escaped
579  unsigned long offset;
580  _BitScanForward(&offset, r);
581  len = offset;
582 #else
583  len = static_cast<SizeType>(__builtin_ffs(r) - 1);
584 #endif
585  char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
586  for (size_t i = 0; i < len; i++)
587  q[i] = p[i];
588 
589  p += len;
590  break;
591  }
592  _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
593  }
594 
595  is.src_ = p;
596  return RAPIDJSON_LIKELY(is.Tell() < length);
597 }
598 #endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
599 
601 
602 #ifdef _MSC_VER
603 RAPIDJSON_DIAG_POP
604 #endif
605 
606 #ifdef __clang__
607 RAPIDJSON_DIAG_POP
608 #endif
609 
610 #endif // RAPIDJSON_RAPIDJSON_H_
JSON writer.
Definition: writer.h:87
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:134
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:184
bool String(const Ch *str)
Simpler but slower overload.
Definition: writer.h:239
void SetMaxDecimalPlaces(int maxDecimalPlaces)
Sets the maximum number of decimal places for double output.
Definition: writer.h:163
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:124
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition: writer.h:252
Writer(OutputStream &os, StackAllocator *stackAllocator=0, size_t levelDepth=kDefaultLevelDepth)
Constructor.
Definition: writer.h:99
Definition: ieee754.h:23
#define RAPIDJSON_LIKELY(x)
Compiler branching hint for expression with high probability to be true.
Definition: rapidjson.h:455
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:468
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:402
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:116
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:119
Type
Type of JSON value.
Definition: rapidjson.h:603
@ kFalseType
false
Definition: rapidjson.h:605
@ kObjectType
object
Definition: rapidjson.h:607
@ kTrueType
true
Definition: rapidjson.h:606
@ kStringType
string
Definition: rapidjson.h:609
@ kNullType
null
Definition: rapidjson.h:604
@ kArrayType
array
Definition: rapidjson.h:608
@ kNumberType
number
Definition: rapidjson.h:610
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:380
Read-only string stream.
Definition: stream.h:110
const Ch * head_
Original head of the string.
Definition: stream.h:125
const Ch * src_
Current read position.
Definition: stream.h:124
Encoding conversion.
Definition: encodings.h:658
Information for each nested level.
Definition: writer.h:256
size_t valueCount
number of values in this level
Definition: writer.h:258
bool inArray
true if in array, otherwise in object
Definition: writer.h:259