rapidjson 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/CODE_OF_CONDUCT.md +84 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +110 -0
  5. data/Rakefile +20 -0
  6. data/ext/rapidjson/buffer.hh +66 -0
  7. data/ext/rapidjson/cext.cc +77 -0
  8. data/ext/rapidjson/cext.hh +20 -0
  9. data/ext/rapidjson/encoder.hh +150 -0
  10. data/ext/rapidjson/extconf.rb +19 -0
  11. data/ext/rapidjson/parser.hh +149 -0
  12. data/ext/rapidjson/rapidjson/include/rapidjson/allocators.h +692 -0
  13. data/ext/rapidjson/rapidjson/include/rapidjson/cursorstreamwrapper.h +78 -0
  14. data/ext/rapidjson/rapidjson/include/rapidjson/document.h +3027 -0
  15. data/ext/rapidjson/rapidjson/include/rapidjson/encodedstream.h +299 -0
  16. data/ext/rapidjson/rapidjson/include/rapidjson/encodings.h +716 -0
  17. data/ext/rapidjson/rapidjson/include/rapidjson/error/en.h +122 -0
  18. data/ext/rapidjson/rapidjson/include/rapidjson/error/error.h +216 -0
  19. data/ext/rapidjson/rapidjson/include/rapidjson/filereadstream.h +99 -0
  20. data/ext/rapidjson/rapidjson/include/rapidjson/filewritestream.h +104 -0
  21. data/ext/rapidjson/rapidjson/include/rapidjson/fwd.h +151 -0
  22. data/ext/rapidjson/rapidjson/include/rapidjson/internal/biginteger.h +297 -0
  23. data/ext/rapidjson/rapidjson/include/rapidjson/internal/clzll.h +71 -0
  24. data/ext/rapidjson/rapidjson/include/rapidjson/internal/diyfp.h +261 -0
  25. data/ext/rapidjson/rapidjson/include/rapidjson/internal/dtoa.h +249 -0
  26. data/ext/rapidjson/rapidjson/include/rapidjson/internal/ieee754.h +78 -0
  27. data/ext/rapidjson/rapidjson/include/rapidjson/internal/itoa.h +308 -0
  28. data/ext/rapidjson/rapidjson/include/rapidjson/internal/meta.h +186 -0
  29. data/ext/rapidjson/rapidjson/include/rapidjson/internal/pow10.h +55 -0
  30. data/ext/rapidjson/rapidjson/include/rapidjson/internal/regex.h +739 -0
  31. data/ext/rapidjson/rapidjson/include/rapidjson/internal/stack.h +232 -0
  32. data/ext/rapidjson/rapidjson/include/rapidjson/internal/strfunc.h +83 -0
  33. data/ext/rapidjson/rapidjson/include/rapidjson/internal/strtod.h +293 -0
  34. data/ext/rapidjson/rapidjson/include/rapidjson/internal/swap.h +46 -0
  35. data/ext/rapidjson/rapidjson/include/rapidjson/istreamwrapper.h +128 -0
  36. data/ext/rapidjson/rapidjson/include/rapidjson/memorybuffer.h +70 -0
  37. data/ext/rapidjson/rapidjson/include/rapidjson/memorystream.h +71 -0
  38. data/ext/rapidjson/rapidjson/include/rapidjson/msinttypes/inttypes.h +316 -0
  39. data/ext/rapidjson/rapidjson/include/rapidjson/msinttypes/stdint.h +300 -0
  40. data/ext/rapidjson/rapidjson/include/rapidjson/ostreamwrapper.h +81 -0
  41. data/ext/rapidjson/rapidjson/include/rapidjson/pointer.h +1482 -0
  42. data/ext/rapidjson/rapidjson/include/rapidjson/prettywriter.h +277 -0
  43. data/ext/rapidjson/rapidjson/include/rapidjson/rapidjson.h +741 -0
  44. data/ext/rapidjson/rapidjson/include/rapidjson/reader.h +2246 -0
  45. data/ext/rapidjson/rapidjson/include/rapidjson/schema.h +2795 -0
  46. data/ext/rapidjson/rapidjson/include/rapidjson/stream.h +223 -0
  47. data/ext/rapidjson/rapidjson/include/rapidjson/stringbuffer.h +121 -0
  48. data/ext/rapidjson/rapidjson/include/rapidjson/uri.h +481 -0
  49. data/ext/rapidjson/rapidjson/include/rapidjson/writer.h +710 -0
  50. data/lib/rapidjson/json_gem.rb +36 -0
  51. data/lib/rapidjson/version.rb +5 -0
  52. data/lib/rapidjson.rb +9 -0
  53. metadata +98 -0
@@ -0,0 +1,1482 @@
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.
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_POINTER_H_
16
+ #define RAPIDJSON_POINTER_H_
17
+
18
+ #include "document.h"
19
+ #include "uri.h"
20
+ #include "internal/itoa.h"
21
+
22
+ #ifdef __clang__
23
+ RAPIDJSON_DIAG_PUSH
24
+ RAPIDJSON_DIAG_OFF(switch-enum)
25
+ #elif defined(_MSC_VER)
26
+ RAPIDJSON_DIAG_PUSH
27
+ RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
28
+ #endif
29
+
30
+ RAPIDJSON_NAMESPACE_BEGIN
31
+
32
+ static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token
33
+
34
+ //! Error code of parsing.
35
+ /*! \ingroup RAPIDJSON_ERRORS
36
+ \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
37
+ */
38
+ enum PointerParseErrorCode {
39
+ kPointerParseErrorNone = 0, //!< The parse is successful
40
+
41
+ kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/'
42
+ kPointerParseErrorInvalidEscape, //!< Invalid escape
43
+ kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment
44
+ kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment
45
+ };
46
+
47
+ ///////////////////////////////////////////////////////////////////////////////
48
+ // GenericPointer
49
+
50
+ //! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
51
+ /*!
52
+ This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer"
53
+ (https://tools.ietf.org/html/rfc6901).
54
+
55
+ A JSON pointer is for identifying a specific value in a JSON document
56
+ (GenericDocument). It can simplify coding of DOM tree manipulation, because it
57
+ can access multiple-level depth of DOM tree with single API call.
58
+
59
+ After it parses a string representation (e.g. "/foo/0" or URI fragment
60
+ representation (e.g. "#/foo/0") into its internal representation (tokens),
61
+ it can be used to resolve a specific value in multiple documents, or sub-tree
62
+ of documents.
63
+
64
+ Contrary to GenericValue, Pointer can be copy constructed and copy assigned.
65
+ Apart from assignment, a Pointer cannot be modified after construction.
66
+
67
+ Although Pointer is very convenient, please aware that constructing Pointer
68
+ involves parsing and dynamic memory allocation. A special constructor with user-
69
+ supplied tokens eliminates these.
70
+
71
+ GenericPointer depends on GenericDocument and GenericValue.
72
+
73
+ \tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> >
74
+ \tparam Allocator The allocator type for allocating memory for internal representation.
75
+
76
+ \note GenericPointer uses same encoding of ValueType.
77
+ However, Allocator of GenericPointer is independent of Allocator of Value.
78
+ */
79
+ template <typename ValueType, typename Allocator = CrtAllocator>
80
+ class GenericPointer {
81
+ public:
82
+ typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value
83
+ typedef typename ValueType::Ch Ch; //!< Character type from Value
84
+ typedef GenericUri<ValueType, Allocator> UriType;
85
+
86
+
87
+ //! A token is the basic units of internal representation.
88
+ /*!
89
+ A JSON pointer string representation "/foo/123" is parsed to two tokens:
90
+ "foo" and 123. 123 will be represented in both numeric form and string form.
91
+ They are resolved according to the actual value type (object or array).
92
+
93
+ For token that are not numbers, or the numeric value is out of bound
94
+ (greater than limits of SizeType), they are only treated as string form
95
+ (i.e. the token's index will be equal to kPointerInvalidIndex).
96
+
97
+ This struct is public so that user can create a Pointer without parsing and
98
+ allocation, using a special constructor.
99
+ */
100
+ struct Token {
101
+ const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character.
102
+ SizeType length; //!< Length of the name.
103
+ SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex.
104
+ };
105
+
106
+ //!@name Constructors and destructor.
107
+ //@{
108
+
109
+ //! Default constructor.
110
+ GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
111
+
112
+ //! Constructor that parses a string or URI fragment representation.
113
+ /*!
114
+ \param source A null-terminated, string or URI fragment representation of JSON pointer.
115
+ \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
116
+ */
117
+ explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
118
+ Parse(source, internal::StrLen(source));
119
+ }
120
+
121
+ #if RAPIDJSON_HAS_STDSTRING
122
+ //! Constructor that parses a string or URI fragment representation.
123
+ /*!
124
+ \param source A string or URI fragment representation of JSON pointer.
125
+ \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
126
+ \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
127
+ */
128
+ explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
129
+ Parse(source.c_str(), source.size());
130
+ }
131
+ #endif
132
+
133
+ //! Constructor that parses a string or URI fragment representation, with length of the source string.
134
+ /*!
135
+ \param source A string or URI fragment representation of JSON pointer.
136
+ \param length Length of source.
137
+ \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
138
+ \note Slightly faster than the overload without length.
139
+ */
140
+ GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
141
+ Parse(source, length);
142
+ }
143
+
144
+ //! Constructor with user-supplied tokens.
145
+ /*!
146
+ This constructor let user supplies const array of tokens.
147
+ This prevents the parsing process and eliminates allocation.
148
+ This is preferred for memory constrained environments.
149
+
150
+ \param tokens An constant array of tokens representing the JSON pointer.
151
+ \param tokenCount Number of tokens.
152
+
153
+ \b Example
154
+ \code
155
+ #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex }
156
+ #define INDEX(i) { #i, sizeof(#i) - 1, i }
157
+
158
+ static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) };
159
+ static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
160
+ // Equivalent to static const Pointer p("/foo/123");
161
+
162
+ #undef NAME
163
+ #undef INDEX
164
+ \endcode
165
+ */
166
+ GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
167
+
168
+ //! Copy constructor.
169
+ GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
170
+ *this = rhs;
171
+ }
172
+
173
+ //! Copy constructor.
174
+ GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
175
+ *this = rhs;
176
+ }
177
+
178
+ //! Destructor.
179
+ ~GenericPointer() {
180
+ if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
181
+ Allocator::Free(tokens_);
182
+ RAPIDJSON_DELETE(ownAllocator_);
183
+ }
184
+
185
+ //! Assignment operator.
186
+ GenericPointer& operator=(const GenericPointer& rhs) {
187
+ if (this != &rhs) {
188
+ // Do not delete ownAllcator
189
+ if (nameBuffer_)
190
+ Allocator::Free(tokens_);
191
+
192
+ tokenCount_ = rhs.tokenCount_;
193
+ parseErrorOffset_ = rhs.parseErrorOffset_;
194
+ parseErrorCode_ = rhs.parseErrorCode_;
195
+
196
+ if (rhs.nameBuffer_)
197
+ CopyFromRaw(rhs); // Normally parsed tokens.
198
+ else {
199
+ tokens_ = rhs.tokens_; // User supplied const tokens.
200
+ nameBuffer_ = 0;
201
+ }
202
+ }
203
+ return *this;
204
+ }
205
+
206
+ //! Swap the content of this pointer with an other.
207
+ /*!
208
+ \param other The pointer to swap with.
209
+ \note Constant complexity.
210
+ */
211
+ GenericPointer& Swap(GenericPointer& other) RAPIDJSON_NOEXCEPT {
212
+ internal::Swap(allocator_, other.allocator_);
213
+ internal::Swap(ownAllocator_, other.ownAllocator_);
214
+ internal::Swap(nameBuffer_, other.nameBuffer_);
215
+ internal::Swap(tokens_, other.tokens_);
216
+ internal::Swap(tokenCount_, other.tokenCount_);
217
+ internal::Swap(parseErrorOffset_, other.parseErrorOffset_);
218
+ internal::Swap(parseErrorCode_, other.parseErrorCode_);
219
+ return *this;
220
+ }
221
+
222
+ //! free-standing swap function helper
223
+ /*!
224
+ Helper function to enable support for common swap implementation pattern based on \c std::swap:
225
+ \code
226
+ void swap(MyClass& a, MyClass& b) {
227
+ using std::swap;
228
+ swap(a.pointer, b.pointer);
229
+ // ...
230
+ }
231
+ \endcode
232
+ \see Swap()
233
+ */
234
+ friend inline void swap(GenericPointer& a, GenericPointer& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
235
+
236
+ //@}
237
+
238
+ //!@name Append token
239
+ //@{
240
+
241
+ //! Append a token and return a new Pointer
242
+ /*!
243
+ \param token Token to be appended.
244
+ \param allocator Allocator for the newly return Pointer.
245
+ \return A new Pointer with appended token.
246
+ */
247
+ GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
248
+ GenericPointer r;
249
+ r.allocator_ = allocator;
250
+ Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
251
+ std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
252
+ r.tokens_[tokenCount_].name = p;
253
+ r.tokens_[tokenCount_].length = token.length;
254
+ r.tokens_[tokenCount_].index = token.index;
255
+ return r;
256
+ }
257
+
258
+ //! Append a name token with length, and return a new Pointer
259
+ /*!
260
+ \param name Name to be appended.
261
+ \param length Length of name.
262
+ \param allocator Allocator for the newly return Pointer.
263
+ \return A new Pointer with appended token.
264
+ */
265
+ GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const {
266
+ Token token = { name, length, kPointerInvalidIndex };
267
+ return Append(token, allocator);
268
+ }
269
+
270
+ //! Append a name token without length, and return a new Pointer
271
+ /*!
272
+ \param name Name (const Ch*) to be appended.
273
+ \param allocator Allocator for the newly return Pointer.
274
+ \return A new Pointer with appended token.
275
+ */
276
+ template <typename T>
277
+ RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
278
+ Append(T* name, Allocator* allocator = 0) const {
279
+ return Append(name, internal::StrLen(name), allocator);
280
+ }
281
+
282
+ #if RAPIDJSON_HAS_STDSTRING
283
+ //! Append a name token, and return a new Pointer
284
+ /*!
285
+ \param name Name to be appended.
286
+ \param allocator Allocator for the newly return Pointer.
287
+ \return A new Pointer with appended token.
288
+ */
289
+ GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const {
290
+ return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator);
291
+ }
292
+ #endif
293
+
294
+ //! Append a index token, and return a new Pointer
295
+ /*!
296
+ \param index Index to be appended.
297
+ \param allocator Allocator for the newly return Pointer.
298
+ \return A new Pointer with appended token.
299
+ */
300
+ GenericPointer Append(SizeType index, Allocator* allocator = 0) const {
301
+ char buffer[21];
302
+ char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer);
303
+ SizeType length = static_cast<SizeType>(end - buffer);
304
+ buffer[length] = '\0';
305
+
306
+ if (sizeof(Ch) == 1) {
307
+ Token token = { reinterpret_cast<Ch*>(buffer), length, index };
308
+ return Append(token, allocator);
309
+ }
310
+ else {
311
+ Ch name[21];
312
+ for (size_t i = 0; i <= length; i++)
313
+ name[i] = static_cast<Ch>(buffer[i]);
314
+ Token token = { name, length, index };
315
+ return Append(token, allocator);
316
+ }
317
+ }
318
+
319
+ //! Append a token by value, and return a new Pointer
320
+ /*!
321
+ \param token token to be appended.
322
+ \param allocator Allocator for the newly return Pointer.
323
+ \return A new Pointer with appended token.
324
+ */
325
+ GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {
326
+ if (token.IsString())
327
+ return Append(token.GetString(), token.GetStringLength(), allocator);
328
+ else {
329
+ RAPIDJSON_ASSERT(token.IsUint64());
330
+ RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
331
+ return Append(static_cast<SizeType>(token.GetUint64()), allocator);
332
+ }
333
+ }
334
+
335
+ //!@name Handling Parse Error
336
+ //@{
337
+
338
+ //! Check whether this is a valid pointer.
339
+ bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }
340
+
341
+ //! Get the parsing error offset in code unit.
342
+ size_t GetParseErrorOffset() const { return parseErrorOffset_; }
343
+
344
+ //! Get the parsing error code.
345
+ PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }
346
+
347
+ //@}
348
+
349
+ //! Get the allocator of this pointer.
350
+ Allocator& GetAllocator() { return *allocator_; }
351
+
352
+ //!@name Tokens
353
+ //@{
354
+
355
+ //! Get the token array (const version only).
356
+ const Token* GetTokens() const { return tokens_; }
357
+
358
+ //! Get the number of tokens.
359
+ size_t GetTokenCount() const { return tokenCount_; }
360
+
361
+ //@}
362
+
363
+ //!@name Equality/inequality operators
364
+ //@{
365
+
366
+ //! Equality operator.
367
+ /*!
368
+ \note When any pointers are invalid, always returns false.
369
+ */
370
+ bool operator==(const GenericPointer& rhs) const {
371
+ if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
372
+ return false;
373
+
374
+ for (size_t i = 0; i < tokenCount_; i++) {
375
+ if (tokens_[i].index != rhs.tokens_[i].index ||
376
+ tokens_[i].length != rhs.tokens_[i].length ||
377
+ (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
378
+ {
379
+ return false;
380
+ }
381
+ }
382
+
383
+ return true;
384
+ }
385
+
386
+ //! Inequality operator.
387
+ /*!
388
+ \note When any pointers are invalid, always returns true.
389
+ */
390
+ bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
391
+
392
+ //! Less than operator.
393
+ /*!
394
+ \note Invalid pointers are always greater than valid ones.
395
+ */
396
+ bool operator<(const GenericPointer& rhs) const {
397
+ if (!IsValid())
398
+ return false;
399
+ if (!rhs.IsValid())
400
+ return true;
401
+
402
+ if (tokenCount_ != rhs.tokenCount_)
403
+ return tokenCount_ < rhs.tokenCount_;
404
+
405
+ for (size_t i = 0; i < tokenCount_; i++) {
406
+ if (tokens_[i].index != rhs.tokens_[i].index)
407
+ return tokens_[i].index < rhs.tokens_[i].index;
408
+
409
+ if (tokens_[i].length != rhs.tokens_[i].length)
410
+ return tokens_[i].length < rhs.tokens_[i].length;
411
+
412
+ if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length))
413
+ return cmp < 0;
414
+ }
415
+
416
+ return false;
417
+ }
418
+
419
+ //@}
420
+
421
+ //!@name Stringify
422
+ //@{
423
+
424
+ //! Stringify the pointer into string representation.
425
+ /*!
426
+ \tparam OutputStream Type of output stream.
427
+ \param os The output stream.
428
+ */
429
+ template<typename OutputStream>
430
+ bool Stringify(OutputStream& os) const {
431
+ return Stringify<false, OutputStream>(os);
432
+ }
433
+
434
+ //! Stringify the pointer into URI fragment representation.
435
+ /*!
436
+ \tparam OutputStream Type of output stream.
437
+ \param os The output stream.
438
+ */
439
+ template<typename OutputStream>
440
+ bool StringifyUriFragment(OutputStream& os) const {
441
+ return Stringify<true, OutputStream>(os);
442
+ }
443
+
444
+ //@}
445
+
446
+ //!@name Create value
447
+ //@{
448
+
449
+ //! Create a value in a subtree.
450
+ /*!
451
+ If the value is not exist, it creates all parent values and a JSON Null value.
452
+ So it always succeed and return the newly created or existing value.
453
+
454
+ Remind that it may change types of parents according to tokens, so it
455
+ potentially removes previously stored values. For example, if a document
456
+ was an array, and "/foo" is used to create a value, then the document
457
+ will be changed to an object, and all existing array elements are lost.
458
+
459
+ \param root Root value of a DOM subtree to be resolved. It can be any value other than document root.
460
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
461
+ \param alreadyExist If non-null, it stores whether the resolved value is already exist.
462
+ \return The resolved newly created (a JSON Null value), or already exists value.
463
+ */
464
+ ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
465
+ RAPIDJSON_ASSERT(IsValid());
466
+ ValueType* v = &root;
467
+ bool exist = true;
468
+ for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
469
+ if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
470
+ v->PushBack(ValueType().Move(), allocator);
471
+ v = &((*v)[v->Size() - 1]);
472
+ exist = false;
473
+ }
474
+ else {
475
+ if (t->index == kPointerInvalidIndex) { // must be object name
476
+ if (!v->IsObject())
477
+ v->SetObject(); // Change to Object
478
+ }
479
+ else { // object name or array index
480
+ if (!v->IsArray() && !v->IsObject())
481
+ v->SetArray(); // Change to Array
482
+ }
483
+
484
+ if (v->IsArray()) {
485
+ if (t->index >= v->Size()) {
486
+ v->Reserve(t->index + 1, allocator);
487
+ while (t->index >= v->Size())
488
+ v->PushBack(ValueType().Move(), allocator);
489
+ exist = false;
490
+ }
491
+ v = &((*v)[t->index]);
492
+ }
493
+ else {
494
+ typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
495
+ if (m == v->MemberEnd()) {
496
+ v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
497
+ m = v->MemberEnd();
498
+ v = &(--m)->value; // Assumes AddMember() appends at the end
499
+ exist = false;
500
+ }
501
+ else
502
+ v = &m->value;
503
+ }
504
+ }
505
+ }
506
+
507
+ if (alreadyExist)
508
+ *alreadyExist = exist;
509
+
510
+ return *v;
511
+ }
512
+
513
+ //! Creates a value in a document.
514
+ /*!
515
+ \param document A document to be resolved.
516
+ \param alreadyExist If non-null, it stores whether the resolved value is already exist.
517
+ \return The resolved newly created, or already exists value.
518
+ */
519
+ template <typename stackAllocator>
520
+ ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const {
521
+ return Create(document, document.GetAllocator(), alreadyExist);
522
+ }
523
+
524
+ //@}
525
+
526
+ //!@name Compute URI
527
+ //@{
528
+
529
+ //! Compute the in-scope URI for a subtree.
530
+ // For use with JSON pointers into JSON schema documents.
531
+ /*!
532
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
533
+ \param rootUri Root URI
534
+ \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
535
+ \param allocator Allocator for Uris
536
+ \return Uri if it can be resolved. Otherwise null.
537
+
538
+ \note
539
+ There are only 3 situations when a URI cannot be resolved:
540
+ 1. A value in the path is not an array nor object.
541
+ 2. An object value does not contain the token.
542
+ 3. A token is out of range of an array value.
543
+
544
+ Use unresolvedTokenIndex to retrieve the token index.
545
+ */
546
+ UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
547
+ static const Ch kIdString[] = { 'i', 'd', '\0' };
548
+ static const ValueType kIdValue(kIdString, 2);
549
+ UriType base = UriType(rootUri, allocator);
550
+ RAPIDJSON_ASSERT(IsValid());
551
+ ValueType* v = &root;
552
+ for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
553
+ switch (v->GetType()) {
554
+ case kObjectType:
555
+ {
556
+ // See if we have an id, and if so resolve with the current base
557
+ typename ValueType::MemberIterator m = v->FindMember(kIdValue);
558
+ if (m != v->MemberEnd() && (m->value).IsString()) {
559
+ UriType here = UriType(m->value, allocator).Resolve(base, allocator);
560
+ base = here;
561
+ }
562
+ m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
563
+ if (m == v->MemberEnd())
564
+ break;
565
+ v = &m->value;
566
+ }
567
+ continue;
568
+ case kArrayType:
569
+ if (t->index == kPointerInvalidIndex || t->index >= v->Size())
570
+ break;
571
+ v = &((*v)[t->index]);
572
+ continue;
573
+ default:
574
+ break;
575
+ }
576
+
577
+ // Error: unresolved token
578
+ if (unresolvedTokenIndex)
579
+ *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
580
+ return UriType(allocator);
581
+ }
582
+ return base;
583
+ }
584
+
585
+ UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
586
+ return GetUri(const_cast<ValueType&>(root), rootUri, unresolvedTokenIndex, allocator);
587
+ }
588
+
589
+
590
+ //!@name Query value
591
+ //@{
592
+
593
+ //! Query a value in a subtree.
594
+ /*!
595
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
596
+ \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
597
+ \return Pointer to the value if it can be resolved. Otherwise null.
598
+
599
+ \note
600
+ There are only 3 situations when a value cannot be resolved:
601
+ 1. A value in the path is not an array nor object.
602
+ 2. An object value does not contain the token.
603
+ 3. A token is out of range of an array value.
604
+
605
+ Use unresolvedTokenIndex to retrieve the token index.
606
+ */
607
+ ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
608
+ RAPIDJSON_ASSERT(IsValid());
609
+ ValueType* v = &root;
610
+ for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
611
+ switch (v->GetType()) {
612
+ case kObjectType:
613
+ {
614
+ typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
615
+ if (m == v->MemberEnd())
616
+ break;
617
+ v = &m->value;
618
+ }
619
+ continue;
620
+ case kArrayType:
621
+ if (t->index == kPointerInvalidIndex || t->index >= v->Size())
622
+ break;
623
+ v = &((*v)[t->index]);
624
+ continue;
625
+ default:
626
+ break;
627
+ }
628
+
629
+ // Error: unresolved token
630
+ if (unresolvedTokenIndex)
631
+ *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
632
+ return 0;
633
+ }
634
+ return v;
635
+ }
636
+
637
+ //! Query a const value in a const subtree.
638
+ /*!
639
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
640
+ \return Pointer to the value if it can be resolved. Otherwise null.
641
+ */
642
+ const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
643
+ return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
644
+ }
645
+
646
+ //@}
647
+
648
+ //!@name Query a value with default
649
+ //@{
650
+
651
+ //! Query a value in a subtree with default value.
652
+ /*!
653
+ Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value.
654
+ So that this function always succeed.
655
+
656
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
657
+ \param defaultValue Default value to be cloned if the value was not exists.
658
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
659
+ \see Create()
660
+ */
661
+ ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
662
+ bool alreadyExist;
663
+ ValueType& v = Create(root, allocator, &alreadyExist);
664
+ return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
665
+ }
666
+
667
+ //! Query a value in a subtree with default null-terminated string.
668
+ ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
669
+ bool alreadyExist;
670
+ ValueType& v = Create(root, allocator, &alreadyExist);
671
+ return alreadyExist ? v : v.SetString(defaultValue, allocator);
672
+ }
673
+
674
+ #if RAPIDJSON_HAS_STDSTRING
675
+ //! Query a value in a subtree with default std::basic_string.
676
+ ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
677
+ bool alreadyExist;
678
+ ValueType& v = Create(root, allocator, &alreadyExist);
679
+ return alreadyExist ? v : v.SetString(defaultValue, allocator);
680
+ }
681
+ #endif
682
+
683
+ //! Query a value in a subtree with default primitive value.
684
+ /*!
685
+ \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
686
+ */
687
+ template <typename T>
688
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
689
+ GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
690
+ return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
691
+ }
692
+
693
+ //! Query a value in a document with default value.
694
+ template <typename stackAllocator>
695
+ ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const {
696
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
697
+ }
698
+
699
+ //! Query a value in a document with default null-terminated string.
700
+ template <typename stackAllocator>
701
+ ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {
702
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
703
+ }
704
+
705
+ #if RAPIDJSON_HAS_STDSTRING
706
+ //! Query a value in a document with default std::basic_string.
707
+ template <typename stackAllocator>
708
+ ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
709
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
710
+ }
711
+ #endif
712
+
713
+ //! Query a value in a document with default primitive value.
714
+ /*!
715
+ \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
716
+ */
717
+ template <typename T, typename stackAllocator>
718
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
719
+ GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
720
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
721
+ }
722
+
723
+ //@}
724
+
725
+ //!@name Set a value
726
+ //@{
727
+
728
+ //! Set a value in a subtree, with move semantics.
729
+ /*!
730
+ It creates all parents if they are not exist or types are different to the tokens.
731
+ So this function always succeeds but potentially remove existing values.
732
+
733
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
734
+ \param value Value to be set.
735
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
736
+ \see Create()
737
+ */
738
+ ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
739
+ return Create(root, allocator) = value;
740
+ }
741
+
742
+ //! Set a value in a subtree, with copy semantics.
743
+ ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
744
+ return Create(root, allocator).CopyFrom(value, allocator);
745
+ }
746
+
747
+ //! Set a null-terminated string in a subtree.
748
+ ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
749
+ return Create(root, allocator) = ValueType(value, allocator).Move();
750
+ }
751
+
752
+ #if RAPIDJSON_HAS_STDSTRING
753
+ //! Set a std::basic_string in a subtree.
754
+ ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
755
+ return Create(root, allocator) = ValueType(value, allocator).Move();
756
+ }
757
+ #endif
758
+
759
+ //! Set a primitive value in a subtree.
760
+ /*!
761
+ \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
762
+ */
763
+ template <typename T>
764
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
765
+ Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
766
+ return Create(root, allocator) = ValueType(value).Move();
767
+ }
768
+
769
+ //! Set a value in a document, with move semantics.
770
+ template <typename stackAllocator>
771
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
772
+ return Create(document) = value;
773
+ }
774
+
775
+ //! Set a value in a document, with copy semantics.
776
+ template <typename stackAllocator>
777
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const {
778
+ return Create(document).CopyFrom(value, document.GetAllocator());
779
+ }
780
+
781
+ //! Set a null-terminated string in a document.
782
+ template <typename stackAllocator>
783
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* value) const {
784
+ return Create(document) = ValueType(value, document.GetAllocator()).Move();
785
+ }
786
+
787
+ #if RAPIDJSON_HAS_STDSTRING
788
+ //! Sets a std::basic_string in a document.
789
+ template <typename stackAllocator>
790
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const {
791
+ return Create(document) = ValueType(value, document.GetAllocator()).Move();
792
+ }
793
+ #endif
794
+
795
+ //! Set a primitive value in a document.
796
+ /*!
797
+ \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
798
+ */
799
+ template <typename T, typename stackAllocator>
800
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
801
+ Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
802
+ return Create(document) = value;
803
+ }
804
+
805
+ //@}
806
+
807
+ //!@name Swap a value
808
+ //@{
809
+
810
+ //! Swap a value with a value in a subtree.
811
+ /*!
812
+ It creates all parents if they are not exist or types are different to the tokens.
813
+ So this function always succeeds but potentially remove existing values.
814
+
815
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
816
+ \param value Value to be swapped.
817
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
818
+ \see Create()
819
+ */
820
+ ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
821
+ return Create(root, allocator).Swap(value);
822
+ }
823
+
824
+ //! Swap a value with a value in a document.
825
+ template <typename stackAllocator>
826
+ ValueType& Swap(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
827
+ return Create(document).Swap(value);
828
+ }
829
+
830
+ //@}
831
+
832
+ //! Erase a value in a subtree.
833
+ /*!
834
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
835
+ \return Whether the resolved value is found and erased.
836
+
837
+ \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false.
838
+ */
839
+ bool Erase(ValueType& root) const {
840
+ RAPIDJSON_ASSERT(IsValid());
841
+ if (tokenCount_ == 0) // Cannot erase the root
842
+ return false;
843
+
844
+ ValueType* v = &root;
845
+ const Token* last = tokens_ + (tokenCount_ - 1);
846
+ for (const Token *t = tokens_; t != last; ++t) {
847
+ switch (v->GetType()) {
848
+ case kObjectType:
849
+ {
850
+ typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
851
+ if (m == v->MemberEnd())
852
+ return false;
853
+ v = &m->value;
854
+ }
855
+ break;
856
+ case kArrayType:
857
+ if (t->index == kPointerInvalidIndex || t->index >= v->Size())
858
+ return false;
859
+ v = &((*v)[t->index]);
860
+ break;
861
+ default:
862
+ return false;
863
+ }
864
+ }
865
+
866
+ switch (v->GetType()) {
867
+ case kObjectType:
868
+ return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
869
+ case kArrayType:
870
+ if (last->index == kPointerInvalidIndex || last->index >= v->Size())
871
+ return false;
872
+ v->Erase(v->Begin() + last->index);
873
+ return true;
874
+ default:
875
+ return false;
876
+ }
877
+ }
878
+
879
+ private:
880
+ //! Clone the content from rhs to this.
881
+ /*!
882
+ \param rhs Source pointer.
883
+ \param extraToken Extra tokens to be allocated.
884
+ \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated.
885
+ \return Start of non-occupied name buffer, for storing extra names.
886
+ */
887
+ Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
888
+ if (!allocator_) // allocator is independently owned.
889
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
890
+
891
+ size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
892
+ for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
893
+ nameBufferSize += t->length;
894
+
895
+ tokenCount_ = rhs.tokenCount_ + extraToken;
896
+ tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
897
+ nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
898
+ if (rhs.tokenCount_ > 0) {
899
+ std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
900
+ }
901
+ if (nameBufferSize > 0) {
902
+ std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
903
+ }
904
+
905
+ // Adjust pointers to name buffer
906
+ std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
907
+ for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
908
+ t->name += diff;
909
+
910
+ return nameBuffer_ + nameBufferSize;
911
+ }
912
+
913
+ //! Check whether a character should be percent-encoded.
914
+ /*!
915
+ According to RFC 3986 2.3 Unreserved Characters.
916
+ \param c The character (code unit) to be tested.
917
+ */
918
+ bool NeedPercentEncode(Ch c) const {
919
+ return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
920
+ }
921
+
922
+ //! Parse a JSON String or its URI fragment representation into tokens.
923
+ #ifndef __clang__ // -Wdocumentation
924
+ /*!
925
+ \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated.
926
+ \param length Length of the source string.
927
+ \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped.
928
+ */
929
+ #endif
930
+ void Parse(const Ch* source, size_t length) {
931
+ RAPIDJSON_ASSERT(source != NULL);
932
+ RAPIDJSON_ASSERT(nameBuffer_ == 0);
933
+ RAPIDJSON_ASSERT(tokens_ == 0);
934
+
935
+ // Create own allocator if user did not supply.
936
+ if (!allocator_)
937
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
938
+
939
+ // Count number of '/' as tokenCount
940
+ tokenCount_ = 0;
941
+ for (const Ch* s = source; s != source + length; s++)
942
+ if (*s == '/')
943
+ tokenCount_++;
944
+
945
+ Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
946
+ Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
947
+ size_t i = 0;
948
+
949
+ // Detect if it is a URI fragment
950
+ bool uriFragment = false;
951
+ if (source[i] == '#') {
952
+ uriFragment = true;
953
+ i++;
954
+ }
955
+
956
+ if (i != length && source[i] != '/') {
957
+ parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus;
958
+ goto error;
959
+ }
960
+
961
+ while (i < length) {
962
+ RAPIDJSON_ASSERT(source[i] == '/');
963
+ i++; // consumes '/'
964
+
965
+ token->name = name;
966
+ bool isNumber = true;
967
+
968
+ while (i < length && source[i] != '/') {
969
+ Ch c = source[i];
970
+ if (uriFragment) {
971
+ // Decoding percent-encoding for URI fragment
972
+ if (c == '%') {
973
+ PercentDecodeStream is(&source[i], source + length);
974
+ GenericInsituStringStream<EncodingType> os(name);
975
+ Ch* begin = os.PutBegin();
976
+ if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
977
+ parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding;
978
+ goto error;
979
+ }
980
+ size_t len = os.PutEnd(begin);
981
+ i += is.Tell() - 1;
982
+ if (len == 1)
983
+ c = *name;
984
+ else {
985
+ name += len;
986
+ isNumber = false;
987
+ i++;
988
+ continue;
989
+ }
990
+ }
991
+ else if (NeedPercentEncode(c)) {
992
+ parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode;
993
+ goto error;
994
+ }
995
+ }
996
+
997
+ i++;
998
+
999
+ // Escaping "~0" -> '~', "~1" -> '/'
1000
+ if (c == '~') {
1001
+ if (i < length) {
1002
+ c = source[i];
1003
+ if (c == '0') c = '~';
1004
+ else if (c == '1') c = '/';
1005
+ else {
1006
+ parseErrorCode_ = kPointerParseErrorInvalidEscape;
1007
+ goto error;
1008
+ }
1009
+ i++;
1010
+ }
1011
+ else {
1012
+ parseErrorCode_ = kPointerParseErrorInvalidEscape;
1013
+ goto error;
1014
+ }
1015
+ }
1016
+
1017
+ // First check for index: all of characters are digit
1018
+ if (c < '0' || c > '9')
1019
+ isNumber = false;
1020
+
1021
+ *name++ = c;
1022
+ }
1023
+ token->length = static_cast<SizeType>(name - token->name);
1024
+ if (token->length == 0)
1025
+ isNumber = false;
1026
+ *name++ = '\0'; // Null terminator
1027
+
1028
+ // Second check for index: more than one digit cannot have leading zero
1029
+ if (isNumber && token->length > 1 && token->name[0] == '0')
1030
+ isNumber = false;
1031
+
1032
+ // String to SizeType conversion
1033
+ SizeType n = 0;
1034
+ if (isNumber) {
1035
+ for (size_t j = 0; j < token->length; j++) {
1036
+ SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
1037
+ if (m < n) { // overflow detection
1038
+ isNumber = false;
1039
+ break;
1040
+ }
1041
+ n = m;
1042
+ }
1043
+ }
1044
+
1045
+ token->index = isNumber ? n : kPointerInvalidIndex;
1046
+ token++;
1047
+ }
1048
+
1049
+ RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
1050
+ parseErrorCode_ = kPointerParseErrorNone;
1051
+ return;
1052
+
1053
+ error:
1054
+ Allocator::Free(tokens_);
1055
+ nameBuffer_ = 0;
1056
+ tokens_ = 0;
1057
+ tokenCount_ = 0;
1058
+ parseErrorOffset_ = i;
1059
+ return;
1060
+ }
1061
+
1062
+ //! Stringify to string or URI fragment representation.
1063
+ /*!
1064
+ \tparam uriFragment True for stringifying to URI fragment representation. False for string representation.
1065
+ \tparam OutputStream type of output stream.
1066
+ \param os The output stream.
1067
+ */
1068
+ template<bool uriFragment, typename OutputStream>
1069
+ bool Stringify(OutputStream& os) const {
1070
+ RAPIDJSON_ASSERT(IsValid());
1071
+
1072
+ if (uriFragment)
1073
+ os.Put('#');
1074
+
1075
+ for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
1076
+ os.Put('/');
1077
+ for (size_t j = 0; j < t->length; j++) {
1078
+ Ch c = t->name[j];
1079
+ if (c == '~') {
1080
+ os.Put('~');
1081
+ os.Put('0');
1082
+ }
1083
+ else if (c == '/') {
1084
+ os.Put('~');
1085
+ os.Put('1');
1086
+ }
1087
+ else if (uriFragment && NeedPercentEncode(c)) {
1088
+ // Transcode to UTF8 sequence
1089
+ GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]);
1090
+ PercentEncodeStream<OutputStream> target(os);
1091
+ if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
1092
+ return false;
1093
+ j += source.Tell() - 1;
1094
+ }
1095
+ else
1096
+ os.Put(c);
1097
+ }
1098
+ }
1099
+ return true;
1100
+ }
1101
+
1102
+ //! A helper stream for decoding a percent-encoded sequence into code unit.
1103
+ /*!
1104
+ This stream decodes %XY triplet into code unit (0-255).
1105
+ If it encounters invalid characters, it sets output code unit as 0 and
1106
+ mark invalid, and to be checked by IsValid().
1107
+ */
1108
+ class PercentDecodeStream {
1109
+ public:
1110
+ typedef typename ValueType::Ch Ch;
1111
+
1112
+ //! Constructor
1113
+ /*!
1114
+ \param source Start of the stream
1115
+ \param end Past-the-end of the stream.
1116
+ */
1117
+ PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
1118
+
1119
+ Ch Take() {
1120
+ if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet
1121
+ valid_ = false;
1122
+ return 0;
1123
+ }
1124
+ src_++;
1125
+ Ch c = 0;
1126
+ for (int j = 0; j < 2; j++) {
1127
+ c = static_cast<Ch>(c << 4);
1128
+ Ch h = *src_;
1129
+ if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
1130
+ else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
1131
+ else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
1132
+ else {
1133
+ valid_ = false;
1134
+ return 0;
1135
+ }
1136
+ src_++;
1137
+ }
1138
+ return c;
1139
+ }
1140
+
1141
+ size_t Tell() const { return static_cast<size_t>(src_ - head_); }
1142
+ bool IsValid() const { return valid_; }
1143
+
1144
+ private:
1145
+ const Ch* src_; //!< Current read position.
1146
+ const Ch* head_; //!< Original head of the string.
1147
+ const Ch* end_; //!< Past-the-end position.
1148
+ bool valid_; //!< Whether the parsing is valid.
1149
+ };
1150
+
1151
+ //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.
1152
+ template <typename OutputStream>
1153
+ class PercentEncodeStream {
1154
+ public:
1155
+ PercentEncodeStream(OutputStream& os) : os_(os) {}
1156
+ void Put(char c) { // UTF-8 must be byte
1157
+ unsigned char u = static_cast<unsigned char>(c);
1158
+ static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1159
+ os_.Put('%');
1160
+ os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
1161
+ os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
1162
+ }
1163
+ private:
1164
+ OutputStream& os_;
1165
+ };
1166
+
1167
+ Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_.
1168
+ Allocator* ownAllocator_; //!< Allocator owned by this Pointer.
1169
+ Ch* nameBuffer_; //!< A buffer containing all names in tokens.
1170
+ Token* tokens_; //!< A list of tokens.
1171
+ size_t tokenCount_; //!< Number of tokens in tokens_.
1172
+ size_t parseErrorOffset_; //!< Offset in code unit when parsing fail.
1173
+ PointerParseErrorCode parseErrorCode_; //!< Parsing error code.
1174
+ };
1175
+
1176
+ //! GenericPointer for Value (UTF-8, default allocator).
1177
+ typedef GenericPointer<Value> Pointer;
1178
+
1179
+ //!@name Helper functions for GenericPointer
1180
+ //@{
1181
+
1182
+ //////////////////////////////////////////////////////////////////////////////
1183
+
1184
+ template <typename T>
1185
+ typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
1186
+ return pointer.Create(root, a);
1187
+ }
1188
+
1189
+ template <typename T, typename CharType, size_t N>
1190
+ typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
1191
+ return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
1192
+ }
1193
+
1194
+ // No allocator parameter
1195
+
1196
+ template <typename DocumentType>
1197
+ typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
1198
+ return pointer.Create(document);
1199
+ }
1200
+
1201
+ template <typename DocumentType, typename CharType, size_t N>
1202
+ typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
1203
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
1204
+ }
1205
+
1206
+ //////////////////////////////////////////////////////////////////////////////
1207
+
1208
+ template <typename T>
1209
+ typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1210
+ return pointer.Get(root, unresolvedTokenIndex);
1211
+ }
1212
+
1213
+ template <typename T>
1214
+ const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
1215
+ return pointer.Get(root, unresolvedTokenIndex);
1216
+ }
1217
+
1218
+ template <typename T, typename CharType, size_t N>
1219
+ typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
1220
+ return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1221
+ }
1222
+
1223
+ template <typename T, typename CharType, size_t N>
1224
+ const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
1225
+ return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
1226
+ }
1227
+
1228
+ //////////////////////////////////////////////////////////////////////////////
1229
+
1230
+ template <typename T>
1231
+ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1232
+ return pointer.GetWithDefault(root, defaultValue, a);
1233
+ }
1234
+
1235
+ template <typename T>
1236
+ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1237
+ return pointer.GetWithDefault(root, defaultValue, a);
1238
+ }
1239
+
1240
+ #if RAPIDJSON_HAS_STDSTRING
1241
+ template <typename T>
1242
+ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1243
+ return pointer.GetWithDefault(root, defaultValue, a);
1244
+ }
1245
+ #endif
1246
+
1247
+ template <typename T, typename T2>
1248
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1249
+ GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
1250
+ return pointer.GetWithDefault(root, defaultValue, a);
1251
+ }
1252
+
1253
+ template <typename T, typename CharType, size_t N>
1254
+ typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
1255
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1256
+ }
1257
+
1258
+ template <typename T, typename CharType, size_t N>
1259
+ typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
1260
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1261
+ }
1262
+
1263
+ #if RAPIDJSON_HAS_STDSTRING
1264
+ template <typename T, typename CharType, size_t N>
1265
+ typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
1266
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1267
+ }
1268
+ #endif
1269
+
1270
+ template <typename T, typename CharType, size_t N, typename T2>
1271
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1272
+ GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
1273
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
1274
+ }
1275
+
1276
+ // No allocator parameter
1277
+
1278
+ template <typename DocumentType>
1279
+ typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
1280
+ return pointer.GetWithDefault(document, defaultValue);
1281
+ }
1282
+
1283
+ template <typename DocumentType>
1284
+ typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {
1285
+ return pointer.GetWithDefault(document, defaultValue);
1286
+ }
1287
+
1288
+ #if RAPIDJSON_HAS_STDSTRING
1289
+ template <typename DocumentType>
1290
+ typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1291
+ return pointer.GetWithDefault(document, defaultValue);
1292
+ }
1293
+ #endif
1294
+
1295
+ template <typename DocumentType, typename T2>
1296
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1297
+ GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
1298
+ return pointer.GetWithDefault(document, defaultValue);
1299
+ }
1300
+
1301
+ template <typename DocumentType, typename CharType, size_t N>
1302
+ typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
1303
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1304
+ }
1305
+
1306
+ template <typename DocumentType, typename CharType, size_t N>
1307
+ typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
1308
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1309
+ }
1310
+
1311
+ #if RAPIDJSON_HAS_STDSTRING
1312
+ template <typename DocumentType, typename CharType, size_t N>
1313
+ typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1314
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1315
+ }
1316
+ #endif
1317
+
1318
+ template <typename DocumentType, typename CharType, size_t N, typename T2>
1319
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1320
+ GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
1321
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
1322
+ }
1323
+
1324
+ //////////////////////////////////////////////////////////////////////////////
1325
+
1326
+ template <typename T>
1327
+ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1328
+ return pointer.Set(root, value, a);
1329
+ }
1330
+
1331
+ template <typename T>
1332
+ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) {
1333
+ return pointer.Set(root, value, a);
1334
+ }
1335
+
1336
+ template <typename T>
1337
+ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) {
1338
+ return pointer.Set(root, value, a);
1339
+ }
1340
+
1341
+ #if RAPIDJSON_HAS_STDSTRING
1342
+ template <typename T>
1343
+ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1344
+ return pointer.Set(root, value, a);
1345
+ }
1346
+ #endif
1347
+
1348
+ template <typename T, typename T2>
1349
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1350
+ SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
1351
+ return pointer.Set(root, value, a);
1352
+ }
1353
+
1354
+ template <typename T, typename CharType, size_t N>
1355
+ typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1356
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1357
+ }
1358
+
1359
+ template <typename T, typename CharType, size_t N>
1360
+ typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
1361
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1362
+ }
1363
+
1364
+ template <typename T, typename CharType, size_t N>
1365
+ typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
1366
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1367
+ }
1368
+
1369
+ #if RAPIDJSON_HAS_STDSTRING
1370
+ template <typename T, typename CharType, size_t N>
1371
+ typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
1372
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1373
+ }
1374
+ #endif
1375
+
1376
+ template <typename T, typename CharType, size_t N, typename T2>
1377
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
1378
+ SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
1379
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
1380
+ }
1381
+
1382
+ // No allocator parameter
1383
+
1384
+ template <typename DocumentType>
1385
+ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1386
+ return pointer.Set(document, value);
1387
+ }
1388
+
1389
+ template <typename DocumentType>
1390
+ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {
1391
+ return pointer.Set(document, value);
1392
+ }
1393
+
1394
+ template <typename DocumentType>
1395
+ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) {
1396
+ return pointer.Set(document, value);
1397
+ }
1398
+
1399
+ #if RAPIDJSON_HAS_STDSTRING
1400
+ template <typename DocumentType>
1401
+ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
1402
+ return pointer.Set(document, value);
1403
+ }
1404
+ #endif
1405
+
1406
+ template <typename DocumentType, typename T2>
1407
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1408
+ SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
1409
+ return pointer.Set(document, value);
1410
+ }
1411
+
1412
+ template <typename DocumentType, typename CharType, size_t N>
1413
+ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1414
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1415
+ }
1416
+
1417
+ template <typename DocumentType, typename CharType, size_t N>
1418
+ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
1419
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1420
+ }
1421
+
1422
+ template <typename DocumentType, typename CharType, size_t N>
1423
+ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
1424
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1425
+ }
1426
+
1427
+ #if RAPIDJSON_HAS_STDSTRING
1428
+ template <typename DocumentType, typename CharType, size_t N>
1429
+ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
1430
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1431
+ }
1432
+ #endif
1433
+
1434
+ template <typename DocumentType, typename CharType, size_t N, typename T2>
1435
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
1436
+ SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
1437
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
1438
+ }
1439
+
1440
+ //////////////////////////////////////////////////////////////////////////////
1441
+
1442
+ template <typename T>
1443
+ typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
1444
+ return pointer.Swap(root, value, a);
1445
+ }
1446
+
1447
+ template <typename T, typename CharType, size_t N>
1448
+ typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
1449
+ return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
1450
+ }
1451
+
1452
+ template <typename DocumentType>
1453
+ typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
1454
+ return pointer.Swap(document, value);
1455
+ }
1456
+
1457
+ template <typename DocumentType, typename CharType, size_t N>
1458
+ typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
1459
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);
1460
+ }
1461
+
1462
+ //////////////////////////////////////////////////////////////////////////////
1463
+
1464
+ template <typename T>
1465
+ bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
1466
+ return pointer.Erase(root);
1467
+ }
1468
+
1469
+ template <typename T, typename CharType, size_t N>
1470
+ bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
1471
+ return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
1472
+ }
1473
+
1474
+ //@}
1475
+
1476
+ RAPIDJSON_NAMESPACE_END
1477
+
1478
+ #if defined(__clang__) || defined(_MSC_VER)
1479
+ RAPIDJSON_DIAG_POP
1480
+ #endif
1481
+
1482
+ #endif // RAPIDJSON_POINTER_H_