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