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