rapidjson
A fast JSON parser/generator for C++ with both SAX/DOM style API
 All Classes Functions Variables Typedefs Pages
document.h
1 #ifndef RAPIDJSON_DOCUMENT_H_
2 #define RAPIDJSON_DOCUMENT_H_
3 
4 #include "reader.h"
5 #include "internal/strfunc.h"
6 
7 #ifdef _MSC_VER
8 #pragma warning(push)
9 #pragma warning(disable : 4127) // conditional expression is constant
10 #endif
11 
12 namespace rapidjson {
13 
14 ///////////////////////////////////////////////////////////////////////////////
15 // GenericValue
16 
17 //! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
18 /*!
19  A JSON value can be one of 7 types. This class is a variant type supporting
20  these types.
21 
22  Use the Value if UTF8 and default allocator
23 
24  \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
25  \tparam Allocator Allocator type for allocating memory of object, array and string.
26 */
27 #pragma pack (push, 4)
28 template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
29 class GenericValue {
30 public:
31  //! Name-value pair in an object.
32  struct Member {
33  GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
35  };
36 
37  typedef Encoding EncodingType; //!< Encoding type from template parameter.
38  typedef Allocator AllocatorType; //!< Allocator type from template parameter.
39  typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
40  typedef Member* MemberIterator; //!< Member iterator for iterating in object.
41  typedef const Member* ConstMemberIterator; //!< Constant member iterator for iterating in object.
42  typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
43  typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
44 
45  //!@name Constructors and destructor.
46  //@{
47 
48  //! Default constructor creates a null value.
49  GenericValue() : flags_(kNullFlag) {}
50 
51  //! Copy constructor is not permitted.
52 private:
53  GenericValue(const GenericValue& rhs);
54 
55 public:
56 
57  //! Constructor with JSON value type.
58  /*! This creates a Value of specified type with default content.
59  \param type Type of the value.
60  \note Default content for number is zero.
61  */
62  GenericValue(Type type) {
63  static const unsigned defaultFlags[7] = {
64  kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag,
65  kNumberFlag | kIntFlag | kUintFlag | kInt64Flag | kUint64Flag | kDoubleFlag
66  };
67  RAPIDJSON_ASSERT(type <= kNumberType);
68  flags_ = defaultFlags[type];
69  memset(&data_, 0, sizeof(data_));
70  }
71 
72  //! Constructor for boolean value.
73  GenericValue(bool b) : flags_(b ? kTrueFlag : kFalseFlag) {}
74 
75  //! Constructor for int value.
76  GenericValue(int i) : flags_(kNumberIntFlag) {
77  data_.n.i64 = i;
78  if (i >= 0)
79  flags_ |= kUintFlag | kUint64Flag;
80  }
81 
82  //! Constructor for unsigned value.
83  GenericValue(unsigned u) : flags_(kNumberUintFlag) {
84  data_.n.u64 = u;
85  if (!(u & 0x80000000))
86  flags_ |= kIntFlag | kInt64Flag;
87  }
88 
89  //! Constructor for int64_t value.
90  GenericValue(int64_t i64) : flags_(kNumberInt64Flag) {
91  data_.n.i64 = i64;
92  if (i64 >= 0) {
93  flags_ |= kNumberUint64Flag;
94  if (!(i64 & 0xFFFFFFFF00000000LL))
95  flags_ |= kUintFlag;
96  if (!(i64 & 0xFFFFFFFF80000000LL))
97  flags_ |= kIntFlag;
98  }
99  else if (i64 >= -2147483648LL)
100  flags_ |= kIntFlag;
101  }
102 
103  //! Constructor for uint64_t value.
104  GenericValue(uint64_t u64) : flags_(kNumberUint64Flag) {
105  data_.n.u64 = u64;
106  if (!(u64 & 0x8000000000000000ULL))
107  flags_ |= kInt64Flag;
108  if (!(u64 & 0xFFFFFFFF00000000ULL))
109  flags_ |= kUintFlag;
110  if (!(u64 & 0xFFFFFFFF80000000ULL))
111  flags_ |= kIntFlag;
112  }
113 
114  //! Constructor for double value.
115  GenericValue(double d) : flags_(kNumberDoubleFlag) { data_.n.d = d; }
116 
117  //! Constructor for constant string (i.e. do not make a copy of string)
118  GenericValue(const Ch* s, SizeType length) {
119  RAPIDJSON_ASSERT(s != NULL);
120  flags_ = kConstStringFlag;
121  data_.s.str = s;
122  data_.s.length = length;
123  }
124 
125  //! Constructor for constant string (i.e. do not make a copy of string)
126  GenericValue(const Ch* s) { SetStringRaw(s, internal::StrLen(s)); }
127 
128  //! Constructor for copy-string (i.e. do make a copy of string)
129  GenericValue(const Ch* s, SizeType length, Allocator& allocator) { SetStringRaw(s, length, allocator); }
130 
131  //! Constructor for copy-string (i.e. do make a copy of string)
132  GenericValue(const Ch*s, Allocator& allocator) { SetStringRaw(s, internal::StrLen(s), allocator); }
133 
134  //! Destructor.
135  /*! Need to destruct elements of array, members of object, or copy-string.
136  */
138  if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
139  switch(flags_) {
140  case kArrayFlag:
141  for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
142  v->~GenericValue();
143  Allocator::Free(data_.a.elements);
144  break;
145 
146  case kObjectFlag:
147  for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) {
148  m->name.~GenericValue();
149  m->value.~GenericValue();
150  }
151  Allocator::Free(data_.o.members);
152  break;
153 
154  case kCopyStringFlag:
155  Allocator::Free(const_cast<Ch*>(data_.s.str));
156  break;
157  }
158  }
159  }
160 
161  //@}
162 
163  //!@name Assignment operators
164  //@{
165 
166  //! Assignment with move semantics.
167  /*! \param rhs Source of the assignment. It will become a null value after assignment.
168  */
170  RAPIDJSON_ASSERT(this != &rhs);
171  this->~GenericValue();
172  memcpy(this, &rhs, sizeof(GenericValue));
173  rhs.flags_ = kNullFlag;
174  return *this;
175  }
176 
177  //! Assignment with primitive types.
178  /*! \tparam T Either Type, int, unsigned, int64_t, uint64_t, const Ch*
179  \param value The value to be assigned.
180  */
181  template <typename T>
183  this->~GenericValue();
184  new (this) GenericValue(value);
185  return *this;
186  }
187  //@}
188 
189  //!@name Type
190  //@{
191 
192  Type GetType() const { return static_cast<Type>(flags_ & kTypeMask); }
193  bool IsNull() const { return flags_ == kNullFlag; }
194  bool IsFalse() const { return flags_ == kFalseFlag; }
195  bool IsTrue() const { return flags_ == kTrueFlag; }
196  bool IsBool() const { return (flags_ & kBoolFlag) != 0; }
197  bool IsObject() const { return flags_ == kObjectFlag; }
198  bool IsArray() const { return flags_ == kArrayFlag; }
199  bool IsNumber() const { return (flags_ & kNumberFlag) != 0; }
200  bool IsInt() const { return (flags_ & kIntFlag) != 0; }
201  bool IsUint() const { return (flags_ & kUintFlag) != 0; }
202  bool IsInt64() const { return (flags_ & kInt64Flag) != 0; }
203  bool IsUint64() const { return (flags_ & kUint64Flag) != 0; }
204  bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; }
205  bool IsString() const { return (flags_ & kStringFlag) != 0; }
206 
207  //@}
208 
209  //!@name Null
210  //@{
211 
212  GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
213 
214  //@}
215 
216  //!@name Bool
217  //@{
218 
219  bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; }
220  GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
221 
222  //@}
223 
224  //!@name Object
225  //@{
226 
227  //! Set this value as an empty object.
228  GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
229 
230  //! Get the value associated with the object's name.
231  GenericValue& operator[](const Ch* name) {
232  if (Member* member = FindMember(name))
233  return member->value;
234  else {
235  static GenericValue NullValue;
236  return NullValue;
237  }
238  }
239  const GenericValue& operator[](const Ch* name) const { return const_cast<GenericValue&>(*this)[name]; }
240 
241  //! Member iterators.
242  ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; }
243  ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; }
244  MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; }
245  MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; }
246 
247  //! Check whether a member exists in the object.
248  bool HasMember(const Ch* name) const { return FindMember(name) != 0; }
249 
250  //! Add a member (name-value pair) to the object.
251  /*! \param name A string value as name of member.
252  \param value Value of any type.
253  \param allocator Allocator for reallocating memory.
254  \return The value itself for fluent API.
255  \note The ownership of name and value will be transfered to this object if success.
256  */
258  RAPIDJSON_ASSERT(IsObject());
259  RAPIDJSON_ASSERT(name.IsString());
260  Object& o = data_.o;
261  if (o.size >= o.capacity) {
262  if (o.capacity == 0) {
263  o.capacity = kDefaultObjectCapacity;
264  o.members = (Member*)allocator.Malloc(o.capacity * sizeof(Member));
265  }
266  else {
267  SizeType oldCapacity = o.capacity;
268  o.capacity *= 2;
269  o.members = (Member*)allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member));
270  }
271  }
272  o.members[o.size].name.RawAssign(name);
273  o.members[o.size].value.RawAssign(value);
274  o.size++;
275  return *this;
276  }
277 
278  GenericValue& AddMember(const Ch* name, Allocator& nameAllocator, GenericValue& value, Allocator& allocator) {
279  GenericValue n(name, internal::StrLen(name), nameAllocator);
280  return AddMember(n, value, allocator);
281  }
282 
283  GenericValue& AddMember(const Ch* name, GenericValue& value, Allocator& allocator) {
284  GenericValue n(name, internal::StrLen(name));
285  return AddMember(n, value, allocator);
286  }
287 
288  template <typename T>
289  GenericValue& AddMember(const Ch* name, T value, Allocator& allocator) {
290  GenericValue n(name, internal::StrLen(name));
291  GenericValue v(value);
292  return AddMember(n, v, allocator);
293  }
294 
295  //! Remove a member in object by its name.
296  /*! \param name Name of member to be removed.
297  \return Whether the member existed.
298  \note Removing member is implemented by moving the last member. So the ordering of members is changed.
299  */
300  bool RemoveMember(const Ch* name) {
301  RAPIDJSON_ASSERT(IsObject());
302  if (Member* m = FindMember(name)) {
303  RAPIDJSON_ASSERT(data_.o.size > 0);
304  RAPIDJSON_ASSERT(data_.o.members != 0);
305 
306  Member* last = data_.o.members + (data_.o.size - 1);
307  if (data_.o.size > 1 && m != last) {
308  // Move the last one to this place
309  m->name = last->name;
310  m->value = last->value;
311  }
312  else {
313  // Only one left, just destroy
314  m->name.~GenericValue();
315  m->value.~GenericValue();
316  }
317  --data_.o.size;
318  return true;
319  }
320  return false;
321  }
322 
323  //@}
324 
325  //!@name Array
326  //@{
327 
328  //! Set this value as an empty array.
329  GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
330 
331  //! Get the number of elements in array.
332  SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
333 
334  //! Get the capacity of array.
335  SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
336 
337  //! Check whether the array is empty.
338  bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
339 
340  //! Remove all elements in the array.
341  /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
342  */
343  void Clear() {
344  RAPIDJSON_ASSERT(IsArray());
345  for (SizeType i = 0; i < data_.a.size; ++i)
346  data_.a.elements[i].~GenericValue();
347  data_.a.size = 0;
348  }
349 
350  //! Get an element from array by index.
351  /*! \param index Zero-based index of element.
352  \note
353 \code
354 Value a(kArrayType);
355 a.PushBack(123);
356 int x = a[0].GetInt(); // Error: operator[ is ambiguous, as 0 also mean a null pointer of const char* type.
357 int y = a[SizeType(0)].GetInt(); // Cast to SizeType will work.
358 int z = a[0u].GetInt(); // This works too.
359 \endcode
360  */
361  GenericValue& operator[](SizeType index) {
362  RAPIDJSON_ASSERT(IsArray());
363  RAPIDJSON_ASSERT(index < data_.a.size);
364  return data_.a.elements[index];
365  }
366  const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
367 
368  //! Element iterator
369  ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; }
370  ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; }
371  ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
372  ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
373 
374  //! Request the array to have enough capacity to store elements.
375  /*! \param newCapacity The capacity that the array at least need to have.
376  \param allocator The allocator for allocating memory. It must be the same one use previously.
377  \return The value itself for fluent API.
378  */
379  GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
380  RAPIDJSON_ASSERT(IsArray());
381  if (newCapacity > data_.a.capacity) {
382  data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue));
383  data_.a.capacity = newCapacity;
384  }
385  return *this;
386  }
387 
388  //! Append a value at the end of the array.
389  /*! \param value The value to be appended.
390  \param allocator The allocator for allocating memory. It must be the same one use previously.
391  \return The value itself for fluent API.
392  \note The ownership of the value will be transfered to this object if success.
393  \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
394  */
396  RAPIDJSON_ASSERT(IsArray());
397  if (data_.a.size >= data_.a.capacity)
398  Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : data_.a.capacity * 2, allocator);
399  data_.a.elements[data_.a.size++].RawAssign(value);
400  return *this;
401  }
402 
403  template <typename T>
404  GenericValue& PushBack(T value, Allocator& allocator) {
405  GenericValue v(value);
406  return PushBack(v, allocator);
407  }
408 
409  //! Remove the last element in the array.
411  RAPIDJSON_ASSERT(IsArray());
412  RAPIDJSON_ASSERT(!Empty());
413  data_.a.elements[--data_.a.size].~GenericValue();
414  return *this;
415  }
416  //@}
417 
418  //!@name Number
419  //@{
420 
421  int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i.i; }
422  unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u.u; }
423  int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; }
424  uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; }
425 
426  double GetDouble() const {
427  RAPIDJSON_ASSERT(IsNumber());
428  if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
429  if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double
430  if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
431  if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision)
432  RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision)
433  }
434 
435  GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
436  GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
437  GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
438  GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
439  GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
440 
441  //@}
442 
443  //!@name String
444  //@{
445 
446  const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return data_.s.str; }
447 
448  //! Get the length of string.
449  /*! Since rapidjson permits "\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
450  */
451  SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return data_.s.length; }
452 
453  //! Set this value as a string without copying source string.
454  /*! This version has better performance with supplied length, and also support string containing null character.
455  \param s source string pointer.
456  \param length The length of source string, excluding the trailing null terminator.
457  \return The value itself for fluent API.
458  */
459  GenericValue& SetString(const Ch* s, SizeType length) { this->~GenericValue(); SetStringRaw(s, length); return *this; }
460 
461  //! Set this value as a string without copying source string.
462  /*! \param s source string pointer.
463  \return The value itself for fluent API.
464  */
465  GenericValue& SetString(const Ch* s) { return SetString(s, internal::StrLen(s)); }
466 
467  //! Set this value as a string by copying from source string.
468  /*! This version has better performance with supplied length, and also support string containing null character.
469  \param s source string.
470  \param length The length of source string, excluding the trailing null terminator.
471  \param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator().
472  \return The value itself for fluent API.
473  */
474  GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, length, allocator); return *this; }
475 
476  //! Set this value as a string by copying from source string.
477  /*! \param s source string.
478  \param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator().
479  \return The value itself for fluent API.
480  */
481  GenericValue& SetString(const Ch* s, Allocator& allocator) { SetString(s, internal::StrLen(s), allocator); return *this; }
482 
483  //@}
484 
485  //! Generate events of this value to a Handler.
486  /*! This function adopts the GoF visitor pattern.
487  Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
488  It can also be used to deep clone this value via GenericDocument, which is also a Handler.
489  \tparam Handler type of handler.
490  \param handler An object implementing concept Handler.
491  */
492  template <typename Handler>
493  const GenericValue& Accept(Handler& handler) const {
494  switch(GetType()) {
495  case kNullType: handler.Null(); break;
496  case kFalseType: handler.Bool(false); break;
497  case kTrueType: handler.Bool(true); break;
498 
499  case kObjectType:
500  handler.StartObject();
501  for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) {
502  handler.String(m->name.data_.s.str, m->name.data_.s.length, false);
503  m->value.Accept(handler);
504  }
505  handler.EndObject(data_.o.size);
506  break;
507 
508  case kArrayType:
509  handler.StartArray();
510  for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
511  v->Accept(handler);
512  handler.EndArray(data_.a.size);
513  break;
514 
515  case kStringType:
516  handler.String(data_.s.str, data_.s.length, false);
517  break;
518 
519  case kNumberType:
520  if (IsInt()) handler.Int(data_.n.i.i);
521  else if (IsUint()) handler.Uint(data_.n.u.u);
522  else if (IsInt64()) handler.Int64(data_.n.i64);
523  else if (IsUint64()) handler.Uint64(data_.n.u64);
524  else handler.Double(data_.n.d);
525  break;
526  }
527  return *this;
528  }
529 
530 private:
531  template <typename, typename>
532  friend class GenericDocument;
533 
534  enum {
535  kBoolFlag = 0x100,
536  kNumberFlag = 0x200,
537  kIntFlag = 0x400,
538  kUintFlag = 0x800,
539  kInt64Flag = 0x1000,
540  kUint64Flag = 0x2000,
541  kDoubleFlag = 0x4000,
542  kStringFlag = 0x100000,
543  kCopyFlag = 0x200000,
544 
545  // Initial flags of different types.
546  kNullFlag = kNullType,
547  kTrueFlag = kTrueType | kBoolFlag,
548  kFalseFlag = kFalseType | kBoolFlag,
549  kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
550  kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
551  kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
552  kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
553  kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
554  kConstStringFlag = kStringType | kStringFlag,
555  kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
556  kObjectFlag = kObjectType,
557  kArrayFlag = kArrayType,
558 
559  kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler
560  };
561 
562  static const SizeType kDefaultArrayCapacity = 16;
563  static const SizeType kDefaultObjectCapacity = 16;
564 
565  struct String {
566  const Ch* str;
567  SizeType length;
568  unsigned hashcode; //!< reserved
569  }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
570 
571  // By using proper binary layout, retrieval of different integer types do not need conversions.
572  union Number {
573 #if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
574  struct I {
575  int i;
576  char padding[4];
577  }i;
578  struct U {
579  unsigned u;
580  char padding2[4];
581  }u;
582 #else
583  struct I {
584  char padding[4];
585  int i;
586  }i;
587  struct U {
588  char padding2[4];
589  unsigned u;
590  }u;
591 #endif
592  int64_t i64;
593  uint64_t u64;
594  double d;
595  }; // 8 bytes
596 
597  struct Object {
598  Member* members;
599  SizeType size;
600  SizeType capacity;
601  }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
602 
603  struct Array {
604  GenericValue<Encoding, Allocator>* elements;
605  SizeType size;
606  SizeType capacity;
607  }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
608 
609  union Data {
610  String s;
611  Number n;
612  Object o;
613  Array a;
614  }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
615 
616  //! Find member by name.
617  Member* FindMember(const Ch* name) {
618  RAPIDJSON_ASSERT(name);
619  RAPIDJSON_ASSERT(IsObject());
620 
621  SizeType length = internal::StrLen(name);
622 
623  Object& o = data_.o;
624  for (Member* member = o.members; member != data_.o.members + data_.o.size; ++member)
625  if (length == member->name.data_.s.length && memcmp(member->name.data_.s.str, name, length * sizeof(Ch)) == 0)
626  return member;
627 
628  return 0;
629  }
630  const Member* FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
631 
632  // Initialize this value as array with initial data, without calling destructor.
633  void SetArrayRaw(GenericValue* values, SizeType count, Allocator& alloctaor) {
634  flags_ = kArrayFlag;
635  data_.a.elements = (GenericValue*)alloctaor.Malloc(count * sizeof(GenericValue));
636  memcpy(data_.a.elements, values, count * sizeof(GenericValue));
637  data_.a.size = data_.a.capacity = count;
638  }
639 
640  //! Initialize this value as object with initial data, without calling destructor.
641  void SetObjectRaw(Member* members, SizeType count, Allocator& alloctaor) {
642  flags_ = kObjectFlag;
643  data_.o.members = (Member*)alloctaor.Malloc(count * sizeof(Member));
644  memcpy(data_.o.members, members, count * sizeof(Member));
645  data_.o.size = data_.o.capacity = count;
646  }
647 
648  //! Initialize this value as constant string, without calling destructor.
649  void SetStringRaw(const Ch* s, SizeType length) {
650  RAPIDJSON_ASSERT(s != NULL);
651  flags_ = kConstStringFlag;
652  data_.s.str = s;
653  data_.s.length = length;
654  }
655 
656  //! Initialize this value as copy string with initial data, without calling destructor.
657  void SetStringRaw(const Ch* s, SizeType length, Allocator& allocator) {
658  RAPIDJSON_ASSERT(s != NULL);
659  flags_ = kCopyStringFlag;
660  data_.s.str = (Ch *)allocator.Malloc((length + 1) * sizeof(Ch));
661  data_.s.length = length;
662  memcpy(const_cast<Ch*>(data_.s.str), s, length * sizeof(Ch));
663  const_cast<Ch*>(data_.s.str)[length] = '\0';
664  }
665 
666  //! Assignment without calling destructor
667  void RawAssign(GenericValue& rhs) {
668  memcpy(this, &rhs, sizeof(GenericValue));
669  rhs.flags_ = kNullFlag;
670  }
671 
672  Data data_;
673  unsigned flags_;
674 };
675 #pragma pack (pop)
676 
677 //! Value with UTF8 encoding.
678 typedef GenericValue<UTF8<> > Value;
679 
680 ///////////////////////////////////////////////////////////////////////////////
681 // GenericDocument
682 
683 //! A document for parsing JSON text as DOM.
684 /*!
685  \implements Handler
686  \tparam Encoding encoding for both parsing and string storage.
687  \tparam Alloactor allocator for allocating memory for the DOM, and the stack during parsing.
688 */
689 template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
690 class GenericDocument : public GenericValue<Encoding, Allocator> {
691 public:
692  typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
693  typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document.
694  typedef Allocator AllocatorType; //!< Allocator type from template parameter.
695 
696  //! Constructor
697  /*! \param allocator Optional allocator for allocating stack memory.
698  \param stackCapacity Initial capacity of stack in bytes.
699  */
700  GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {}
701 
702  //! Parse JSON text from an input stream.
703  /*! \tparam parseFlags Combination of ParseFlag.
704  \param stream Input stream to be parsed.
705  \return The document itself for fluent API.
706  */
707  template <unsigned parseFlags, typename Stream>
709  ValueType::SetNull(); // Remove existing root if exist
711  if (reader.template Parse<parseFlags>(stream, *this)) {
712  RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
713  this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13.
714  parseError_ = 0;
715  errorOffset_ = 0;
716  }
717  else {
718  parseError_ = reader.GetParseError();
719  errorOffset_ = reader.GetErrorOffset();
720  ClearStack();
721  }
722  return *this;
723  }
724 
725  //! Parse JSON text from a mutable string.
726  /*! \tparam parseFlags Combination of ParseFlag.
727  \param str Mutable zero-terminated string to be parsed.
728  \return The document itself for fluent API.
729  */
730  template <unsigned parseFlags>
733  return ParseStream<parseFlags | kParseInsituFlag>(s);
734  }
735 
736  //! Parse JSON text from a read-only string.
737  /*! \tparam parseFlags Combination of ParseFlag (must not contain kParseInsituFlag).
738  \param str Read-only zero-terminated string to be parsed.
739  */
740  template <unsigned parseFlags>
741  GenericDocument& Parse(const Ch* str) {
742  RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
744  return ParseStream<parseFlags>(s);
745  }
746 
747  //! Whether a parse error was occured in the last parsing.
748  bool HasParseError() const { return parseError_ != 0; }
749 
750  //! Get the message of parsing error.
751  const char* GetParseError() const { return parseError_; }
752 
753  //! Get the offset in character of the parsing error.
754  size_t GetErrorOffset() const { return errorOffset_; }
755 
756  //! Get the allocator of this document.
757  Allocator& GetAllocator() { return stack_.GetAllocator(); }
758 
759  //! Get the capacity of stack in bytes.
760  size_t GetStackCapacity() const { return stack_.GetCapacity(); }
761 
762 private:
763  // Prohibit assignment
764  GenericDocument& operator=(const GenericDocument&);
765 
766  friend class GenericReader<Encoding, Allocator>; // for Reader to call the following private handler functions
767 
768  // Implementation of Handler
769  void Null() { new (stack_.template Push<ValueType>()) ValueType(); }
770  void Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); }
771  void Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); }
772  void Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); }
773  void Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); }
774  void Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); }
775  void Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); }
776 
777  void String(const Ch* str, SizeType length, bool copy) {
778  if (copy)
779  new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
780  else
781  new (stack_.template Push<ValueType>()) ValueType(str, length);
782  }
783 
784  void StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); }
785 
786  void EndObject(SizeType memberCount) {
787  typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
788  stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
789  }
790 
791  void StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); }
792 
793  void EndArray(SizeType elementCount) {
794  ValueType* elements = stack_.template Pop<ValueType>(elementCount);
795  stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
796  }
797 
798  void ClearStack() {
799  if (Allocator::kNeedFree)
800  while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
801  (stack_.template Pop<ValueType>(1))->~ValueType();
802  else
803  stack_.Clear();
804  }
805 
806  static const size_t kDefaultStackCapacity = 1024;
807  internal::Stack<Allocator> stack_;
808  const char* parseError_;
809  size_t errorOffset_;
810 };
811 
812 typedef GenericDocument<UTF8<> > Document;
813 
814 } // namespace rapidjson
815 
816 #ifdef _MSC_VER
817 #pragma warning(pop)
818 #endif
819 
820 #endif // RAPIDJSON_DOCUMENT_H_