rapidjson A fast JSON parser/generator for C++ with both SAX/DOM style API

- Main Page
- Related Pages
- Classes
- Files

- File List

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)
34 GenericValue<Encoding, Allocator> value; //!< value of member.
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 */
137 ~GenericValue() {
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 */
169 GenericValue& operator=(GenericValue& rhs) {
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>
182 GenericValue& operator=(T value) {
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 */
257 GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
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 */
395 GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
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.
410 GenericValue& PopBack() {
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>
708 GenericDocument& ParseStream(Stream& stream) {
709 ValueType::SetNull(); // Remove existing root if exist
710 GenericReader<Encoding, Allocator> reader;
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>
731 GenericDocument& ParseInsitu(Ch* str) {
732 GenericInsituStringStream<Encoding> s(str);
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));
743 GenericStringStream<Encoding> s(str);
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_