1 | // Tencent is pleased to support the open source community by making RapidJSON available. |
2 | // |
3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. |
4 | // |
5 | // Licensed under the MIT License (the "License"); you may not use this file except |
6 | // in compliance with the License. You may obtain a copy of the License at |
7 | // |
8 | // http://opensource.org/licenses/MIT |
9 | // |
10 | // Unless required by applicable law or agreed to in writing, software distributed |
11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the |
13 | // specific language governing permissions and limitations under the License. |
14 | |
15 | #ifndef RAPIDJSON_DOCUMENT_H_ |
16 | #define RAPIDJSON_DOCUMENT_H_ |
17 | |
18 | /*! \file document.h */ |
19 | |
20 | #include "reader.h" |
21 | #include "internal/meta.h" |
22 | #include "internal/strfunc.h" |
23 | #include "memorystream.h" |
24 | #include "encodedstream.h" |
25 | #include <new> // placement new |
26 | #include <limits> |
27 | |
28 | RAPIDJSON_DIAG_PUSH |
29 | #ifdef _MSC_VER |
30 | RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant |
31 | RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data |
32 | #endif |
33 | |
34 | #ifdef __clang__ |
35 | RAPIDJSON_DIAG_OFF(padded) |
36 | RAPIDJSON_DIAG_OFF(switch-enum) |
37 | RAPIDJSON_DIAG_OFF(c++98-compat) |
38 | #endif |
39 | |
40 | #ifdef __GNUC__ |
41 | RAPIDJSON_DIAG_OFF(effc++) |
42 | #if __GNUC__ >= 6 |
43 | RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions |
44 | #endif |
45 | #endif // __GNUC__ |
46 | |
47 | #ifndef RAPIDJSON_NOMEMBERITERATORCLASS |
48 | #include <iterator> // std::iterator, std::random_access_iterator_tag |
49 | #endif |
50 | |
51 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
52 | #include <utility> // std::move |
53 | #endif |
54 | |
55 | RAPIDJSON_NAMESPACE_BEGIN |
56 | |
57 | // Forward declaration. |
58 | template <typename Encoding, typename Allocator> |
59 | class GenericValue; |
60 | |
61 | template <typename Encoding, typename Allocator, typename StackAllocator> |
62 | class GenericDocument; |
63 | |
64 | //! Name-value pair in a JSON object value. |
65 | /*! |
66 | This class was internal to GenericValue. It used to be a inner struct. |
67 | But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct. |
68 | https://code.google.com/p/rapidjson/issues/detail?id=64 |
69 | */ |
70 | template <typename Encoding, typename Allocator> |
71 | struct GenericMember { |
72 | GenericValue<Encoding, Allocator> name; //!< name of member (must be a string) |
73 | GenericValue<Encoding, Allocator> value; //!< value of member. |
74 | }; |
75 | |
76 | /////////////////////////////////////////////////////////////////////////////// |
77 | // GenericMemberIterator |
78 | |
79 | #ifndef RAPIDJSON_NOMEMBERITERATORCLASS |
80 | |
81 | //! (Constant) member iterator for a JSON object value |
82 | /*! |
83 | \tparam Const Is this a constant iterator? |
84 | \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) |
85 | \tparam Allocator Allocator type for allocating memory of object, array and string. |
86 | |
87 | This class implements a Random Access Iterator for GenericMember elements |
88 | of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements]. |
89 | |
90 | \note This iterator implementation is mainly intended to avoid implicit |
91 | conversions from iterator values to \c NULL, |
92 | e.g. from GenericValue::FindMember. |
93 | |
94 | \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a |
95 | pointer-based implementation, if your platform doesn't provide |
96 | the C++ <iterator> header. |
97 | |
98 | \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator |
99 | */ |
100 | template <bool Const, typename Encoding, typename Allocator> |
101 | class GenericMemberIterator |
102 | : public std::iterator<std::random_access_iterator_tag |
103 | , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> { |
104 | |
105 | friend class GenericValue<Encoding,Allocator>; |
106 | template <bool, typename, typename> friend class GenericMemberIterator; |
107 | |
108 | typedef GenericMember<Encoding,Allocator> PlainType; |
109 | typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; |
110 | typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType; |
111 | |
112 | public: |
113 | //! Iterator type itself |
114 | typedef GenericMemberIterator Iterator; |
115 | //! Constant iterator type |
116 | typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator; |
117 | //! Non-constant iterator type |
118 | typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator; |
119 | |
120 | //! Pointer to (const) GenericMember |
121 | typedef typename BaseType::pointer Pointer; |
122 | //! Reference to (const) GenericMember |
123 | typedef typename BaseType::reference Reference; |
124 | //! Signed integer type (e.g. \c ptrdiff_t) |
125 | typedef typename BaseType::difference_type DifferenceType; |
126 | |
127 | //! Default constructor (singular value) |
128 | /*! Creates an iterator pointing to no element. |
129 | \note All operations, except for comparisons, are undefined on such values. |
130 | */ |
131 | GenericMemberIterator() : ptr_() {} |
132 | |
133 | //! Iterator conversions to more const |
134 | /*! |
135 | \param it (Non-const) iterator to copy from |
136 | |
137 | Allows the creation of an iterator from another GenericMemberIterator |
138 | that is "less const". Especially, creating a non-constant iterator |
139 | from a constant iterator are disabled: |
140 | \li const -> non-const (not ok) |
141 | \li const -> const (ok) |
142 | \li non-const -> const (ok) |
143 | \li non-const -> non-const (ok) |
144 | |
145 | \note If the \c Const template parameter is already \c false, this |
146 | constructor effectively defines a regular copy-constructor. |
147 | Otherwise, the copy constructor is implicitly defined. |
148 | */ |
149 | GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} |
150 | Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; } |
151 | |
152 | //! @name stepping |
153 | //@{ |
154 | Iterator& operator++(){ ++ptr_; return *this; } |
155 | Iterator& operator--(){ --ptr_; return *this; } |
156 | Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; } |
157 | Iterator operator--(int){ Iterator old(*this); --ptr_; return old; } |
158 | //@} |
159 | |
160 | //! @name increment/decrement |
161 | //@{ |
162 | Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); } |
163 | Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); } |
164 | |
165 | Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; } |
166 | Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; } |
167 | //@} |
168 | |
169 | //! @name relations |
170 | //@{ |
171 | bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; } |
172 | bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; } |
173 | bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; } |
174 | bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; } |
175 | bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; } |
176 | bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; } |
177 | //@} |
178 | |
179 | //! @name dereference |
180 | //@{ |
181 | Reference operator*() const { return *ptr_; } |
182 | Pointer operator->() const { return ptr_; } |
183 | Reference operator[](DifferenceType n) const { return ptr_[n]; } |
184 | //@} |
185 | |
186 | //! Distance |
187 | DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; } |
188 | |
189 | private: |
190 | //! Internal constructor from plain pointer |
191 | explicit GenericMemberIterator(Pointer p) : ptr_(p) {} |
192 | |
193 | Pointer ptr_; //!< raw pointer |
194 | }; |
195 | |
196 | #else // RAPIDJSON_NOMEMBERITERATORCLASS |
197 | |
198 | // class-based member iterator implementation disabled, use plain pointers |
199 | |
200 | template <bool Const, typename Encoding, typename Allocator> |
201 | struct GenericMemberIterator; |
202 | |
203 | //! non-const GenericMemberIterator |
204 | template <typename Encoding, typename Allocator> |
205 | struct GenericMemberIterator<false,Encoding,Allocator> { |
206 | //! use plain pointer as iterator type |
207 | typedef GenericMember<Encoding,Allocator>* Iterator; |
208 | }; |
209 | //! const GenericMemberIterator |
210 | template <typename Encoding, typename Allocator> |
211 | struct GenericMemberIterator<true,Encoding,Allocator> { |
212 | //! use plain const pointer as iterator type |
213 | typedef const GenericMember<Encoding,Allocator>* Iterator; |
214 | }; |
215 | |
216 | #endif // RAPIDJSON_NOMEMBERITERATORCLASS |
217 | |
218 | /////////////////////////////////////////////////////////////////////////////// |
219 | // GenericStringRef |
220 | |
221 | //! Reference to a constant string (not taking a copy) |
222 | /*! |
223 | \tparam CharType character type of the string |
224 | |
225 | This helper class is used to automatically infer constant string |
226 | references for string literals, especially from \c const \b (!) |
227 | character arrays. |
228 | |
229 | The main use is for creating JSON string values without copying the |
230 | source string via an \ref Allocator. This requires that the referenced |
231 | string pointers have a sufficient lifetime, which exceeds the lifetime |
232 | of the associated GenericValue. |
233 | |
234 | \b Example |
235 | \code |
236 | Value v("foo"); // ok, no need to copy & calculate length |
237 | const char foo[] = "foo"; |
238 | v.SetString(foo); // ok |
239 | |
240 | const char* bar = foo; |
241 | // Value x(bar); // not ok, can't rely on bar's lifetime |
242 | Value x(StringRef(bar)); // lifetime explicitly guaranteed by user |
243 | Value y(StringRef(bar, 3)); // ok, explicitly pass length |
244 | \endcode |
245 | |
246 | \see StringRef, GenericValue::SetString |
247 | */ |
248 | template<typename CharType> |
249 | struct GenericStringRef { |
250 | typedef CharType Ch; //!< character type of the string |
251 | |
252 | //! Create string reference from \c const character array |
253 | #ifndef __clang__ // -Wdocumentation |
254 | /*! |
255 | This constructor implicitly creates a constant string reference from |
256 | a \c const character array. It has better performance than |
257 | \ref StringRef(const CharType*) by inferring the string \ref length |
258 | from the array length, and also supports strings containing null |
259 | characters. |
260 | |
261 | \tparam N length of the string, automatically inferred |
262 | |
263 | \param str Constant character array, lifetime assumed to be longer |
264 | than the use of the string in e.g. a GenericValue |
265 | |
266 | \post \ref s == str |
267 | |
268 | \note Constant complexity. |
269 | \note There is a hidden, private overload to disallow references to |
270 | non-const character arrays to be created via this constructor. |
271 | By this, e.g. function-scope arrays used to be filled via |
272 | \c snprintf are excluded from consideration. |
273 | In such cases, the referenced string should be \b copied to the |
274 | GenericValue instead. |
275 | */ |
276 | #endif |
277 | template<SizeType N> |
278 | GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT |
279 | : s(str), length(N-1) {} |
280 | |
281 | //! Explicitly create string reference from \c const character pointer |
282 | #ifndef __clang__ // -Wdocumentation |
283 | /*! |
284 | This constructor can be used to \b explicitly create a reference to |
285 | a constant string pointer. |
286 | |
287 | \see StringRef(const CharType*) |
288 | |
289 | \param str Constant character pointer, lifetime assumed to be longer |
290 | than the use of the string in e.g. a GenericValue |
291 | |
292 | \post \ref s == str |
293 | |
294 | \note There is a hidden, private overload to disallow references to |
295 | non-const character arrays to be created via this constructor. |
296 | By this, e.g. function-scope arrays used to be filled via |
297 | \c snprintf are excluded from consideration. |
298 | In such cases, the referenced string should be \b copied to the |
299 | GenericValue instead. |
300 | */ |
301 | #endif |
302 | explicit GenericStringRef(const CharType* str) |
303 | : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != 0); } |
304 | |
305 | //! Create constant string reference from pointer and length |
306 | #ifndef __clang__ // -Wdocumentation |
307 | /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue |
308 | \param len length of the string, excluding the trailing NULL terminator |
309 | |
310 | \post \ref s == str && \ref length == len |
311 | \note Constant complexity. |
312 | */ |
313 | #endif |
314 | GenericStringRef(const CharType* str, SizeType len) |
315 | : s(str), length(len) { RAPIDJSON_ASSERT(s != 0); } |
316 | |
317 | GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {} |
318 | |
319 | GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; } |
320 | |
321 | //! implicit conversion to plain CharType pointer |
322 | operator const Ch *() const { return s; } |
323 | |
324 | const Ch* const s; //!< plain CharType pointer |
325 | const SizeType length; //!< length of the string (excluding the trailing NULL terminator) |
326 | |
327 | private: |
328 | //! Disallow construction from non-const array |
329 | template<SizeType N> |
330 | GenericStringRef(CharType (&str)[N]) /* = delete */; |
331 | }; |
332 | |
333 | //! Mark a character pointer as constant string |
334 | /*! Mark a plain character pointer as a "string literal". This function |
335 | can be used to avoid copying a character string to be referenced as a |
336 | value in a JSON GenericValue object, if the string's lifetime is known |
337 | to be valid long enough. |
338 | \tparam CharType Character type of the string |
339 | \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue |
340 | \return GenericStringRef string reference object |
341 | \relatesalso GenericStringRef |
342 | |
343 | \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember |
344 | */ |
345 | template<typename CharType> |
346 | inline GenericStringRef<CharType> StringRef(const CharType* str) { |
347 | return GenericStringRef<CharType>(str, internal::StrLen(str)); |
348 | } |
349 | |
350 | //! Mark a character pointer as constant string |
351 | /*! Mark a plain character pointer as a "string literal". This function |
352 | can be used to avoid copying a character string to be referenced as a |
353 | value in a JSON GenericValue object, if the string's lifetime is known |
354 | to be valid long enough. |
355 | |
356 | This version has better performance with supplied length, and also |
357 | supports string containing null characters. |
358 | |
359 | \tparam CharType character type of the string |
360 | \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue |
361 | \param length The length of source string. |
362 | \return GenericStringRef string reference object |
363 | \relatesalso GenericStringRef |
364 | */ |
365 | template<typename CharType> |
366 | inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) { |
367 | return GenericStringRef<CharType>(str, SizeType(length)); |
368 | } |
369 | |
370 | #if RAPIDJSON_HAS_STDSTRING |
371 | //! Mark a string object as constant string |
372 | /*! Mark a string object (e.g. \c std::string) as a "string literal". |
373 | This function can be used to avoid copying a string to be referenced as a |
374 | value in a JSON GenericValue object, if the string's lifetime is known |
375 | to be valid long enough. |
376 | |
377 | \tparam CharType character type of the string |
378 | \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue |
379 | \return GenericStringRef string reference object |
380 | \relatesalso GenericStringRef |
381 | \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. |
382 | */ |
383 | template<typename CharType> |
384 | inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) { |
385 | return GenericStringRef<CharType>(str.data(), SizeType(str.size())); |
386 | } |
387 | #endif |
388 | |
389 | /////////////////////////////////////////////////////////////////////////////// |
390 | // GenericValue type traits |
391 | namespace internal { |
392 | |
393 | template <typename T, typename Encoding = void, typename Allocator = void> |
394 | struct IsGenericValueImpl : FalseType {}; |
395 | |
396 | // select candidates according to nested encoding and allocator types |
397 | template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type> |
398 | : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {}; |
399 | |
400 | // helper to match arbitrary GenericValue instantiations, including derived classes |
401 | template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {}; |
402 | |
403 | } // namespace internal |
404 | |
405 | /////////////////////////////////////////////////////////////////////////////// |
406 | // TypeHelper |
407 | |
408 | namespace internal { |
409 | |
410 | template <typename ValueType, typename T> |
411 | struct TypeHelper {}; |
412 | |
413 | template<typename ValueType> |
414 | struct TypeHelper<ValueType, bool> { |
415 | static bool Is(const ValueType& v) { return v.IsBool(); } |
416 | static bool Get(const ValueType& v) { return v.GetBool(); } |
417 | static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); } |
418 | static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); } |
419 | }; |
420 | |
421 | template<typename ValueType> |
422 | struct TypeHelper<ValueType, int> { |
423 | static bool Is(const ValueType& v) { return v.IsInt(); } |
424 | static int Get(const ValueType& v) { return v.GetInt(); } |
425 | static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); } |
426 | static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); } |
427 | }; |
428 | |
429 | template<typename ValueType> |
430 | struct TypeHelper<ValueType, unsigned> { |
431 | static bool Is(const ValueType& v) { return v.IsUint(); } |
432 | static unsigned Get(const ValueType& v) { return v.GetUint(); } |
433 | static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); } |
434 | static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); } |
435 | }; |
436 | |
437 | template<typename ValueType> |
438 | struct TypeHelper<ValueType, int64_t> { |
439 | static bool Is(const ValueType& v) { return v.IsInt64(); } |
440 | static int64_t Get(const ValueType& v) { return v.GetInt64(); } |
441 | static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); } |
442 | static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); } |
443 | }; |
444 | |
445 | template<typename ValueType> |
446 | struct TypeHelper<ValueType, uint64_t> { |
447 | static bool Is(const ValueType& v) { return v.IsUint64(); } |
448 | static uint64_t Get(const ValueType& v) { return v.GetUint64(); } |
449 | static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); } |
450 | static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); } |
451 | }; |
452 | |
453 | template<typename ValueType> |
454 | struct TypeHelper<ValueType, double> { |
455 | static bool Is(const ValueType& v) { return v.IsDouble(); } |
456 | static double Get(const ValueType& v) { return v.GetDouble(); } |
457 | static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); } |
458 | static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); } |
459 | }; |
460 | |
461 | template<typename ValueType> |
462 | struct TypeHelper<ValueType, float> { |
463 | static bool Is(const ValueType& v) { return v.IsFloat(); } |
464 | static float Get(const ValueType& v) { return v.GetFloat(); } |
465 | static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); } |
466 | static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); } |
467 | }; |
468 | |
469 | template<typename ValueType> |
470 | struct TypeHelper<ValueType, const typename ValueType::Ch*> { |
471 | typedef const typename ValueType::Ch* StringType; |
472 | static bool Is(const ValueType& v) { return v.IsString(); } |
473 | static StringType Get(const ValueType& v) { return v.GetString(); } |
474 | static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); } |
475 | static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } |
476 | }; |
477 | |
478 | #if RAPIDJSON_HAS_STDSTRING |
479 | template<typename ValueType> |
480 | struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > { |
481 | typedef std::basic_string<typename ValueType::Ch> StringType; |
482 | static bool Is(const ValueType& v) { return v.IsString(); } |
483 | static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); } |
484 | static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } |
485 | }; |
486 | #endif |
487 | |
488 | template<typename ValueType> |
489 | struct TypeHelper<ValueType, typename ValueType::Array> { |
490 | typedef typename ValueType::Array ArrayType; |
491 | static bool Is(const ValueType& v) { return v.IsArray(); } |
492 | static ArrayType Get(ValueType& v) { return v.GetArray(); } |
493 | static ValueType& Set(ValueType& v, ArrayType data) { return v = data; } |
494 | static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; } |
495 | }; |
496 | |
497 | template<typename ValueType> |
498 | struct TypeHelper<ValueType, typename ValueType::ConstArray> { |
499 | typedef typename ValueType::ConstArray ArrayType; |
500 | static bool Is(const ValueType& v) { return v.IsArray(); } |
501 | static ArrayType Get(const ValueType& v) { return v.GetArray(); } |
502 | }; |
503 | |
504 | template<typename ValueType> |
505 | struct TypeHelper<ValueType, typename ValueType::Object> { |
506 | typedef typename ValueType::Object ObjectType; |
507 | static bool Is(const ValueType& v) { return v.IsObject(); } |
508 | static ObjectType Get(ValueType& v) { return v.GetObject(); } |
509 | static ValueType& Set(ValueType& v, ObjectType data) { return v = data; } |
510 | static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { v = data; } |
511 | }; |
512 | |
513 | template<typename ValueType> |
514 | struct TypeHelper<ValueType, typename ValueType::ConstObject> { |
515 | typedef typename ValueType::ConstObject ObjectType; |
516 | static bool Is(const ValueType& v) { return v.IsObject(); } |
517 | static ObjectType Get(const ValueType& v) { return v.GetObject(); } |
518 | }; |
519 | |
520 | } // namespace internal |
521 | |
522 | // Forward declarations |
523 | template <bool, typename> class GenericArray; |
524 | template <bool, typename> class GenericObject; |
525 | |
526 | /////////////////////////////////////////////////////////////////////////////// |
527 | // GenericValue |
528 | |
529 | //! Represents a JSON value. Use Value for UTF8 encoding and default allocator. |
530 | /*! |
531 | A JSON value can be one of 7 types. This class is a variant type supporting |
532 | these types. |
533 | |
534 | Use the Value if UTF8 and default allocator |
535 | |
536 | \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) |
537 | \tparam Allocator Allocator type for allocating memory of object, array and string. |
538 | */ |
539 | template <typename Encoding, typename Allocator = MemoryPoolAllocator<> > |
540 | class GenericValue { |
541 | public: |
542 | //! Name-value pair in an object. |
543 | typedef GenericMember<Encoding, Allocator> Member; |
544 | typedef Encoding EncodingType; //!< Encoding type from template parameter. |
545 | typedef Allocator AllocatorType; //!< Allocator type from template parameter. |
546 | typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. |
547 | typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string |
548 | typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object. |
549 | typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. |
550 | typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. |
551 | typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. |
552 | typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of itself. |
553 | typedef GenericArray<false, ValueType> Array; |
554 | typedef GenericArray<true, ValueType> ConstArray; |
555 | typedef GenericObject<false, ValueType> Object; |
556 | typedef GenericObject<true, ValueType> ConstObject; |
557 | |
558 | //!@name Constructors and destructor. |
559 | //@{ |
560 | |
561 | //! Default constructor creates a null value. |
562 | GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; } |
563 | |
564 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
565 | //! Move constructor in C++11 |
566 | GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) { |
567 | rhs.data_.f.flags = kNullFlag; // give up contents |
568 | } |
569 | #endif |
570 | |
571 | private: |
572 | //! Copy constructor is not permitted. |
573 | GenericValue(const GenericValue& rhs); |
574 | |
575 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
576 | //! Moving from a GenericDocument is not permitted. |
577 | template <typename StackAllocator> |
578 | GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs); |
579 | |
580 | //! Move assignment from a GenericDocument is not permitted. |
581 | template <typename StackAllocator> |
582 | GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs); |
583 | #endif |
584 | |
585 | public: |
586 | |
587 | //! Constructor with JSON value type. |
588 | /*! This creates a Value of specified type with default content. |
589 | \param type Type of the value. |
590 | \note Default content for number is zero. |
591 | */ |
592 | explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() { |
593 | static const uint16_t defaultFlags[7] = { |
594 | kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, |
595 | kNumberAnyFlag |
596 | }; |
597 | RAPIDJSON_ASSERT(type <= kNumberType); |
598 | data_.f.flags = defaultFlags[type]; |
599 | |
600 | // Use ShortString to store empty string. |
601 | if (type == kStringType) |
602 | data_.ss.SetLength(0); |
603 | } |
604 | |
605 | //! Explicit copy constructor (with allocator) |
606 | /*! Creates a copy of a Value by using the given Allocator |
607 | \tparam SourceAllocator allocator of \c rhs |
608 | \param rhs Value to copy from (read-only) |
609 | \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). |
610 | \see CopyFrom() |
611 | */ |
612 | template< typename SourceAllocator > |
613 | GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator); |
614 | |
615 | //! Constructor for boolean value. |
616 | /*! \param b Boolean value |
617 | \note This constructor is limited to \em real boolean values and rejects |
618 | implicitly converted types like arbitrary pointers. Use an explicit cast |
619 | to \c bool, if you want to construct a boolean JSON value in such cases. |
620 | */ |
621 | #ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen |
622 | template <typename T> |
623 | explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<bool, T>))) RAPIDJSON_NOEXCEPT // See #472 |
624 | #else |
625 | explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT |
626 | #endif |
627 | : data_() { |
628 | // safe-guard against failing SFINAE |
629 | RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value)); |
630 | data_.f.flags = b ? kTrueFlag : kFalseFlag; |
631 | } |
632 | |
633 | //! Constructor for int value. |
634 | explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() { |
635 | data_.n.i64 = i; |
636 | data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag; |
637 | } |
638 | |
639 | //! Constructor for unsigned value. |
640 | explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() { |
641 | data_.n.u64 = u; |
642 | data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag); |
643 | } |
644 | |
645 | //! Constructor for int64_t value. |
646 | explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() { |
647 | data_.n.i64 = i64; |
648 | data_.f.flags = kNumberInt64Flag; |
649 | if (i64 >= 0) { |
650 | data_.f.flags |= kNumberUint64Flag; |
651 | if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) |
652 | data_.f.flags |= kUintFlag; |
653 | if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) |
654 | data_.f.flags |= kIntFlag; |
655 | } |
656 | else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) |
657 | data_.f.flags |= kIntFlag; |
658 | } |
659 | |
660 | //! Constructor for uint64_t value. |
661 | explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() { |
662 | data_.n.u64 = u64; |
663 | data_.f.flags = kNumberUint64Flag; |
664 | if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) |
665 | data_.f.flags |= kInt64Flag; |
666 | if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) |
667 | data_.f.flags |= kUintFlag; |
668 | if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) |
669 | data_.f.flags |= kIntFlag; |
670 | } |
671 | |
672 | //! Constructor for double value. |
673 | explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; } |
674 | |
675 | //! Constructor for constant string (i.e. do not make a copy of string) |
676 | GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); } |
677 | |
678 | //! Constructor for constant string (i.e. do not make a copy of string) |
679 | explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); } |
680 | |
681 | //! Constructor for copy-string (i.e. do make a copy of string) |
682 | GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); } |
683 | |
684 | //! Constructor for copy-string (i.e. do make a copy of string) |
685 | GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } |
686 | |
687 | #if RAPIDJSON_HAS_STDSTRING |
688 | //! Constructor for copy-string from a string object (i.e. do make a copy of string) |
689 | /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. |
690 | */ |
691 | GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } |
692 | #endif |
693 | |
694 | //! Constructor for Array. |
695 | /*! |
696 | \param a An array obtained by \c GetArray(). |
697 | \note \c Array is always pass-by-value. |
698 | \note the source array is moved into this value and the sourec array becomes empty. |
699 | */ |
700 | GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) { |
701 | a.value_.data_ = Data(); |
702 | a.value_.data_.f.flags = kArrayFlag; |
703 | } |
704 | |
705 | //! Constructor for Object. |
706 | /*! |
707 | \param o An object obtained by \c GetObject(). |
708 | \note \c Object is always pass-by-value. |
709 | \note the source object is moved into this value and the sourec object becomes empty. |
710 | */ |
711 | GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) { |
712 | o.value_.data_ = Data(); |
713 | o.value_.data_.f.flags = kObjectFlag; |
714 | } |
715 | |
716 | //! Destructor. |
717 | /*! Need to destruct elements of array, members of object, or copy-string. |
718 | */ |
719 | ~GenericValue() { |
720 | if (Allocator::kNeedFree) { // Shortcut by Allocator's trait |
721 | switch(data_.f.flags) { |
722 | case kArrayFlag: |
723 | { |
724 | GenericValue* e = GetElementsPointer(); |
725 | for (GenericValue* v = e; v != e + data_.a.size; ++v) |
726 | v->~GenericValue(); |
727 | Allocator::Free(e); |
728 | } |
729 | break; |
730 | |
731 | case kObjectFlag: |
732 | for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) |
733 | m->~Member(); |
734 | Allocator::Free(GetMembersPointer()); |
735 | break; |
736 | |
737 | case kCopyStringFlag: |
738 | Allocator::Free(const_cast<Ch*>(GetStringPointer())); |
739 | break; |
740 | |
741 | default: |
742 | break; // Do nothing for other types. |
743 | } |
744 | } |
745 | } |
746 | |
747 | //@} |
748 | |
749 | //!@name Assignment operators |
750 | //@{ |
751 | |
752 | //! Assignment with move semantics. |
753 | /*! \param rhs Source of the assignment. It will become a null value after assignment. |
754 | */ |
755 | GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT { |
756 | RAPIDJSON_ASSERT(this != &rhs); |
757 | this->~GenericValue(); |
758 | RawAssign(rhs); |
759 | return *this; |
760 | } |
761 | |
762 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
763 | //! Move assignment in C++11 |
764 | GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT { |
765 | return *this = rhs.Move(); |
766 | } |
767 | #endif |
768 | |
769 | //! Assignment of constant string reference (no copy) |
770 | /*! \param str Constant string reference to be assigned |
771 | \note This overload is needed to avoid clashes with the generic primitive type assignment overload below. |
772 | \see GenericStringRef, operator=(T) |
773 | */ |
774 | GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT { |
775 | GenericValue s(str); |
776 | return *this = s; |
777 | } |
778 | |
779 | //! Assignment with primitive types. |
780 | /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t |
781 | \param value The value to be assigned. |
782 | |
783 | \note The source type \c T explicitly disallows all pointer types, |
784 | especially (\c const) \ref Ch*. This helps avoiding implicitly |
785 | referencing character strings with insufficient lifetime, use |
786 | \ref SetString(const Ch*, Allocator&) (for copying) or |
787 | \ref StringRef() (to explicitly mark the pointer as constant) instead. |
788 | All other pointer types would implicitly convert to \c bool, |
789 | use \ref SetBool() instead. |
790 | */ |
791 | template <typename T> |
792 | RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&)) |
793 | operator=(T value) { |
794 | GenericValue v(value); |
795 | return *this = v; |
796 | } |
797 | |
798 | //! Deep-copy assignment from Value |
799 | /*! Assigns a \b copy of the Value to the current Value object |
800 | \tparam SourceAllocator Allocator type of \c rhs |
801 | \param rhs Value to copy from (read-only) |
802 | \param allocator Allocator to use for copying |
803 | */ |
804 | template <typename SourceAllocator> |
805 | GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) { |
806 | RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs)); |
807 | this->~GenericValue(); |
808 | new (this) GenericValue(rhs, allocator); |
809 | return *this; |
810 | } |
811 | |
812 | //! Exchange the contents of this value with those of other. |
813 | /*! |
814 | \param other Another value. |
815 | \note Constant complexity. |
816 | */ |
817 | GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT { |
818 | GenericValue temp; |
819 | temp.RawAssign(*this); |
820 | RawAssign(other); |
821 | other.RawAssign(temp); |
822 | return *this; |
823 | } |
824 | |
825 | //! free-standing swap function helper |
826 | /*! |
827 | Helper function to enable support for common swap implementation pattern based on \c std::swap: |
828 | \code |
829 | void swap(MyClass& a, MyClass& b) { |
830 | using std::swap; |
831 | swap(a.value, b.value); |
832 | // ... |
833 | } |
834 | \endcode |
835 | \see Swap() |
836 | */ |
837 | friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } |
838 | |
839 | //! Prepare Value for move semantics |
840 | /*! \return *this */ |
841 | GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } |
842 | //@} |
843 | |
844 | //!@name Equal-to and not-equal-to operators |
845 | //@{ |
846 | //! Equal-to operator |
847 | /*! |
848 | \note If an object contains duplicated named member, comparing equality with any object is always \c false. |
849 | \note Linear time complexity (number of all values in the subtree and total lengths of all strings). |
850 | */ |
851 | template <typename SourceAllocator> |
852 | bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const { |
853 | typedef GenericValue<Encoding, SourceAllocator> RhsType; |
854 | if (GetType() != rhs.GetType()) |
855 | return false; |
856 | |
857 | switch (GetType()) { |
858 | case kObjectType: // Warning: O(n^2) inner-loop |
859 | if (data_.o.size != rhs.data_.o.size) |
860 | return false; |
861 | for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) { |
862 | typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name); |
863 | if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value) |
864 | return false; |
865 | } |
866 | return true; |
867 | |
868 | case kArrayType: |
869 | if (data_.a.size != rhs.data_.a.size) |
870 | return false; |
871 | for (SizeType i = 0; i < data_.a.size; i++) |
872 | if ((*this)[i] != rhs[i]) |
873 | return false; |
874 | return true; |
875 | |
876 | case kStringType: |
877 | return StringEqual(rhs); |
878 | |
879 | case kNumberType: |
880 | if (IsDouble() || rhs.IsDouble()) { |
881 | double a = GetDouble(); // May convert from integer to double. |
882 | double b = rhs.GetDouble(); // Ditto |
883 | return a >= b && a <= b; // Prevent -Wfloat-equal |
884 | } |
885 | else |
886 | return data_.n.u64 == rhs.data_.n.u64; |
887 | |
888 | default: |
889 | return true; |
890 | } |
891 | } |
892 | |
893 | //! Equal-to operator with const C-string pointer |
894 | bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); } |
895 | |
896 | #if RAPIDJSON_HAS_STDSTRING |
897 | //! Equal-to operator with string object |
898 | /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. |
899 | */ |
900 | bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); } |
901 | #endif |
902 | |
903 | //! Equal-to operator with primitive types |
904 | /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false |
905 | */ |
906 | template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } |
907 | |
908 | //! Not-equal-to operator |
909 | /*! \return !(*this == rhs) |
910 | */ |
911 | template <typename SourceAllocator> |
912 | bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); } |
913 | |
914 | //! Not-equal-to operator with const C-string pointer |
915 | bool operator!=(const Ch* rhs) const { return !(*this == rhs); } |
916 | |
917 | //! Not-equal-to operator with arbitrary types |
918 | /*! \return !(*this == rhs) |
919 | */ |
920 | template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } |
921 | |
922 | //! Equal-to operator with arbitrary types (symmetric version) |
923 | /*! \return (rhs == lhs) |
924 | */ |
925 | template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; } |
926 | |
927 | //! Not-Equal-to operator with arbitrary types (symmetric version) |
928 | /*! \return !(rhs == lhs) |
929 | */ |
930 | template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } |
931 | //@} |
932 | |
933 | //!@name Type |
934 | //@{ |
935 | |
936 | Type GetType() const { return static_cast<Type>(data_.f.flags & kTypeMask); } |
937 | bool IsNull() const { return data_.f.flags == kNullFlag; } |
938 | bool IsFalse() const { return data_.f.flags == kFalseFlag; } |
939 | bool IsTrue() const { return data_.f.flags == kTrueFlag; } |
940 | bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; } |
941 | bool IsObject() const { return data_.f.flags == kObjectFlag; } |
942 | bool IsArray() const { return data_.f.flags == kArrayFlag; } |
943 | bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; } |
944 | bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; } |
945 | bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; } |
946 | bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; } |
947 | bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; } |
948 | bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; } |
949 | bool IsString() const { return (data_.f.flags & kStringFlag) != 0; } |
950 | |
951 | // Checks whether a number can be losslessly converted to a double. |
952 | bool IsLosslessDouble() const { |
953 | if (!IsNumber()) return false; |
954 | if (IsUint64()) { |
955 | uint64_t u = GetUint64(); |
956 | volatile double d = static_cast<double>(u); |
957 | return (d >= 0.0) |
958 | && (d < static_cast<double>(std::numeric_limits<uint64_t>::max())) |
959 | && (u == static_cast<uint64_t>(d)); |
960 | } |
961 | if (IsInt64()) { |
962 | int64_t i = GetInt64(); |
963 | volatile double d = static_cast<double>(i); |
964 | return (d >= static_cast<double>(std::numeric_limits<int64_t>::min())) |
965 | && (d < static_cast<double>(std::numeric_limits<int64_t>::max())) |
966 | && (i == static_cast<int64_t>(d)); |
967 | } |
968 | return true; // double, int, uint are always lossless |
969 | } |
970 | |
971 | // Checks whether a number is a float (possible lossy). |
972 | bool IsFloat() const { |
973 | if ((data_.f.flags & kDoubleFlag) == 0) |
974 | return false; |
975 | double d = GetDouble(); |
976 | return d >= -3.4028234e38 && d <= 3.4028234e38; |
977 | } |
978 | // Checks whether a number can be losslessly converted to a float. |
979 | bool IsLosslessFloat() const { |
980 | if (!IsNumber()) return false; |
981 | double a = GetDouble(); |
982 | if (a < static_cast<double>(-std::numeric_limits<float>::max()) |
983 | || a > static_cast<double>(std::numeric_limits<float>::max())) |
984 | return false; |
985 | double b = static_cast<double>(static_cast<float>(a)); |
986 | return a >= b && a <= b; // Prevent -Wfloat-equal |
987 | } |
988 | |
989 | //@} |
990 | |
991 | //!@name Null |
992 | //@{ |
993 | |
994 | GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } |
995 | |
996 | //@} |
997 | |
998 | //!@name Bool |
999 | //@{ |
1000 | |
1001 | bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; } |
1002 | //!< Set boolean value |
1003 | /*! \post IsBool() == true */ |
1004 | GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } |
1005 | |
1006 | //@} |
1007 | |
1008 | //!@name Object |
1009 | //@{ |
1010 | |
1011 | //! Set this value as an empty object. |
1012 | /*! \post IsObject() == true */ |
1013 | GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } |
1014 | |
1015 | //! Get the number of members in the object. |
1016 | SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } |
1017 | |
1018 | //! Check whether the object is empty. |
1019 | bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } |
1020 | |
1021 | //! Get a value from an object associated with the name. |
1022 | /*! \pre IsObject() == true |
1023 | \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType)) |
1024 | \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. |
1025 | Since 0.2, if the name is not correct, it will assert. |
1026 | If user is unsure whether a member exists, user should use HasMember() first. |
1027 | A better approach is to use FindMember(). |
1028 | \note Linear time complexity. |
1029 | */ |
1030 | template <typename T> |
1031 | RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) { |
1032 | GenericValue n(StringRef(name)); |
1033 | return (*this)[n]; |
1034 | } |
1035 | template <typename T> |
1036 | RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; } |
1037 | |
1038 | //! Get a value from an object associated with the name. |
1039 | /*! \pre IsObject() == true |
1040 | \tparam SourceAllocator Allocator of the \c name value |
1041 | |
1042 | \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen(). |
1043 | And it can also handle strings with embedded null characters. |
1044 | |
1045 | \note Linear time complexity. |
1046 | */ |
1047 | template <typename SourceAllocator> |
1048 | GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) { |
1049 | MemberIterator member = FindMember(name); |
1050 | if (member != MemberEnd()) |
1051 | return member->value; |
1052 | else { |
1053 | RAPIDJSON_ASSERT(false); // see above note |
1054 | |
1055 | // This will generate -Wexit-time-destructors in clang |
1056 | // static GenericValue NullValue; |
1057 | // return NullValue; |
1058 | |
1059 | // Use static buffer and placement-new to prevent destruction |
1060 | static char buffer[sizeof(GenericValue)]; |
1061 | return *new (buffer) GenericValue(); |
1062 | } |
1063 | } |
1064 | template <typename SourceAllocator> |
1065 | const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; } |
1066 | |
1067 | #if RAPIDJSON_HAS_STDSTRING |
1068 | //! Get a value from an object associated with name (string object). |
1069 | GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; } |
1070 | const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; } |
1071 | #endif |
1072 | |
1073 | //! Const member iterator |
1074 | /*! \pre IsObject() == true */ |
1075 | ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); } |
1076 | //! Const \em past-the-end member iterator |
1077 | /*! \pre IsObject() == true */ |
1078 | ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); } |
1079 | //! Member iterator |
1080 | /*! \pre IsObject() == true */ |
1081 | MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); } |
1082 | //! \em Past-the-end member iterator |
1083 | /*! \pre IsObject() == true */ |
1084 | MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); } |
1085 | |
1086 | //! Check whether a member exists in the object. |
1087 | /*! |
1088 | \param name Member name to be searched. |
1089 | \pre IsObject() == true |
1090 | \return Whether a member with that name exists. |
1091 | \note It is better to use FindMember() directly if you need the obtain the value as well. |
1092 | \note Linear time complexity. |
1093 | */ |
1094 | bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); } |
1095 | |
1096 | #if RAPIDJSON_HAS_STDSTRING |
1097 | //! Check whether a member exists in the object with string object. |
1098 | /*! |
1099 | \param name Member name to be searched. |
1100 | \pre IsObject() == true |
1101 | \return Whether a member with that name exists. |
1102 | \note It is better to use FindMember() directly if you need the obtain the value as well. |
1103 | \note Linear time complexity. |
1104 | */ |
1105 | bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); } |
1106 | #endif |
1107 | |
1108 | //! Check whether a member exists in the object with GenericValue name. |
1109 | /*! |
1110 | This version is faster because it does not need a StrLen(). It can also handle string with null character. |
1111 | \param name Member name to be searched. |
1112 | \pre IsObject() == true |
1113 | \return Whether a member with that name exists. |
1114 | \note It is better to use FindMember() directly if you need the obtain the value as well. |
1115 | \note Linear time complexity. |
1116 | */ |
1117 | template <typename SourceAllocator> |
1118 | bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); } |
1119 | |
1120 | //! Find member by name. |
1121 | /*! |
1122 | \param name Member name to be searched. |
1123 | \pre IsObject() == true |
1124 | \return Iterator to member, if it exists. |
1125 | Otherwise returns \ref MemberEnd(). |
1126 | |
1127 | \note Earlier versions of Rapidjson returned a \c NULL pointer, in case |
1128 | the requested member doesn't exist. For consistency with e.g. |
1129 | \c std::map, this has been changed to MemberEnd() now. |
1130 | \note Linear time complexity. |
1131 | */ |
1132 | MemberIterator FindMember(const Ch* name) { |
1133 | GenericValue n(StringRef(name)); |
1134 | return FindMember(n); |
1135 | } |
1136 | |
1137 | ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); } |
1138 | |
1139 | //! Find member by name. |
1140 | /*! |
1141 | This version is faster because it does not need a StrLen(). It can also handle string with null character. |
1142 | \param name Member name to be searched. |
1143 | \pre IsObject() == true |
1144 | \return Iterator to member, if it exists. |
1145 | Otherwise returns \ref MemberEnd(). |
1146 | |
1147 | \note Earlier versions of Rapidjson returned a \c NULL pointer, in case |
1148 | the requested member doesn't exist. For consistency with e.g. |
1149 | \c std::map, this has been changed to MemberEnd() now. |
1150 | \note Linear time complexity. |
1151 | */ |
1152 | template <typename SourceAllocator> |
1153 | MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) { |
1154 | RAPIDJSON_ASSERT(IsObject()); |
1155 | RAPIDJSON_ASSERT(name.IsString()); |
1156 | MemberIterator member = MemberBegin(); |
1157 | for ( ; member != MemberEnd(); ++member) |
1158 | if (name.StringEqual(member->name)) |
1159 | break; |
1160 | return member; |
1161 | } |
1162 | template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); } |
1163 | |
1164 | #if RAPIDJSON_HAS_STDSTRING |
1165 | //! Find member by string object name. |
1166 | /*! |
1167 | \param name Member name to be searched. |
1168 | \pre IsObject() == true |
1169 | \return Iterator to member, if it exists. |
1170 | Otherwise returns \ref MemberEnd(). |
1171 | */ |
1172 | MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(GenericValue(StringRef(name))); } |
1173 | ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(GenericValue(StringRef(name))); } |
1174 | #endif |
1175 | |
1176 | //! Add a member (name-value pair) to the object. |
1177 | /*! \param name A string value as name of member. |
1178 | \param value Value of any type. |
1179 | \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). |
1180 | \return The value itself for fluent API. |
1181 | \note The ownership of \c name and \c value will be transferred to this object on success. |
1182 | \pre IsObject() && name.IsString() |
1183 | \post name.IsNull() && value.IsNull() |
1184 | \note Amortized Constant time complexity. |
1185 | */ |
1186 | GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { |
1187 | RAPIDJSON_ASSERT(IsObject()); |
1188 | RAPIDJSON_ASSERT(name.IsString()); |
1189 | |
1190 | ObjectData& o = data_.o; |
1191 | if (o.size >= o.capacity) { |
1192 | if (o.capacity == 0) { |
1193 | o.capacity = kDefaultObjectCapacity; |
1194 | SetMembersPointer(reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member)))); |
1195 | } |
1196 | else { |
1197 | SizeType oldCapacity = o.capacity; |
1198 | o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5 |
1199 | SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member)))); |
1200 | } |
1201 | } |
1202 | Member* members = GetMembersPointer(); |
1203 | members[o.size].name.RawAssign(name); |
1204 | members[o.size].value.RawAssign(value); |
1205 | o.size++; |
1206 | return *this; |
1207 | } |
1208 | |
1209 | //! Add a constant string value as member (name-value pair) to the object. |
1210 | /*! \param name A string value as name of member. |
1211 | \param value constant string reference as value of member. |
1212 | \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). |
1213 | \return The value itself for fluent API. |
1214 | \pre IsObject() |
1215 | \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. |
1216 | \note Amortized Constant time complexity. |
1217 | */ |
1218 | GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) { |
1219 | GenericValue v(value); |
1220 | return AddMember(name, v, allocator); |
1221 | } |
1222 | |
1223 | #if RAPIDJSON_HAS_STDSTRING |
1224 | //! Add a string object as member (name-value pair) to the object. |
1225 | /*! \param name A string value as name of member. |
1226 | \param value constant string reference as value of member. |
1227 | \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). |
1228 | \return The value itself for fluent API. |
1229 | \pre IsObject() |
1230 | \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. |
1231 | \note Amortized Constant time complexity. |
1232 | */ |
1233 | GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) { |
1234 | GenericValue v(value, allocator); |
1235 | return AddMember(name, v, allocator); |
1236 | } |
1237 | #endif |
1238 | |
1239 | //! Add any primitive value as member (name-value pair) to the object. |
1240 | /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t |
1241 | \param name A string value as name of member. |
1242 | \param value Value of primitive type \c T as value of member |
1243 | \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). |
1244 | \return The value itself for fluent API. |
1245 | \pre IsObject() |
1246 | |
1247 | \note The source type \c T explicitly disallows all pointer types, |
1248 | especially (\c const) \ref Ch*. This helps avoiding implicitly |
1249 | referencing character strings with insufficient lifetime, use |
1250 | \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref |
1251 | AddMember(StringRefType, StringRefType, Allocator&). |
1252 | All other pointer types would implicitly convert to \c bool, |
1253 | use an explicit cast instead, if needed. |
1254 | \note Amortized Constant time complexity. |
1255 | */ |
1256 | template <typename T> |
1257 | RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&)) |
1258 | AddMember(GenericValue& name, T value, Allocator& allocator) { |
1259 | GenericValue v(value); |
1260 | return AddMember(name, v, allocator); |
1261 | } |
1262 | |
1263 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
1264 | GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) { |
1265 | return AddMember(name, value, allocator); |
1266 | } |
1267 | GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) { |
1268 | return AddMember(name, value, allocator); |
1269 | } |
1270 | GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) { |
1271 | return AddMember(name, value, allocator); |
1272 | } |
1273 | GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) { |
1274 | GenericValue n(name); |
1275 | return AddMember(n, value, allocator); |
1276 | } |
1277 | #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS |
1278 | |
1279 | |
1280 | //! Add a member (name-value pair) to the object. |
1281 | /*! \param name A constant string reference as name of member. |
1282 | \param value Value of any type. |
1283 | \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). |
1284 | \return The value itself for fluent API. |
1285 | \note The ownership of \c value will be transferred to this object on success. |
1286 | \pre IsObject() |
1287 | \post value.IsNull() |
1288 | \note Amortized Constant time complexity. |
1289 | */ |
1290 | GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) { |
1291 | GenericValue n(name); |
1292 | return AddMember(n, value, allocator); |
1293 | } |
1294 | |
1295 | //! Add a constant string value as member (name-value pair) to the object. |
1296 | /*! \param name A constant string reference as name of member. |
1297 | \param value constant string reference as value of member. |
1298 | \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). |
1299 | \return The value itself for fluent API. |
1300 | \pre IsObject() |
1301 | \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below. |
1302 | \note Amortized Constant time complexity. |
1303 | */ |
1304 | GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) { |
1305 | GenericValue v(value); |
1306 | return AddMember(name, v, allocator); |
1307 | } |
1308 | |
1309 | //! Add any primitive value as member (name-value pair) to the object. |
1310 | /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t |
1311 | \param name A constant string reference as name of member. |
1312 | \param value Value of primitive type \c T as value of member |
1313 | \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). |
1314 | \return The value itself for fluent API. |
1315 | \pre IsObject() |
1316 | |
1317 | \note The source type \c T explicitly disallows all pointer types, |
1318 | especially (\c const) \ref Ch*. This helps avoiding implicitly |
1319 | referencing character strings with insufficient lifetime, use |
1320 | \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref |
1321 | AddMember(StringRefType, StringRefType, Allocator&). |
1322 | All other pointer types would implicitly convert to \c bool, |
1323 | use an explicit cast instead, if needed. |
1324 | \note Amortized Constant time complexity. |
1325 | */ |
1326 | template <typename T> |
1327 | RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&)) |
1328 | AddMember(StringRefType name, T value, Allocator& allocator) { |
1329 | GenericValue n(name); |
1330 | return AddMember(n, value, allocator); |
1331 | } |
1332 | |
1333 | //! Remove all members in the object. |
1334 | /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged. |
1335 | \note Linear time complexity. |
1336 | */ |
1337 | void RemoveAllMembers() { |
1338 | RAPIDJSON_ASSERT(IsObject()); |
1339 | for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) |
1340 | m->~Member(); |
1341 | data_.o.size = 0; |
1342 | } |
1343 | |
1344 | //! Remove a member in object by its name. |
1345 | /*! \param name Name of member to be removed. |
1346 | \return Whether the member existed. |
1347 | \note This function may reorder the object members. Use \ref |
1348 | EraseMember(ConstMemberIterator) if you need to preserve the |
1349 | relative order of the remaining members. |
1350 | \note Linear time complexity. |
1351 | */ |
1352 | bool RemoveMember(const Ch* name) { |
1353 | GenericValue n(StringRef(name)); |
1354 | return RemoveMember(n); |
1355 | } |
1356 | |
1357 | #if RAPIDJSON_HAS_STDSTRING |
1358 | bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); } |
1359 | #endif |
1360 | |
1361 | template <typename SourceAllocator> |
1362 | bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) { |
1363 | MemberIterator m = FindMember(name); |
1364 | if (m != MemberEnd()) { |
1365 | RemoveMember(m); |
1366 | return true; |
1367 | } |
1368 | else |
1369 | return false; |
1370 | } |
1371 | |
1372 | //! Remove a member in object by iterator. |
1373 | /*! \param m member iterator (obtained by FindMember() or MemberBegin()). |
1374 | \return the new iterator after removal. |
1375 | \note This function may reorder the object members. Use \ref |
1376 | EraseMember(ConstMemberIterator) if you need to preserve the |
1377 | relative order of the remaining members. |
1378 | \note Constant time complexity. |
1379 | */ |
1380 | MemberIterator RemoveMember(MemberIterator m) { |
1381 | RAPIDJSON_ASSERT(IsObject()); |
1382 | RAPIDJSON_ASSERT(data_.o.size > 0); |
1383 | RAPIDJSON_ASSERT(GetMembersPointer() != 0); |
1384 | RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); |
1385 | |
1386 | MemberIterator last(GetMembersPointer() + (data_.o.size - 1)); |
1387 | if (data_.o.size > 1 && m != last) |
1388 | *m = *last; // Move the last one to this place |
1389 | else |
1390 | m->~Member(); // Only one left, just destroy |
1391 | --data_.o.size; |
1392 | return m; |
1393 | } |
1394 | |
1395 | //! Remove a member from an object by iterator. |
1396 | /*! \param pos iterator to the member to remove |
1397 | \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd() |
1398 | \return Iterator following the removed element. |
1399 | If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned. |
1400 | \note This function preserves the relative order of the remaining object |
1401 | members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator). |
1402 | \note Linear time complexity. |
1403 | */ |
1404 | MemberIterator EraseMember(ConstMemberIterator pos) { |
1405 | return EraseMember(pos, pos +1); |
1406 | } |
1407 | |
1408 | //! Remove members in the range [first, last) from an object. |
1409 | /*! \param first iterator to the first member to remove |
1410 | \param last iterator following the last member to remove |
1411 | \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd() |
1412 | \return Iterator following the last removed element. |
1413 | \note This function preserves the relative order of the remaining object |
1414 | members. |
1415 | \note Linear time complexity. |
1416 | */ |
1417 | MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) { |
1418 | RAPIDJSON_ASSERT(IsObject()); |
1419 | RAPIDJSON_ASSERT(data_.o.size > 0); |
1420 | RAPIDJSON_ASSERT(GetMembersPointer() != 0); |
1421 | RAPIDJSON_ASSERT(first >= MemberBegin()); |
1422 | RAPIDJSON_ASSERT(first <= last); |
1423 | RAPIDJSON_ASSERT(last <= MemberEnd()); |
1424 | |
1425 | MemberIterator pos = MemberBegin() + (first - MemberBegin()); |
1426 | for (MemberIterator itr = pos; itr != last; ++itr) |
1427 | itr->~Member(); |
1428 | std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member)); |
1429 | data_.o.size -= static_cast<SizeType>(last - first); |
1430 | return pos; |
1431 | } |
1432 | |
1433 | //! Erase a member in object by its name. |
1434 | /*! \param name Name of member to be removed. |
1435 | \return Whether the member existed. |
1436 | \note Linear time complexity. |
1437 | */ |
1438 | bool EraseMember(const Ch* name) { |
1439 | GenericValue n(StringRef(name)); |
1440 | return EraseMember(n); |
1441 | } |
1442 | |
1443 | #if RAPIDJSON_HAS_STDSTRING |
1444 | bool EraseMember(const std::basic_string<Ch>& name) { return EraseMember(GenericValue(StringRef(name))); } |
1445 | #endif |
1446 | |
1447 | template <typename SourceAllocator> |
1448 | bool EraseMember(const GenericValue<Encoding, SourceAllocator>& name) { |
1449 | MemberIterator m = FindMember(name); |
1450 | if (m != MemberEnd()) { |
1451 | EraseMember(m); |
1452 | return true; |
1453 | } |
1454 | else |
1455 | return false; |
1456 | } |
1457 | |
1458 | Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } |
1459 | ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } |
1460 | |
1461 | //@} |
1462 | |
1463 | //!@name Array |
1464 | //@{ |
1465 | |
1466 | //! Set this value as an empty array. |
1467 | /*! \post IsArray == true */ |
1468 | GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } |
1469 | |
1470 | //! Get the number of elements in array. |
1471 | SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } |
1472 | |
1473 | //! Get the capacity of array. |
1474 | SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } |
1475 | |
1476 | //! Check whether the array is empty. |
1477 | bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } |
1478 | |
1479 | //! Remove all elements in the array. |
1480 | /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. |
1481 | \note Linear time complexity. |
1482 | */ |
1483 | void Clear() { |
1484 | RAPIDJSON_ASSERT(IsArray()); |
1485 | GenericValue* e = GetElementsPointer(); |
1486 | for (GenericValue* v = e; v != e + data_.a.size; ++v) |
1487 | v->~GenericValue(); |
1488 | data_.a.size = 0; |
1489 | } |
1490 | |
1491 | //! Get an element from array by index. |
1492 | /*! \pre IsArray() == true |
1493 | \param index Zero-based index of element. |
1494 | \see operator[](T*) |
1495 | */ |
1496 | GenericValue& operator[](SizeType index) { |
1497 | RAPIDJSON_ASSERT(IsArray()); |
1498 | RAPIDJSON_ASSERT(index < data_.a.size); |
1499 | return GetElementsPointer()[index]; |
1500 | } |
1501 | const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; } |
1502 | |
1503 | //! Element iterator |
1504 | /*! \pre IsArray() == true */ |
1505 | ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); } |
1506 | //! \em Past-the-end element iterator |
1507 | /*! \pre IsArray() == true */ |
1508 | ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; } |
1509 | //! Constant element iterator |
1510 | /*! \pre IsArray() == true */ |
1511 | ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); } |
1512 | //! Constant \em past-the-end element iterator |
1513 | /*! \pre IsArray() == true */ |
1514 | ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); } |
1515 | |
1516 | //! Request the array to have enough capacity to store elements. |
1517 | /*! \param newCapacity The capacity that the array at least need to have. |
1518 | \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). |
1519 | \return The value itself for fluent API. |
1520 | \note Linear time complexity. |
1521 | */ |
1522 | GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { |
1523 | RAPIDJSON_ASSERT(IsArray()); |
1524 | if (newCapacity > data_.a.capacity) { |
1525 | SetElementsPointer(reinterpret_cast<GenericValue*>(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)))); |
1526 | data_.a.capacity = newCapacity; |
1527 | } |
1528 | return *this; |
1529 | } |
1530 | |
1531 | //! Append a GenericValue at the end of the array. |
1532 | /*! \param value Value to be appended. |
1533 | \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). |
1534 | \pre IsArray() == true |
1535 | \post value.IsNull() == true |
1536 | \return The value itself for fluent API. |
1537 | \note The ownership of \c value will be transferred to this array on success. |
1538 | \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. |
1539 | \note Amortized constant time complexity. |
1540 | */ |
1541 | GenericValue& PushBack(GenericValue& value, Allocator& allocator) { |
1542 | RAPIDJSON_ASSERT(IsArray()); |
1543 | if (data_.a.size >= data_.a.capacity) |
1544 | Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator); |
1545 | GetElementsPointer()[data_.a.size++].RawAssign(value); |
1546 | return *this; |
1547 | } |
1548 | |
1549 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
1550 | GenericValue& PushBack(GenericValue&& value, Allocator& allocator) { |
1551 | return PushBack(value, allocator); |
1552 | } |
1553 | #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS |
1554 | |
1555 | //! Append a constant string reference at the end of the array. |
1556 | /*! \param value Constant string reference to be appended. |
1557 | \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator(). |
1558 | \pre IsArray() == true |
1559 | \return The value itself for fluent API. |
1560 | \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. |
1561 | \note Amortized constant time complexity. |
1562 | \see GenericStringRef |
1563 | */ |
1564 | GenericValue& PushBack(StringRefType value, Allocator& allocator) { |
1565 | return (*this).template PushBack<StringRefType>(value, allocator); |
1566 | } |
1567 | |
1568 | //! Append a primitive value at the end of the array. |
1569 | /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t |
1570 | \param value Value of primitive type T to be appended. |
1571 | \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). |
1572 | \pre IsArray() == true |
1573 | \return The value itself for fluent API. |
1574 | \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. |
1575 | |
1576 | \note The source type \c T explicitly disallows all pointer types, |
1577 | especially (\c const) \ref Ch*. This helps avoiding implicitly |
1578 | referencing character strings with insufficient lifetime, use |
1579 | \ref PushBack(GenericValue&, Allocator&) or \ref |
1580 | PushBack(StringRefType, Allocator&). |
1581 | All other pointer types would implicitly convert to \c bool, |
1582 | use an explicit cast instead, if needed. |
1583 | \note Amortized constant time complexity. |
1584 | */ |
1585 | template <typename T> |
1586 | RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&)) |
1587 | PushBack(T value, Allocator& allocator) { |
1588 | GenericValue v(value); |
1589 | return PushBack(v, allocator); |
1590 | } |
1591 | |
1592 | //! Remove the last element in the array. |
1593 | /*! |
1594 | \note Constant time complexity. |
1595 | */ |
1596 | GenericValue& PopBack() { |
1597 | RAPIDJSON_ASSERT(IsArray()); |
1598 | RAPIDJSON_ASSERT(!Empty()); |
1599 | GetElementsPointer()[--data_.a.size].~GenericValue(); |
1600 | return *this; |
1601 | } |
1602 | |
1603 | //! Remove an element of array by iterator. |
1604 | /*! |
1605 | \param pos iterator to the element to remove |
1606 | \pre IsArray() == true && \ref Begin() <= \c pos < \ref End() |
1607 | \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned. |
1608 | \note Linear time complexity. |
1609 | */ |
1610 | ValueIterator Erase(ConstValueIterator pos) { |
1611 | return Erase(pos, pos + 1); |
1612 | } |
1613 | |
1614 | //! Remove elements in the range [first, last) of the array. |
1615 | /*! |
1616 | \param first iterator to the first element to remove |
1617 | \param last iterator following the last element to remove |
1618 | \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End() |
1619 | \return Iterator following the last removed element. |
1620 | \note Linear time complexity. |
1621 | */ |
1622 | ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { |
1623 | RAPIDJSON_ASSERT(IsArray()); |
1624 | RAPIDJSON_ASSERT(data_.a.size > 0); |
1625 | RAPIDJSON_ASSERT(GetElementsPointer() != 0); |
1626 | RAPIDJSON_ASSERT(first >= Begin()); |
1627 | RAPIDJSON_ASSERT(first <= last); |
1628 | RAPIDJSON_ASSERT(last <= End()); |
1629 | ValueIterator pos = Begin() + (first - Begin()); |
1630 | for (ValueIterator itr = pos; itr != last; ++itr) |
1631 | itr->~GenericValue(); |
1632 | std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue)); |
1633 | data_.a.size -= static_cast<SizeType>(last - first); |
1634 | return pos; |
1635 | } |
1636 | |
1637 | Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); } |
1638 | ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); } |
1639 | |
1640 | //@} |
1641 | |
1642 | //!@name Number |
1643 | //@{ |
1644 | |
1645 | int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; } |
1646 | unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; } |
1647 | int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; } |
1648 | uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; } |
1649 | |
1650 | //! Get the value as double type. |
1651 | /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless. |
1652 | */ |
1653 | double GetDouble() const { |
1654 | RAPIDJSON_ASSERT(IsNumber()); |
1655 | if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. |
1656 | if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double |
1657 | if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double |
1658 | if ((data_.f.flags & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision) |
1659 | RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision) |
1660 | } |
1661 | |
1662 | //! Get the value as float type. |
1663 | /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless. |
1664 | */ |
1665 | float GetFloat() const { |
1666 | return static_cast<float>(GetDouble()); |
1667 | } |
1668 | |
1669 | GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } |
1670 | GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } |
1671 | GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } |
1672 | GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } |
1673 | GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } |
1674 | GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(f); return *this; } |
1675 | |
1676 | //@} |
1677 | |
1678 | //!@name String |
1679 | //@{ |
1680 | |
1681 | const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); } |
1682 | |
1683 | //! Get the length of string. |
1684 | /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). |
1685 | */ |
1686 | SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); } |
1687 | |
1688 | //! Set this value as a string without copying source string. |
1689 | /*! This version has better performance with supplied length, and also support string containing null character. |
1690 | \param s source string pointer. |
1691 | \param length The length of source string, excluding the trailing null terminator. |
1692 | \return The value itself for fluent API. |
1693 | \post IsString() == true && GetString() == s && GetStringLength() == length |
1694 | \see SetString(StringRefType) |
1695 | */ |
1696 | GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); } |
1697 | |
1698 | //! Set this value as a string without copying source string. |
1699 | /*! \param s source string reference |
1700 | \return The value itself for fluent API. |
1701 | \post IsString() == true && GetString() == s && GetStringLength() == s.length |
1702 | */ |
1703 | GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; } |
1704 | |
1705 | //! Set this value as a string by copying from source string. |
1706 | /*! This version has better performance with supplied length, and also support string containing null character. |
1707 | \param s source string. |
1708 | \param length The length of source string, excluding the trailing null terminator. |
1709 | \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). |
1710 | \return The value itself for fluent API. |
1711 | \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length |
1712 | */ |
1713 | GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; } |
1714 | |
1715 | //! Set this value as a string by copying from source string. |
1716 | /*! \param s source string. |
1717 | \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). |
1718 | \return The value itself for fluent API. |
1719 | \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length |
1720 | */ |
1721 | GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); } |
1722 | |
1723 | #if RAPIDJSON_HAS_STDSTRING |
1724 | //! Set this value as a string by copying from source string. |
1725 | /*! \param s source string. |
1726 | \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). |
1727 | \return The value itself for fluent API. |
1728 | \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() |
1729 | \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. |
1730 | */ |
1731 | GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); } |
1732 | #endif |
1733 | |
1734 | //@} |
1735 | |
1736 | //!@name Array |
1737 | //@{ |
1738 | |
1739 | //! Templated version for checking whether this value is type T. |
1740 | /*! |
1741 | \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string<Ch> |
1742 | */ |
1743 | template <typename T> |
1744 | bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); } |
1745 | |
1746 | template <typename T> |
1747 | T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); } |
1748 | |
1749 | template <typename T> |
1750 | T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); } |
1751 | |
1752 | template<typename T> |
1753 | ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); } |
1754 | |
1755 | template<typename T> |
1756 | ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); } |
1757 | |
1758 | //@} |
1759 | |
1760 | //! Generate events of this value to a Handler. |
1761 | /*! This function adopts the GoF visitor pattern. |
1762 | Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. |
1763 | It can also be used to deep clone this value via GenericDocument, which is also a Handler. |
1764 | \tparam Handler type of handler. |
1765 | \param handler An object implementing concept Handler. |
1766 | */ |
1767 | template <typename Handler> |
1768 | bool Accept(Handler& handler) const { |
1769 | switch(GetType()) { |
1770 | case kNullType: return handler.Null(); |
1771 | case kFalseType: return handler.Bool(false); |
1772 | case kTrueType: return handler.Bool(true); |
1773 | |
1774 | case kObjectType: |
1775 | if (RAPIDJSON_UNLIKELY(!handler.StartObject())) |
1776 | return false; |
1777 | for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { |
1778 | RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator. |
1779 | if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0))) |
1780 | return false; |
1781 | if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler))) |
1782 | return false; |
1783 | } |
1784 | return handler.EndObject(data_.o.size); |
1785 | |
1786 | case kArrayType: |
1787 | if (RAPIDJSON_UNLIKELY(!handler.StartArray())) |
1788 | return false; |
1789 | for (const GenericValue* v = Begin(); v != End(); ++v) |
1790 | if (RAPIDJSON_UNLIKELY(!v->Accept(handler))) |
1791 | return false; |
1792 | return handler.EndArray(data_.a.size); |
1793 | |
1794 | case kStringType: |
1795 | return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0); |
1796 | |
1797 | default: |
1798 | RAPIDJSON_ASSERT(GetType() == kNumberType); |
1799 | if (IsDouble()) return handler.Double(data_.n.d); |
1800 | else if (IsInt()) return handler.Int(data_.n.i.i); |
1801 | else if (IsUint()) return handler.Uint(data_.n.u.u); |
1802 | else if (IsInt64()) return handler.Int64(data_.n.i64); |
1803 | else return handler.Uint64(data_.n.u64); |
1804 | } |
1805 | } |
1806 | |
1807 | private: |
1808 | template <typename, typename> friend class GenericValue; |
1809 | template <typename, typename, typename> friend class GenericDocument; |
1810 | |
1811 | enum { |
1812 | kBoolFlag = 0x0008, |
1813 | kNumberFlag = 0x0010, |
1814 | kIntFlag = 0x0020, |
1815 | kUintFlag = 0x0040, |
1816 | kInt64Flag = 0x0080, |
1817 | kUint64Flag = 0x0100, |
1818 | kDoubleFlag = 0x0200, |
1819 | kStringFlag = 0x0400, |
1820 | kCopyFlag = 0x0800, |
1821 | kInlineStrFlag = 0x1000, |
1822 | |
1823 | // Initial flags of different types. |
1824 | kNullFlag = kNullType, |
1825 | kTrueFlag = kTrueType | kBoolFlag, |
1826 | kFalseFlag = kFalseType | kBoolFlag, |
1827 | kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, |
1828 | kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag, |
1829 | kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, |
1830 | kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, |
1831 | kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, |
1832 | kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag, |
1833 | kConstStringFlag = kStringType | kStringFlag, |
1834 | kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, |
1835 | kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag, |
1836 | kObjectFlag = kObjectType, |
1837 | kArrayFlag = kArrayType, |
1838 | |
1839 | kTypeMask = 0x07 |
1840 | }; |
1841 | |
1842 | static const SizeType kDefaultArrayCapacity = 16; |
1843 | static const SizeType kDefaultObjectCapacity = 16; |
1844 | |
1845 | struct Flag { |
1846 | #if RAPIDJSON_48BITPOINTER_OPTIMIZATION |
1847 | char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer |
1848 | #elif RAPIDJSON_64BIT |
1849 | char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes |
1850 | #else |
1851 | char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes |
1852 | #endif |
1853 | uint16_t flags; |
1854 | }; |
1855 | |
1856 | struct String { |
1857 | SizeType length; |
1858 | SizeType hashcode; //!< reserved |
1859 | const Ch* str; |
1860 | }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode |
1861 | |
1862 | // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars |
1863 | // (excluding the terminating zero) and store a value to determine the length of the contained |
1864 | // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string |
1865 | // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as |
1866 | // the string terminator as well. For getting the string length back from that value just use |
1867 | // "MaxSize - str[LenPos]". |
1868 | // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode, |
1869 | // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings). |
1870 | struct ShortString { |
1871 | enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; |
1872 | Ch str[MaxChars]; |
1873 | |
1874 | inline static bool Usable(SizeType len) { return (MaxSize >= len); } |
1875 | inline void SetLength(SizeType len) { str[LenPos] = static_cast<Ch>(MaxSize - len); } |
1876 | inline SizeType GetLength() const { return static_cast<SizeType>(MaxSize - str[LenPos]); } |
1877 | }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode |
1878 | |
1879 | // By using proper binary layout, retrieval of different integer types do not need conversions. |
1880 | union Number { |
1881 | #if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN |
1882 | struct I { |
1883 | int i; |
1884 | char padding[4]; |
1885 | }i; |
1886 | struct U { |
1887 | unsigned u; |
1888 | char padding2[4]; |
1889 | }u; |
1890 | #else |
1891 | struct I { |
1892 | char padding[4]; |
1893 | int i; |
1894 | }i; |
1895 | struct U { |
1896 | char padding2[4]; |
1897 | unsigned u; |
1898 | }u; |
1899 | #endif |
1900 | int64_t i64; |
1901 | uint64_t u64; |
1902 | double d; |
1903 | }; // 8 bytes |
1904 | |
1905 | struct ObjectData { |
1906 | SizeType size; |
1907 | SizeType capacity; |
1908 | Member* members; |
1909 | }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode |
1910 | |
1911 | struct ArrayData { |
1912 | SizeType size; |
1913 | SizeType capacity; |
1914 | GenericValue* elements; |
1915 | }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode |
1916 | |
1917 | union Data { |
1918 | String s; |
1919 | ShortString ss; |
1920 | Number n; |
1921 | ObjectData o; |
1922 | ArrayData a; |
1923 | Flag f; |
1924 | }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION |
1925 | |
1926 | RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); } |
1927 | RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); } |
1928 | RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); } |
1929 | RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); } |
1930 | RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); } |
1931 | RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); } |
1932 | |
1933 | // Initialize this value as array with initial data, without calling destructor. |
1934 | void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { |
1935 | data_.f.flags = kArrayFlag; |
1936 | if (count) { |
1937 | GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue))); |
1938 | SetElementsPointer(e); |
1939 | std::memcpy(e, values, count * sizeof(GenericValue)); |
1940 | } |
1941 | else |
1942 | SetElementsPointer(0); |
1943 | data_.a.size = data_.a.capacity = count; |
1944 | } |
1945 | |
1946 | //! Initialize this value as object with initial data, without calling destructor. |
1947 | void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { |
1948 | data_.f.flags = kObjectFlag; |
1949 | if (count) { |
1950 | Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member))); |
1951 | SetMembersPointer(m); |
1952 | std::memcpy(m, members, count * sizeof(Member)); |
1953 | } |
1954 | else |
1955 | SetMembersPointer(0); |
1956 | data_.o.size = data_.o.capacity = count; |
1957 | } |
1958 | |
1959 | //! Initialize this value as constant string, without calling destructor. |
1960 | void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { |
1961 | data_.f.flags = kConstStringFlag; |
1962 | SetStringPointer(s); |
1963 | data_.s.length = s.length; |
1964 | } |
1965 | |
1966 | //! Initialize this value as copy string with initial data, without calling destructor. |
1967 | void SetStringRaw(StringRefType s, Allocator& allocator) { |
1968 | Ch* str = 0; |
1969 | if (ShortString::Usable(s.length)) { |
1970 | data_.f.flags = kShortStringFlag; |
1971 | data_.ss.SetLength(s.length); |
1972 | str = data_.ss.str; |
1973 | } else { |
1974 | data_.f.flags = kCopyStringFlag; |
1975 | data_.s.length = s.length; |
1976 | str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch))); |
1977 | SetStringPointer(str); |
1978 | } |
1979 | std::memcpy(str, s, s.length * sizeof(Ch)); |
1980 | str[s.length] = '\0'; |
1981 | } |
1982 | |
1983 | //! Assignment without calling destructor |
1984 | void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { |
1985 | data_ = rhs.data_; |
1986 | // data_.f.flags = rhs.data_.f.flags; |
1987 | rhs.data_.f.flags = kNullFlag; |
1988 | } |
1989 | |
1990 | template <typename SourceAllocator> |
1991 | bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const { |
1992 | RAPIDJSON_ASSERT(IsString()); |
1993 | RAPIDJSON_ASSERT(rhs.IsString()); |
1994 | |
1995 | const SizeType len1 = GetStringLength(); |
1996 | const SizeType len2 = rhs.GetStringLength(); |
1997 | if(len1 != len2) { return false; } |
1998 | |
1999 | const Ch* const str1 = GetString(); |
2000 | const Ch* const str2 = rhs.GetString(); |
2001 | if(str1 == str2) { return true; } // fast path for constant string |
2002 | |
2003 | return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0); |
2004 | } |
2005 | |
2006 | Data data_; |
2007 | }; |
2008 | |
2009 | //! GenericValue with UTF8 encoding |
2010 | typedef GenericValue<UTF8<> > Value; |
2011 | |
2012 | /////////////////////////////////////////////////////////////////////////////// |
2013 | // GenericDocument |
2014 | |
2015 | //! A document for parsing JSON text as DOM. |
2016 | /*! |
2017 | \note implements Handler concept |
2018 | \tparam Encoding Encoding for both parsing and string storage. |
2019 | \tparam Allocator Allocator for allocating memory for the DOM |
2020 | \tparam StackAllocator Allocator for allocating memory for stack during parsing. |
2021 | \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue. |
2022 | */ |
2023 | template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator> |
2024 | class GenericDocument : public GenericValue<Encoding, Allocator> { |
2025 | public: |
2026 | typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. |
2027 | typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document. |
2028 | typedef Allocator AllocatorType; //!< Allocator type from template parameter. |
2029 | |
2030 | //! Constructor |
2031 | /*! Creates an empty document of specified type. |
2032 | \param type Mandatory type of object to create. |
2033 | \param allocator Optional allocator for allocating memory. |
2034 | \param stackCapacity Optional initial capacity of stack in bytes. |
2035 | \param stackAllocator Optional allocator for allocating memory for stack. |
2036 | */ |
2037 | explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : |
2038 | GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() |
2039 | { |
2040 | if (!allocator_) |
2041 | ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); |
2042 | } |
2043 | |
2044 | //! Constructor |
2045 | /*! Creates an empty document which type is Null. |
2046 | \param allocator Optional allocator for allocating memory. |
2047 | \param stackCapacity Optional initial capacity of stack in bytes. |
2048 | \param stackAllocator Optional allocator for allocating memory for stack. |
2049 | */ |
2050 | GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : |
2051 | allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() |
2052 | { |
2053 | if (!allocator_) |
2054 | ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); |
2055 | } |
2056 | |
2057 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
2058 | //! Move constructor in C++11 |
2059 | GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT |
2060 | : ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid prohibited move from Document |
2061 | allocator_(rhs.allocator_), |
2062 | ownAllocator_(rhs.ownAllocator_), |
2063 | stack_(std::move(rhs.stack_)), |
2064 | parseResult_(rhs.parseResult_) |
2065 | { |
2066 | rhs.allocator_ = 0; |
2067 | rhs.ownAllocator_ = 0; |
2068 | rhs.parseResult_ = ParseResult(); |
2069 | } |
2070 | #endif |
2071 | |
2072 | ~GenericDocument() { |
2073 | Destroy(); |
2074 | } |
2075 | |
2076 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
2077 | //! Move assignment in C++11 |
2078 | GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT |
2079 | { |
2080 | // The cast to ValueType is necessary here, because otherwise it would |
2081 | // attempt to call GenericValue's templated assignment operator. |
2082 | ValueType::operator=(std::forward<ValueType>(rhs)); |
2083 | |
2084 | // Calling the destructor here would prematurely call stack_'s destructor |
2085 | Destroy(); |
2086 | |
2087 | allocator_ = rhs.allocator_; |
2088 | ownAllocator_ = rhs.ownAllocator_; |
2089 | stack_ = std::move(rhs.stack_); |
2090 | parseResult_ = rhs.parseResult_; |
2091 | |
2092 | rhs.allocator_ = 0; |
2093 | rhs.ownAllocator_ = 0; |
2094 | rhs.parseResult_ = ParseResult(); |
2095 | |
2096 | return *this; |
2097 | } |
2098 | #endif |
2099 | |
2100 | //! Exchange the contents of this document with those of another. |
2101 | /*! |
2102 | \param rhs Another document. |
2103 | \note Constant complexity. |
2104 | \see GenericValue::Swap |
2105 | */ |
2106 | GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT { |
2107 | ValueType::Swap(rhs); |
2108 | stack_.Swap(rhs.stack_); |
2109 | internal::Swap(allocator_, rhs.allocator_); |
2110 | internal::Swap(ownAllocator_, rhs.ownAllocator_); |
2111 | internal::Swap(parseResult_, rhs.parseResult_); |
2112 | return *this; |
2113 | } |
2114 | |
2115 | //! free-standing swap function helper |
2116 | /*! |
2117 | Helper function to enable support for common swap implementation pattern based on \c std::swap: |
2118 | \code |
2119 | void swap(MyClass& a, MyClass& b) { |
2120 | using std::swap; |
2121 | swap(a.doc, b.doc); |
2122 | // ... |
2123 | } |
2124 | \endcode |
2125 | \see Swap() |
2126 | */ |
2127 | friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } |
2128 | |
2129 | //! Populate this document by a generator which produces SAX events. |
2130 | /*! \tparam Generator A functor with <tt>bool f(Handler)</tt> prototype. |
2131 | \param g Generator functor which sends SAX events to the parameter. |
2132 | \return The document itself for fluent API. |
2133 | */ |
2134 | template <typename Generator> |
2135 | GenericDocument& Populate(Generator& g) { |
2136 | ClearStackOnExit scope(*this); |
2137 | if (g(*this)) { |
2138 | RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object |
2139 | ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document |
2140 | } |
2141 | return *this; |
2142 | } |
2143 | |
2144 | //!@name Parse from stream |
2145 | //!@{ |
2146 | |
2147 | //! Parse JSON text from an input stream (with Encoding conversion) |
2148 | /*! \tparam parseFlags Combination of \ref ParseFlag. |
2149 | \tparam SourceEncoding Encoding of input stream |
2150 | \tparam InputStream Type of input stream, implementing Stream concept |
2151 | \param is Input stream to be parsed. |
2152 | \return The document itself for fluent API. |
2153 | */ |
2154 | template <unsigned parseFlags, typename SourceEncoding, typename InputStream> |
2155 | GenericDocument& ParseStream(InputStream& is) { |
2156 | GenericReader<SourceEncoding, Encoding, StackAllocator> reader( |
2157 | stack_.HasAllocator() ? &stack_.GetAllocator() : 0); |
2158 | ClearStackOnExit scope(*this); |
2159 | parseResult_ = reader.template Parse<parseFlags>(is, *this); |
2160 | if (parseResult_) { |
2161 | RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object |
2162 | ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document |
2163 | } |
2164 | return *this; |
2165 | } |
2166 | |
2167 | //! Parse JSON text from an input stream |
2168 | /*! \tparam parseFlags Combination of \ref ParseFlag. |
2169 | \tparam InputStream Type of input stream, implementing Stream concept |
2170 | \param is Input stream to be parsed. |
2171 | \return The document itself for fluent API. |
2172 | */ |
2173 | template <unsigned parseFlags, typename InputStream> |
2174 | GenericDocument& ParseStream(InputStream& is) { |
2175 | return ParseStream<parseFlags, Encoding, InputStream>(is); |
2176 | } |
2177 | |
2178 | //! Parse JSON text from an input stream (with \ref kParseDefaultFlags) |
2179 | /*! \tparam InputStream Type of input stream, implementing Stream concept |
2180 | \param is Input stream to be parsed. |
2181 | \return The document itself for fluent API. |
2182 | */ |
2183 | template <typename InputStream> |
2184 | GenericDocument& ParseStream(InputStream& is) { |
2185 | return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is); |
2186 | } |
2187 | //!@} |
2188 | |
2189 | //!@name Parse in-place from mutable string |
2190 | //!@{ |
2191 | |
2192 | //! Parse JSON text from a mutable string |
2193 | /*! \tparam parseFlags Combination of \ref ParseFlag. |
2194 | \param str Mutable zero-terminated string to be parsed. |
2195 | \return The document itself for fluent API. |
2196 | */ |
2197 | template <unsigned parseFlags> |
2198 | GenericDocument& ParseInsitu(Ch* str) { |
2199 | GenericInsituStringStream<Encoding> s(str); |
2200 | return ParseStream<parseFlags | kParseInsituFlag>(s); |
2201 | } |
2202 | |
2203 | //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags) |
2204 | /*! \param str Mutable zero-terminated string to be parsed. |
2205 | \return The document itself for fluent API. |
2206 | */ |
2207 | GenericDocument& ParseInsitu(Ch* str) { |
2208 | return ParseInsitu<kParseDefaultFlags>(str); |
2209 | } |
2210 | //!@} |
2211 | |
2212 | //!@name Parse from read-only string |
2213 | //!@{ |
2214 | |
2215 | //! Parse JSON text from a read-only string (with Encoding conversion) |
2216 | /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). |
2217 | \tparam SourceEncoding Transcoding from input Encoding |
2218 | \param str Read-only zero-terminated string to be parsed. |
2219 | */ |
2220 | template <unsigned parseFlags, typename SourceEncoding> |
2221 | GenericDocument& Parse(const typename SourceEncoding::Ch* str) { |
2222 | RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); |
2223 | GenericStringStream<SourceEncoding> s(str); |
2224 | return ParseStream<parseFlags, SourceEncoding>(s); |
2225 | } |
2226 | |
2227 | //! Parse JSON text from a read-only string |
2228 | /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). |
2229 | \param str Read-only zero-terminated string to be parsed. |
2230 | */ |
2231 | template <unsigned parseFlags> |
2232 | GenericDocument& Parse(const Ch* str) { |
2233 | return Parse<parseFlags, Encoding>(str); |
2234 | } |
2235 | |
2236 | //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) |
2237 | /*! \param str Read-only zero-terminated string to be parsed. |
2238 | */ |
2239 | GenericDocument& Parse(const Ch* str) { |
2240 | return Parse<kParseDefaultFlags>(str); |
2241 | } |
2242 | |
2243 | template <unsigned parseFlags, typename SourceEncoding> |
2244 | GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) { |
2245 | RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); |
2246 | MemoryStream ms(static_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch)); |
2247 | EncodedInputStream<SourceEncoding, MemoryStream> is(ms); |
2248 | ParseStream<parseFlags, SourceEncoding>(is); |
2249 | return *this; |
2250 | } |
2251 | |
2252 | template <unsigned parseFlags> |
2253 | GenericDocument& Parse(const Ch* str, size_t length) { |
2254 | return Parse<parseFlags, Encoding>(str, length); |
2255 | } |
2256 | |
2257 | GenericDocument& Parse(const Ch* str, size_t length) { |
2258 | return Parse<kParseDefaultFlags>(str, length); |
2259 | } |
2260 | |
2261 | #if RAPIDJSON_HAS_STDSTRING |
2262 | template <unsigned parseFlags, typename SourceEncoding> |
2263 | GenericDocument& Parse(const std::basic_string<typename SourceEncoding::Ch>& str) { |
2264 | // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t) |
2265 | return Parse<parseFlags, SourceEncoding>(str.c_str()); |
2266 | } |
2267 | |
2268 | template <unsigned parseFlags> |
2269 | GenericDocument& Parse(const std::basic_string<Ch>& str) { |
2270 | return Parse<parseFlags, Encoding>(str.c_str()); |
2271 | } |
2272 | |
2273 | GenericDocument& Parse(const std::basic_string<Ch>& str) { |
2274 | return Parse<kParseDefaultFlags>(str); |
2275 | } |
2276 | #endif // RAPIDJSON_HAS_STDSTRING |
2277 | |
2278 | //!@} |
2279 | |
2280 | //!@name Handling parse errors |
2281 | //!@{ |
2282 | |
2283 | //! Whether a parse error has occured in the last parsing. |
2284 | bool HasParseError() const { return parseResult_.IsError(); } |
2285 | |
2286 | //! Get the \ref ParseErrorCode of last parsing. |
2287 | ParseErrorCode GetParseError() const { return parseResult_.Code(); } |
2288 | |
2289 | //! Get the position of last parsing error in input, 0 otherwise. |
2290 | size_t GetErrorOffset() const { return parseResult_.Offset(); } |
2291 | |
2292 | //! Implicit conversion to get the last parse result |
2293 | #ifndef __clang // -Wdocumentation |
2294 | /*! \return \ref ParseResult of the last parse operation |
2295 | |
2296 | \code |
2297 | Document doc; |
2298 | ParseResult ok = doc.Parse(json); |
2299 | if (!ok) |
2300 | printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset()); |
2301 | \endcode |
2302 | */ |
2303 | #endif |
2304 | operator ParseResult() const { return parseResult_; } |
2305 | //!@} |
2306 | |
2307 | //! Get the allocator of this document. |
2308 | Allocator& GetAllocator() { |
2309 | RAPIDJSON_ASSERT(allocator_); |
2310 | return *allocator_; |
2311 | } |
2312 | |
2313 | //! Get the capacity of stack in bytes. |
2314 | size_t GetStackCapacity() const { return stack_.GetCapacity(); } |
2315 | |
2316 | private: |
2317 | // clear stack on any exit from ParseStream, e.g. due to exception |
2318 | struct ClearStackOnExit { |
2319 | explicit ClearStackOnExit(GenericDocument& d) : d_(d) {} |
2320 | ~ClearStackOnExit() { d_.ClearStack(); } |
2321 | private: |
2322 | ClearStackOnExit(const ClearStackOnExit&); |
2323 | ClearStackOnExit& operator=(const ClearStackOnExit&); |
2324 | GenericDocument& d_; |
2325 | }; |
2326 | |
2327 | // callers of the following private Handler functions |
2328 | // template <typename,typename,typename> friend class GenericReader; // for parsing |
2329 | template <typename, typename> friend class GenericValue; // for deep copying |
2330 | |
2331 | public: |
2332 | // Implementation of Handler |
2333 | bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; } |
2334 | bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; } |
2335 | bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } |
2336 | bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } |
2337 | bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } |
2338 | bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } |
2339 | bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; } |
2340 | |
2341 | bool RawNumber(const Ch* str, SizeType length, bool copy) { |
2342 | if (copy) |
2343 | new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator()); |
2344 | else |
2345 | new (stack_.template Push<ValueType>()) ValueType(str, length); |
2346 | return true; |
2347 | } |
2348 | |
2349 | bool String(const Ch* str, SizeType length, bool copy) { |
2350 | if (copy) |
2351 | new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator()); |
2352 | else |
2353 | new (stack_.template Push<ValueType>()) ValueType(str, length); |
2354 | return true; |
2355 | } |
2356 | |
2357 | bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; } |
2358 | |
2359 | bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); } |
2360 | |
2361 | bool EndObject(SizeType memberCount) { |
2362 | typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount); |
2363 | stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator()); |
2364 | return true; |
2365 | } |
2366 | |
2367 | bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; } |
2368 | |
2369 | bool EndArray(SizeType elementCount) { |
2370 | ValueType* elements = stack_.template Pop<ValueType>(elementCount); |
2371 | stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator()); |
2372 | return true; |
2373 | } |
2374 | |
2375 | private: |
2376 | //! Prohibit copying |
2377 | GenericDocument(const GenericDocument&); |
2378 | //! Prohibit assignment |
2379 | GenericDocument& operator=(const GenericDocument&); |
2380 | |
2381 | void ClearStack() { |
2382 | if (Allocator::kNeedFree) |
2383 | while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) |
2384 | (stack_.template Pop<ValueType>(1))->~ValueType(); |
2385 | else |
2386 | stack_.Clear(); |
2387 | stack_.ShrinkToFit(); |
2388 | } |
2389 | |
2390 | void Destroy() { |
2391 | RAPIDJSON_DELETE(ownAllocator_); |
2392 | } |
2393 | |
2394 | static const size_t kDefaultStackCapacity = 1024; |
2395 | Allocator* allocator_; |
2396 | Allocator* ownAllocator_; |
2397 | internal::Stack<StackAllocator> stack_; |
2398 | ParseResult parseResult_; |
2399 | }; |
2400 | |
2401 | //! GenericDocument with UTF8 encoding |
2402 | typedef GenericDocument<UTF8<> > Document; |
2403 | |
2404 | // defined here due to the dependency on GenericDocument |
2405 | template <typename Encoding, typename Allocator> |
2406 | template <typename SourceAllocator> |
2407 | inline |
2408 | GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator) |
2409 | { |
2410 | switch (rhs.GetType()) { |
2411 | case kObjectType: |
2412 | case kArrayType: { // perform deep copy via SAX Handler |
2413 | GenericDocument<Encoding,Allocator> d(&allocator); |
2414 | rhs.Accept(d); |
2415 | RawAssign(*d.stack_.template Pop<GenericValue>(1)); |
2416 | } |
2417 | break; |
2418 | case kStringType: |
2419 | if (rhs.data_.f.flags == kConstStringFlag) { |
2420 | data_.f.flags = rhs.data_.f.flags; |
2421 | data_ = *reinterpret_cast<const Data*>(&rhs.data_); |
2422 | } else { |
2423 | SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); |
2424 | } |
2425 | break; |
2426 | default: |
2427 | data_.f.flags = rhs.data_.f.flags; |
2428 | data_ = *reinterpret_cast<const Data*>(&rhs.data_); |
2429 | break; |
2430 | } |
2431 | } |
2432 | |
2433 | //! Helper class for accessing Value of array type. |
2434 | /*! |
2435 | Instance of this helper class is obtained by \c GenericValue::GetArray(). |
2436 | In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. |
2437 | */ |
2438 | template <bool Const, typename ValueT> |
2439 | class GenericArray { |
2440 | public: |
2441 | typedef GenericArray<true, ValueT> ConstArray; |
2442 | typedef GenericArray<false, ValueT> Array; |
2443 | typedef ValueT PlainType; |
2444 | typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; |
2445 | typedef ValueType* ValueIterator; // This may be const or non-const iterator |
2446 | typedef const ValueT* ConstValueIterator; |
2447 | typedef typename ValueType::AllocatorType AllocatorType; |
2448 | typedef typename ValueType::StringRefType StringRefType; |
2449 | |
2450 | template <typename, typename> |
2451 | friend class GenericValue; |
2452 | |
2453 | GenericArray(const GenericArray& rhs) : value_(rhs.value_) {} |
2454 | GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; } |
2455 | ~GenericArray() {} |
2456 | |
2457 | SizeType Size() const { return value_.Size(); } |
2458 | SizeType Capacity() const { return value_.Capacity(); } |
2459 | bool Empty() const { return value_.Empty(); } |
2460 | void Clear() const { value_.Clear(); } |
2461 | ValueType& operator[](SizeType index) const { return value_[index]; } |
2462 | ValueIterator Begin() const { return value_.Begin(); } |
2463 | ValueIterator End() const { return value_.End(); } |
2464 | GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; } |
2465 | GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } |
2466 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
2467 | GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } |
2468 | #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS |
2469 | GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } |
2470 | template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } |
2471 | GenericArray PopBack() const { value_.PopBack(); return *this; } |
2472 | ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); } |
2473 | ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); } |
2474 | |
2475 | #if RAPIDJSON_HAS_CXX11_RANGE_FOR |
2476 | ValueIterator begin() const { return value_.Begin(); } |
2477 | ValueIterator end() const { return value_.End(); } |
2478 | #endif |
2479 | |
2480 | private: |
2481 | GenericArray(); |
2482 | GenericArray(ValueType& value) : value_(value) {} |
2483 | ValueType& value_; |
2484 | }; |
2485 | |
2486 | //! Helper class for accessing Value of object type. |
2487 | /*! |
2488 | Instance of this helper class is obtained by \c GenericValue::GetObject(). |
2489 | In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. |
2490 | */ |
2491 | template <bool Const, typename ValueT> |
2492 | class GenericObject { |
2493 | public: |
2494 | typedef GenericObject<true, ValueT> ConstObject; |
2495 | typedef GenericObject<false, ValueT> Object; |
2496 | typedef ValueT PlainType; |
2497 | typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; |
2498 | typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename ValueT::AllocatorType> MemberIterator; // This may be const or non-const iterator |
2499 | typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename ValueT::AllocatorType> ConstMemberIterator; |
2500 | typedef typename ValueType::AllocatorType AllocatorType; |
2501 | typedef typename ValueType::StringRefType StringRefType; |
2502 | typedef typename ValueType::EncodingType EncodingType; |
2503 | typedef typename ValueType::Ch Ch; |
2504 | |
2505 | template <typename, typename> |
2506 | friend class GenericValue; |
2507 | |
2508 | GenericObject(const GenericObject& rhs) : value_(rhs.value_) {} |
2509 | GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; } |
2510 | ~GenericObject() {} |
2511 | |
2512 | SizeType MemberCount() const { return value_.MemberCount(); } |
2513 | bool ObjectEmpty() const { return value_.ObjectEmpty(); } |
2514 | template <typename T> ValueType& operator[](T* name) const { return value_[name]; } |
2515 | template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; } |
2516 | #if RAPIDJSON_HAS_STDSTRING |
2517 | ValueType& operator[](const std::basic_string<Ch>& name) const { return value_[name]; } |
2518 | #endif |
2519 | MemberIterator MemberBegin() const { return value_.MemberBegin(); } |
2520 | MemberIterator MemberEnd() const { return value_.MemberEnd(); } |
2521 | bool HasMember(const Ch* name) const { return value_.HasMember(name); } |
2522 | #if RAPIDJSON_HAS_STDSTRING |
2523 | bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); } |
2524 | #endif |
2525 | template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); } |
2526 | MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); } |
2527 | template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); } |
2528 | #if RAPIDJSON_HAS_STDSTRING |
2529 | MemberIterator FindMember(const std::basic_string<Ch>& name) const { return value_.FindMember(name); } |
2530 | #endif |
2531 | GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2532 | GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2533 | #if RAPIDJSON_HAS_STDSTRING |
2534 | GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2535 | #endif |
2536 | template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2537 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
2538 | GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2539 | GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2540 | GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2541 | GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2542 | #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS |
2543 | GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2544 | GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2545 | template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2546 | void RemoveAllMembers() { return value_.RemoveAllMembers(); } |
2547 | bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); } |
2548 | #if RAPIDJSON_HAS_STDSTRING |
2549 | bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); } |
2550 | #endif |
2551 | template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); } |
2552 | MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); } |
2553 | MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); } |
2554 | MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); } |
2555 | bool EraseMember(const Ch* name) const { return value_.EraseMember(name); } |
2556 | #if RAPIDJSON_HAS_STDSTRING |
2557 | bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); } |
2558 | #endif |
2559 | template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); } |
2560 | |
2561 | #if RAPIDJSON_HAS_CXX11_RANGE_FOR |
2562 | MemberIterator begin() const { return value_.MemberBegin(); } |
2563 | MemberIterator end() const { return value_.MemberEnd(); } |
2564 | #endif |
2565 | |
2566 | private: |
2567 | GenericObject(); |
2568 | GenericObject(ValueType& value) : value_(value) {} |
2569 | ValueType& value_; |
2570 | }; |
2571 | |
2572 | RAPIDJSON_NAMESPACE_END |
2573 | RAPIDJSON_DIAG_POP |
2574 | |
2575 | #endif // RAPIDJSON_DOCUMENT_H_ |
2576 | |