1 #ifndef RAPIDJSON_DOCUMENT_H_
2 #define RAPIDJSON_DOCUMENT_H_
10 #pragma warning(disable : 4127) // conditional expression is constant
28 #pragma pack (push, 4)
29 template <
typename Encoding,
typename Allocator = MemoryPoolAllocator<> >
40 typedef typename Encoding::Ch
Ch;
64 static const unsigned defaultFlags[7] = {
65 kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag,
66 kNumberFlag | kIntFlag | kUintFlag | kInt64Flag | kUint64Flag | kDoubleFlag
69 flags_ = defaultFlags[type];
70 memset(&data_, 0,
sizeof(data_));
80 flags_ |= kUintFlag | kUint64Flag;
86 if (!(u & 0x80000000))
87 flags_ |= kIntFlag | kInt64Flag;
94 flags_ |= kNumberUint64Flag;
95 if (!(i64 & 0xFFFFFFFF00000000LL))
97 if (!(i64 & 0xFFFFFFFF80000000LL))
100 else if (i64 >= -2147483648LL)
107 if (!(u64 & 0x8000000000000000ULL))
108 flags_ |= kInt64Flag;
109 if (!(u64 & 0xFFFFFFFF00000000ULL))
111 if (!(u64 & 0xFFFFFFFF80000000ULL))
121 flags_ = kConstStringFlag;
123 data_.s.length = length;
139 if (Allocator::kNeedFree) {
142 for (
GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
144 Allocator::Free(data_.a.elements);
148 for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) {
149 m->name.~GenericValue();
150 m->value.~GenericValue();
152 Allocator::Free(data_.o.members);
155 case kCopyStringFlag:
156 Allocator::Free(const_cast<Ch*>(data_.s.str));
174 rhs.flags_ = kNullFlag;
182 template <
typename T>
194 bool IsNull()
const {
return flags_ == kNullFlag; }
195 bool IsFalse()
const {
return flags_ == kFalseFlag; }
196 bool IsTrue()
const {
return flags_ == kTrueFlag; }
197 bool IsBool()
const {
return (flags_ & kBoolFlag) != 0; }
198 bool IsObject()
const {
return flags_ == kObjectFlag; }
199 bool IsArray()
const {
return flags_ == kArrayFlag; }
200 bool IsNumber()
const {
return (flags_ & kNumberFlag) != 0; }
201 bool IsInt()
const {
return (flags_ & kIntFlag) != 0; }
202 bool IsUint()
const {
return (flags_ & kUintFlag) != 0; }
203 bool IsInt64()
const {
return (flags_ & kInt64Flag) != 0; }
204 bool IsUint64()
const {
return (flags_ & kUint64Flag) != 0; }
205 bool IsDouble()
const {
return (flags_ & kDoubleFlag) != 0; }
206 bool IsString()
const {
return (flags_ & kStringFlag) != 0; }
233 if (Member* member = FindMember(name))
234 return member->value;
249 bool HasMember(
const Ch* name)
const {
return FindMember(name) != 0; }
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));
270 o.members = (Member*)allocator.Realloc(o.members, oldCapacity *
sizeof(Member), o.capacity *
sizeof(Member));
273 o.members[o.size].name.RawAssign(name);
274 o.members[o.size].value.RawAssign(value);
289 template <
typename T>
303 if (Member* m = FindMember(name)) {
307 Member* last = data_.o.members + (data_.o.size - 1);
308 if (data_.o.size > 1 && m != last) {
310 m->name = last->name;
311 m->value = last->value;
315 m->name.~GenericValue();
316 m->value.~GenericValue();
346 for (
SizeType i = 0; i < data_.a.size; ++i)
347 data_.a.elements[i].~GenericValue();
365 return data_.a.elements[index];
382 if (newCapacity > data_.a.capacity) {
384 data_.a.capacity = newCapacity;
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);
404 template <
typename T>
414 data_.a.elements[--data_.a.size].~GenericValue();
429 if ((flags_ & kDoubleFlag) != 0)
return data_.n.d;
430 if ((flags_ & kIntFlag) != 0)
return data_.n.i.i;
431 if ((flags_ & kUintFlag) != 0)
return data_.n.u.u;
432 if ((flags_ & kInt64Flag) != 0)
return (
double)data_.n.i64;
493 template <
typename Handler>
498 case kTrueType: handler.Bool(
true);
break;
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);
506 handler.EndObject(data_.o.size);
510 handler.StartArray();
511 for (
GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
513 handler.EndArray(data_.a.size);
517 handler.String(data_.s.str, data_.s.length,
false);
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);
532 template <
typename,
typename>
541 kUint64Flag = 0x2000,
542 kDoubleFlag = 0x4000,
543 kStringFlag = 0x100000,
544 kCopyFlag = 0x200000,
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,
556 kCopyStringFlag =
kStringType | kStringFlag | kCopyFlag,
563 static const SizeType kDefaultArrayCapacity = 16;
564 static const SizeType kDefaultObjectCapacity = 16;
574 #if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
605 GenericValue<Encoding, Allocator>* elements;
618 Member* FindMember(
const Ch* name) {
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)
631 const Member* FindMember(
const Ch* name)
const {
return const_cast<GenericValue&
>(*this).FindMember(name); }
637 memcpy(data_.a.elements, values, count *
sizeof(
GenericValue));
638 data_.a.size = data_.a.capacity = count;
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;
650 void SetStringRaw(
const Ch* s,
SizeType length) {
652 flags_ = kConstStringFlag;
654 data_.s.length = length;
658 void SetStringRaw(
const Ch* s,
SizeType length, Allocator& allocator) {
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';
670 rhs.flags_ = kNullFlag;
690 template <
typename Encoding,
typename Allocator = MemoryPoolAllocator<> >
693 typedef typename Encoding::Ch
Ch;
701 GenericDocument(
Allocator* allocator = 0,
size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {}
708 template <
unsigned parseFlags,
typename Stream>
712 if (reader.template Parse<parseFlags>(stream, *
this)) {
714 this->RawAssign(*stack_.template Pop<ValueType>(1));
731 template <
unsigned parseFlags>
734 return ParseStream<parseFlags | kParseInsituFlag>(s);
741 template <
unsigned parseFlags>
745 return ParseStream<parseFlags>(s);
770 void Null() {
new (stack_.template Push<ValueType>())
ValueType(); }
771 void Bool(
bool b) {
new (stack_.template Push<ValueType>())
ValueType(b); }
772 void Int(
int i) {
new (stack_.template Push<ValueType>())
ValueType(i); }
773 void Uint(
unsigned i) {
new (stack_.template Push<ValueType>())
ValueType(i); }
774 void Int64(int64_t i) {
new (stack_.template Push<ValueType>())
ValueType(i); }
775 void Uint64(uint64_t i) {
new (stack_.template Push<ValueType>())
ValueType(i); }
776 void Double(
double d) {
new (stack_.template Push<ValueType>())
ValueType(d); }
778 void String(
const Ch* str,
SizeType length,
bool copy) {
782 new (stack_.template Push<ValueType>())
ValueType(str, length);
787 void EndObject(
SizeType memberCount) {
788 typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
794 void EndArray(
SizeType elementCount) {
795 ValueType* elements = stack_.template Pop<ValueType>(elementCount);
796 stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount,
GetAllocator());
800 if (Allocator::kNeedFree)
801 while (stack_.GetSize() > 0)
802 (stack_.template Pop<ValueType>(1))->~
ValueType();
807 static const size_t kDefaultStackCapacity = 1024;
808 internal::Stack<Allocator> stack_;
809 const char* parseError_;
821 #endif // RAPIDJSON_DOCUMENT_H_
GenericDocument & Parse(const Ch *str)
Parse JSON text from a read-only string.
Member * MemberIterator
Member iterator for iterating in object.
Concept for receiving events from GenericReader upon parsing.
ValueIterator Begin()
Element iterator.
GenericValue< Encoding, Allocator > name
name of member (must be a string)
GenericValue(uint64_t u64)
Constructor for uint64_t value.
GenericValue(const Ch *s, SizeType length, Allocator &allocator)
Constructor for copy-string (i.e. do make a copy of string)
uint64_t GetUint64() const
~GenericValue()
Destructor.
GenericValue & operator=(T value)
Assignment with primitive types.
GenericValue & PushBack(T value, Allocator &allocator)
SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
GenericValue(const Ch *s, SizeType length)
Constructor for constant string (i.e. do not make a copy of string)
GenericDocument & ParseInsitu(Ch *str)
Parse JSON text from a mutable string.
SizeType StrLen(const Ch *s)
Custom strlen() which works on different character types.
GenericValue & operator[](const Ch *name)
Get the value associated with the object's name.
GenericValue & SetObject()
Set this value as an empty object.
ConstMemberIterator MemberBegin() const
Member iterators.
ConstMemberIterator MemberEnd() const
unsigned SizeType
Use 32-bit array/string indices even for 64-bit platform, instead of using size_t.
const GenericValue & Accept(Handler &handler) const
Generate events of this value to a Handler.
GenericDocument & ParseStream(Stream &stream)
Parse JSON text from an input stream.
GenericValue(const Ch *s, Allocator &allocator)
Constructor for copy-string (i.e. do make a copy of string)
size_t GetStackCapacity() const
Get the capacity of stack in bytes.
bool RemoveMember(const Ch *name)
Remove a member in object by its name.
GenericValue(int64_t i64)
Constructor for int64_t value.
GenericValue(double d)
Constructor for double value.
GenericValue & PopBack()
Remove the last element in the array.
GenericValue & Reserve(SizeType newCapacity, Allocator &allocator)
Request the array to have enough capacity to store elements.
Allocator AllocatorType
Allocator type from template parameter.
MemberIterator MemberBegin()
Allocator AllocatorType
Allocator type from template parameter.
GenericValue & SetInt64(int64_t i64)
GenericValue & SetString(const Ch *s, SizeType length, Allocator &allocator)
Set this value as a string by copying from source string.
GenericValue & SetInt(int i)
GenericValue & SetString(const Ch *s, SizeType length)
Set this value as a string without copying source string.
GenericValue(Type type)
Constructor with JSON value type.
SizeType Size() const
Get the number of elements in array.
const GenericValue * ConstValueIterator
Constant value iterator for iterating in array.
Concept for encoding of Unicode characters.
GenericValue< Encoding, Allocator > ValueType
Value type of the document.
GenericValue & AddMember(GenericValue &name, GenericValue &value, Allocator &allocator)
Add a member (name-value pair) to the object.
ConstValueIterator Begin() const
void Clear()
Remove all elements in the array.
#define RAPIDJSON_ASSERT(x)
Assertion.
GenericValue & operator=(GenericValue &rhs)
Assignment with move semantics.
GenericValue()
Default constructor creates a null value.
const Member * ConstMemberIterator
Constant member iterator for iterating in object.
GenericValue & operator[](SizeType index)
Get an element from array by index.
const GenericValue & operator[](SizeType index) const
GenericValue & SetDouble(double d)
GenericValue & PushBack(GenericValue &value, Allocator &allocator)
Append a value at the end of the array.
bool HasParseError() const
Whether a parse error was occured in the last parsing.
MemberIterator MemberEnd()
const char * GetParseError() const
Get the message of parsing error.
A document for parsing JSON text as DOM.
GenericValue & SetUint(unsigned u)
GenericValue * ValueIterator
Value iterator for iterating in array.
Encoding::Ch Ch
Character type derived from Encoding.
Encoding::Ch Ch
Character type derived from Encoding.
GenericValue & AddMember(const Ch *name, T value, Allocator &allocator)
GenericValue & AddMember(const Ch *name, GenericValue &value, Allocator &allocator)
Concept for reading and writing characters.
size_t GetErrorOffset() const
Allocator & GetAllocator()
Get the allocator of this document.
size_t GetErrorOffset() const
Get the offset in character of the parsing error.
Encoding EncodingType
Encoding type from template parameter.
CompositeGenerator< T > values(T val1, T val2)
const char * GetParseError() const
GenericValue(unsigned u)
Constructor for unsigned value.
In-situ(destructive) parsing.
bool HasMember(const Ch *name) const
Check whether a member exists in the object.
bool Empty() const
Check whether the array is empty.
GenericValue & SetString(const Ch *s)
Set this value as a string without copying source string.
GenericValue(int i)
Constructor for int value.
GenericValue & SetBool(bool b)
GenericDocument(Allocator *allocator=0, size_t stackCapacity=kDefaultStackCapacity)
Constructor.
Concept for allocating, resizing and freeing memory block.
Represents a JSON value. Use Value for UTF8 encoding and default allocator.
GenericValue< UTF8<> > Value
Value with UTF8 encoding.
GenericValue & SetArray()
Set this value as an empty array.
GenericValue & SetString(const Ch *s, Allocator &allocator)
Set this value as a string by copying from source string.
GenericValue< Encoding, Allocator > value
value of member.
GenericValue(bool b)
Constructor for boolean value.
const Ch * GetString() const
GenericValue(const Ch *s)
Constructor for constant string (i.e. do not make a copy of string)
GenericValue & AddMember(const Ch *name, Allocator &nameAllocator, GenericValue &value, Allocator &allocator)
ConstValueIterator End() const
SizeType Capacity() const
Get the capacity of array.
GenericValue & SetUint64(uint64_t u64)
GenericDocument< UTF8<> > Document
Name-value pair in an object.
SizeType GetStringLength() const
Get the length of string.
A read-write string stream.
const GenericValue & operator[](const Ch *name) const