DeepCover Embedded Security in IoT: Public-key Secured Data Paths
Dependencies: MaximInterface
pointer.h
00001 // Tencent is pleased to support the open source community by making RapidJSON available. 00002 // 00003 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 00004 // 00005 // Licensed under the MIT License (the "License"); you may not use this file except 00006 // in compliance with the License. You may obtain a copy of the License at 00007 // 00008 // http://opensource.org/licenses/MIT 00009 // 00010 // Unless required by applicable law or agreed to in writing, software distributed 00011 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 00012 // CONDITIONS OF ANY KIND, either express or implied. See the License for the 00013 // specific language governing permissions and limitations under the License. 00014 00015 #ifndef RAPIDJSON_POINTER_H_ 00016 #define RAPIDJSON_POINTER_H_ 00017 00018 #include "document.h " 00019 #include "internal/itoa.h" 00020 00021 #ifdef __clang__ 00022 RAPIDJSON_DIAG_PUSH 00023 RAPIDJSON_DIAG_OFF(switch-enum) 00024 #endif 00025 00026 #ifdef _MSC_VER 00027 RAPIDJSON_DIAG_PUSH 00028 RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated 00029 #endif 00030 00031 RAPIDJSON_NAMESPACE_BEGIN 00032 00033 static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token 00034 00035 //! Error code of parsing. 00036 /*! \ingroup RAPIDJSON_ERRORS 00037 \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode 00038 */ 00039 enum PointerParseErrorCode { 00040 kPointerParseErrorNone = 0, //!< The parse is successful 00041 00042 kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/' 00043 kPointerParseErrorInvalidEscape, //!< Invalid escape 00044 kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment 00045 kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment 00046 }; 00047 00048 /////////////////////////////////////////////////////////////////////////////// 00049 // GenericPointer 00050 00051 //! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator. 00052 /*! 00053 This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer" 00054 (https://tools.ietf.org/html/rfc6901). 00055 00056 A JSON pointer is for identifying a specific value in a JSON document 00057 (GenericDocument). It can simplify coding of DOM tree manipulation, because it 00058 can access multiple-level depth of DOM tree with single API call. 00059 00060 After it parses a string representation (e.g. "/foo/0" or URI fragment 00061 representation (e.g. "#/foo/0") into its internal representation (tokens), 00062 it can be used to resolve a specific value in multiple documents, or sub-tree 00063 of documents. 00064 00065 Contrary to GenericValue, Pointer can be copy constructed and copy assigned. 00066 Apart from assignment, a Pointer cannot be modified after construction. 00067 00068 Although Pointer is very convenient, please aware that constructing Pointer 00069 involves parsing and dynamic memory allocation. A special constructor with user- 00070 supplied tokens eliminates these. 00071 00072 GenericPointer depends on GenericDocument and GenericValue. 00073 00074 \tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> > 00075 \tparam Allocator The allocator type for allocating memory for internal representation. 00076 00077 \note GenericPointer uses same encoding of ValueType. 00078 However, Allocator of GenericPointer is independent of Allocator of Value. 00079 */ 00080 template <typename ValueType, typename Allocator = CrtAllocator> 00081 class GenericPointer { 00082 public: 00083 typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value 00084 typedef typename ValueType::Ch Ch; //!< Character type from Value 00085 00086 //! A token is the basic units of internal representation. 00087 /*! 00088 A JSON pointer string representation "/foo/123" is parsed to two tokens: 00089 "foo" and 123. 123 will be represented in both numeric form and string form. 00090 They are resolved according to the actual value type (object or array). 00091 00092 For token that are not numbers, or the numeric value is out of bound 00093 (greater than limits of SizeType), they are only treated as string form 00094 (i.e. the token's index will be equal to kPointerInvalidIndex). 00095 00096 This struct is public so that user can create a Pointer without parsing and 00097 allocation, using a special constructor. 00098 */ 00099 struct Token { 00100 const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character. 00101 SizeType length; //!< Length of the name. 00102 SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex. 00103 }; 00104 00105 //!@name Constructors and destructor. 00106 //@{ 00107 00108 //! Default constructor. 00109 GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} 00110 00111 //! Constructor that parses a string or URI fragment representation. 00112 /*! 00113 \param source A null-terminated, string or URI fragment representation of JSON pointer. 00114 \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. 00115 */ 00116 explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { 00117 Parse(source, internal::StrLen(source)); 00118 } 00119 00120 #if RAPIDJSON_HAS_STDSTRING 00121 //! Constructor that parses a string or URI fragment representation. 00122 /*! 00123 \param source A string or URI fragment representation of JSON pointer. 00124 \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. 00125 \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. 00126 */ 00127 explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { 00128 Parse(source.c_str(), source.size()); 00129 } 00130 #endif 00131 00132 //! Constructor that parses a string or URI fragment representation, with length of the source string. 00133 /*! 00134 \param source A string or URI fragment representation of JSON pointer. 00135 \param length Length of source. 00136 \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. 00137 \note Slightly faster than the overload without length. 00138 */ 00139 GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { 00140 Parse(source, length); 00141 } 00142 00143 //! Constructor with user-supplied tokens. 00144 /*! 00145 This constructor let user supplies const array of tokens. 00146 This prevents the parsing process and eliminates allocation. 00147 This is preferred for memory constrained environments. 00148 00149 \param tokens An constant array of tokens representing the JSON pointer. 00150 \param tokenCount Number of tokens. 00151 00152 \b Example 00153 \code 00154 #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } 00155 #define INDEX(i) { #i, sizeof(#i) - 1, i } 00156 00157 static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; 00158 static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); 00159 // Equivalent to static const Pointer p("/foo/123"); 00160 00161 #undef NAME 00162 #undef INDEX 00163 \endcode 00164 */ 00165 GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} 00166 00167 //! Copy constructor. 00168 GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { 00169 *this = rhs; 00170 } 00171 00172 //! Destructor. 00173 ~GenericPointer() { 00174 if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. 00175 Allocator::Free(tokens_); 00176 RAPIDJSON_DELETE(ownAllocator_); 00177 } 00178 00179 //! Assignment operator. 00180 GenericPointer& operator=(const GenericPointer& rhs) { 00181 if (this != &rhs) { 00182 // Do not delete ownAllcator 00183 if (nameBuffer_) 00184 Allocator::Free(tokens_); 00185 00186 tokenCount_ = rhs.tokenCount_; 00187 parseErrorOffset_ = rhs.parseErrorOffset_; 00188 parseErrorCode_ = rhs.parseErrorCode_; 00189 00190 if (rhs.nameBuffer_) 00191 CopyFromRaw(rhs); // Normally parsed tokens. 00192 else { 00193 tokens_ = rhs.tokens_; // User supplied const tokens. 00194 nameBuffer_ = 0; 00195 } 00196 } 00197 return *this; 00198 } 00199 00200 //@} 00201 00202 //!@name Append token 00203 //@{ 00204 00205 //! Append a token and return a new Pointer 00206 /*! 00207 \param token Token to be appended. 00208 \param allocator Allocator for the newly return Pointer. 00209 \return A new Pointer with appended token. 00210 */ 00211 GenericPointer Append(const Token& token, Allocator* allocator = 0) const { 00212 GenericPointer r; 00213 r.allocator_ = allocator; 00214 Ch *p = r.CopyFromRaw(*this, 1, token.length + 1); 00215 std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch)); 00216 r.tokens_[tokenCount_].name = p; 00217 r.tokens_[tokenCount_].length = token.length; 00218 r.tokens_[tokenCount_].index = token.index; 00219 return r; 00220 } 00221 00222 //! Append a name token with length, and return a new Pointer 00223 /*! 00224 \param name Name to be appended. 00225 \param length Length of name. 00226 \param allocator Allocator for the newly return Pointer. 00227 \return A new Pointer with appended token. 00228 */ 00229 GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const { 00230 Token token = { name, length, kPointerInvalidIndex }; 00231 return Append(token, allocator); 00232 } 00233 00234 //! Append a name token without length, and return a new Pointer 00235 /*! 00236 \param name Name (const Ch*) to be appended. 00237 \param allocator Allocator for the newly return Pointer. 00238 \return A new Pointer with appended token. 00239 */ 00240 template <typename T> 00241 RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer)) 00242 Append(T* name, Allocator* allocator = 0) const { 00243 return Append(name, StrLen(name), allocator); 00244 } 00245 00246 #if RAPIDJSON_HAS_STDSTRING 00247 //! Append a name token, and return a new Pointer 00248 /*! 00249 \param name Name to be appended. 00250 \param allocator Allocator for the newly return Pointer. 00251 \return A new Pointer with appended token. 00252 */ 00253 GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const { 00254 return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator); 00255 } 00256 #endif 00257 00258 //! Append a index token, and return a new Pointer 00259 /*! 00260 \param index Index to be appended. 00261 \param allocator Allocator for the newly return Pointer. 00262 \return A new Pointer with appended token. 00263 */ 00264 GenericPointer Append(SizeType index, Allocator* allocator = 0) const { 00265 char buffer[21]; 00266 char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer); 00267 SizeType length = static_cast<SizeType>(end - buffer); 00268 buffer[length] = '\0'; 00269 00270 if (sizeof(Ch) == 1) { 00271 Token token = { reinterpret_cast<Ch*>(buffer), length, index }; 00272 return Append(token, allocator); 00273 } 00274 else { 00275 Ch name[21]; 00276 for (size_t i = 0; i <= length; i++) 00277 name[i] = buffer[i]; 00278 Token token = { name, length, index }; 00279 return Append(token, allocator); 00280 } 00281 } 00282 00283 //! Append a token by value, and return a new Pointer 00284 /*! 00285 \param token token to be appended. 00286 \param allocator Allocator for the newly return Pointer. 00287 \return A new Pointer with appended token. 00288 */ 00289 GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const { 00290 if (token.IsString()) 00291 return Append(token.GetString(), token.GetStringLength(), allocator); 00292 else { 00293 RAPIDJSON_ASSERT(token.IsUint64()); 00294 RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0)); 00295 return Append(static_cast<SizeType>(token.GetUint64()), allocator); 00296 } 00297 } 00298 00299 //!@name Handling Parse Error 00300 //@{ 00301 00302 //! Check whether this is a valid pointer. 00303 bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; } 00304 00305 //! Get the parsing error offset in code unit. 00306 size_t GetParseErrorOffset() const { return parseErrorOffset_; } 00307 00308 //! Get the parsing error code. 00309 PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; } 00310 00311 //@} 00312 00313 //! Get the allocator of this pointer. 00314 Allocator& GetAllocator() { return *allocator_; } 00315 00316 //!@name Tokens 00317 //@{ 00318 00319 //! Get the token array (const version only). 00320 const Token* GetTokens() const { return tokens_; } 00321 00322 //! Get the number of tokens. 00323 size_t GetTokenCount() const { return tokenCount_; } 00324 00325 //@} 00326 00327 //!@name Equality/inequality operators 00328 //@{ 00329 00330 //! Equality operator. 00331 /*! 00332 \note When any pointers are invalid, always returns false. 00333 */ 00334 bool operator==(const GenericPointer& rhs) const { 00335 if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_) 00336 return false; 00337 00338 for (size_t i = 0; i < tokenCount_; i++) { 00339 if (tokens_[i].index != rhs.tokens_[i].index || 00340 tokens_[i].length != rhs.tokens_[i].length || 00341 (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0)) 00342 { 00343 return false; 00344 } 00345 } 00346 00347 return true; 00348 } 00349 00350 //! Inequality operator. 00351 /*! 00352 \note When any pointers are invalid, always returns true. 00353 */ 00354 bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); } 00355 00356 //@} 00357 00358 //!@name Stringify 00359 //@{ 00360 00361 //! Stringify the pointer into string representation. 00362 /*! 00363 \tparam OutputStream Type of output stream. 00364 \param os The output stream. 00365 */ 00366 template<typename OutputStream> 00367 bool Stringify(OutputStream& os) const { 00368 return Stringify<false, OutputStream>(os); 00369 } 00370 00371 //! Stringify the pointer into URI fragment representation. 00372 /*! 00373 \tparam OutputStream Type of output stream. 00374 \param os The output stream. 00375 */ 00376 template<typename OutputStream> 00377 bool StringifyUriFragment(OutputStream& os) const { 00378 return Stringify<true, OutputStream>(os); 00379 } 00380 00381 //@} 00382 00383 //!@name Create value 00384 //@{ 00385 00386 //! Create a value in a subtree. 00387 /*! 00388 If the value is not exist, it creates all parent values and a JSON Null value. 00389 So it always succeed and return the newly created or existing value. 00390 00391 Remind that it may change types of parents according to tokens, so it 00392 potentially removes previously stored values. For example, if a document 00393 was an array, and "/foo" is used to create a value, then the document 00394 will be changed to an object, and all existing array elements are lost. 00395 00396 \param root Root value of a DOM subtree to be resolved. It can be any value other than document root. 00397 \param allocator Allocator for creating the values if the specified value or its parents are not exist. 00398 \param alreadyExist If non-null, it stores whether the resolved value is already exist. 00399 \return The resolved newly created (a JSON Null value), or already exists value. 00400 */ 00401 ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const { 00402 RAPIDJSON_ASSERT(IsValid()); 00403 ValueType* v = &root; 00404 bool exist = true; 00405 for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { 00406 if (v->IsArray() && t->name[0] == '-' && t->length == 1) { 00407 v->PushBack(ValueType().Move(), allocator); 00408 v = &((*v)[v->Size() - 1]); 00409 exist = false; 00410 } 00411 else { 00412 if (t->index == kPointerInvalidIndex) { // must be object name 00413 if (!v->IsObject()) 00414 v->SetObject(); // Change to Object 00415 } 00416 else { // object name or array index 00417 if (!v->IsArray() && !v->IsObject()) 00418 v->SetArray(); // Change to Array 00419 } 00420 00421 if (v->IsArray()) { 00422 if (t->index >= v->Size()) { 00423 v->Reserve(t->index + 1, allocator); 00424 while (t->index >= v->Size()) 00425 v->PushBack(ValueType().Move(), allocator); 00426 exist = false; 00427 } 00428 v = &((*v)[t->index]); 00429 } 00430 else { 00431 typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length)); 00432 if (m == v->MemberEnd()) { 00433 v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator); 00434 v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end 00435 exist = false; 00436 } 00437 else 00438 v = &m->value; 00439 } 00440 } 00441 } 00442 00443 if (alreadyExist) 00444 *alreadyExist = exist; 00445 00446 return *v; 00447 } 00448 00449 //! Creates a value in a document. 00450 /*! 00451 \param document A document to be resolved. 00452 \param alreadyExist If non-null, it stores whether the resolved value is already exist. 00453 \return The resolved newly created, or already exists value. 00454 */ 00455 template <typename stackAllocator> 00456 ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const { 00457 return Create(document, document.GetAllocator(), alreadyExist); 00458 } 00459 00460 //@} 00461 00462 //!@name Query value 00463 //@{ 00464 00465 //! Query a value in a subtree. 00466 /*! 00467 \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. 00468 \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. 00469 \return Pointer to the value if it can be resolved. Otherwise null. 00470 00471 \note 00472 There are only 3 situations when a value cannot be resolved: 00473 1. A value in the path is not an array nor object. 00474 2. An object value does not contain the token. 00475 3. A token is out of range of an array value. 00476 00477 Use unresolvedTokenIndex to retrieve the token index. 00478 */ 00479 ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const { 00480 RAPIDJSON_ASSERT(IsValid()); 00481 ValueType* v = &root; 00482 for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { 00483 switch (v->GetType()) { 00484 case kObjectType: 00485 { 00486 typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length)); 00487 if (m == v->MemberEnd()) 00488 break; 00489 v = &m->value; 00490 } 00491 continue; 00492 case kArrayType: 00493 if (t->index == kPointerInvalidIndex || t->index >= v->Size()) 00494 break; 00495 v = &((*v)[t->index]); 00496 continue; 00497 default: 00498 break; 00499 } 00500 00501 // Error: unresolved token 00502 if (unresolvedTokenIndex) 00503 *unresolvedTokenIndex = static_cast<size_t>(t - tokens_); 00504 return 0; 00505 } 00506 return v; 00507 } 00508 00509 //! Query a const value in a const subtree. 00510 /*! 00511 \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. 00512 \return Pointer to the value if it can be resolved. Otherwise null. 00513 */ 00514 const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const { 00515 return Get(const_cast<ValueType&>(root), unresolvedTokenIndex); 00516 } 00517 00518 //@} 00519 00520 //!@name Query a value with default 00521 //@{ 00522 00523 //! Query a value in a subtree with default value. 00524 /*! 00525 Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value. 00526 So that this function always succeed. 00527 00528 \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. 00529 \param defaultValue Default value to be cloned if the value was not exists. 00530 \param allocator Allocator for creating the values if the specified value or its parents are not exist. 00531 \see Create() 00532 */ 00533 ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { 00534 bool alreadyExist; 00535 Value& v = Create(root, allocator, &alreadyExist); 00536 return alreadyExist ? v : v.CopyFrom(defaultValue, allocator); 00537 } 00538 00539 //! Query a value in a subtree with default null-terminated string. 00540 ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const { 00541 bool alreadyExist; 00542 Value& v = Create(root, allocator, &alreadyExist); 00543 return alreadyExist ? v : v.SetString(defaultValue, allocator); 00544 } 00545 00546 #if RAPIDJSON_HAS_STDSTRING 00547 //! Query a value in a subtree with default std::basic_string. 00548 ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const { 00549 bool alreadyExist; 00550 Value& v = Create(root, allocator, &alreadyExist); 00551 return alreadyExist ? v : v.SetString(defaultValue, allocator); 00552 } 00553 #endif 00554 00555 //! Query a value in a subtree with default primitive value. 00556 /*! 00557 \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool 00558 */ 00559 template <typename T> 00560 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) 00561 GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { 00562 return GetWithDefault(root, ValueType(defaultValue).Move(), allocator); 00563 } 00564 00565 //! Query a value in a document with default value. 00566 template <typename stackAllocator> 00567 ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const { 00568 return GetWithDefault(document, defaultValue, document.GetAllocator()); 00569 } 00570 00571 //! Query a value in a document with default null-terminated string. 00572 template <typename stackAllocator> 00573 ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const { 00574 return GetWithDefault(document, defaultValue, document.GetAllocator()); 00575 } 00576 00577 #if RAPIDJSON_HAS_STDSTRING 00578 //! Query a value in a document with default std::basic_string. 00579 template <typename stackAllocator> 00580 ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const { 00581 return GetWithDefault(document, defaultValue, document.GetAllocator()); 00582 } 00583 #endif 00584 00585 //! Query a value in a document with default primitive value. 00586 /*! 00587 \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool 00588 */ 00589 template <typename T, typename stackAllocator> 00590 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) 00591 GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const { 00592 return GetWithDefault(document, defaultValue, document.GetAllocator()); 00593 } 00594 00595 //@} 00596 00597 //!@name Set a value 00598 //@{ 00599 00600 //! Set a value in a subtree, with move semantics. 00601 /*! 00602 It creates all parents if they are not exist or types are different to the tokens. 00603 So this function always succeeds but potentially remove existing values. 00604 00605 \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. 00606 \param value Value to be set. 00607 \param allocator Allocator for creating the values if the specified value or its parents are not exist. 00608 \see Create() 00609 */ 00610 ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { 00611 return Create(root, allocator) = value; 00612 } 00613 00614 //! Set a value in a subtree, with copy semantics. 00615 ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const { 00616 return Create(root, allocator).CopyFrom(value, allocator); 00617 } 00618 00619 //! Set a null-terminated string in a subtree. 00620 ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const { 00621 return Create(root, allocator) = ValueType(value, allocator).Move(); 00622 } 00623 00624 #if RAPIDJSON_HAS_STDSTRING 00625 //! Set a std::basic_string in a subtree. 00626 ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const { 00627 return Create(root, allocator) = ValueType(value, allocator).Move(); 00628 } 00629 #endif 00630 00631 //! Set a primitive value in a subtree. 00632 /*! 00633 \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool 00634 */ 00635 template <typename T> 00636 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) 00637 Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { 00638 return Create(root, allocator) = ValueType(value).Move(); 00639 } 00640 00641 //! Set a value in a document, with move semantics. 00642 template <typename stackAllocator> 00643 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const { 00644 return Create(document) = value; 00645 } 00646 00647 //! Set a value in a document, with copy semantics. 00648 template <typename stackAllocator> 00649 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const { 00650 return Create(document).CopyFrom(value, document.GetAllocator()); 00651 } 00652 00653 //! Set a null-terminated string in a document. 00654 template <typename stackAllocator> 00655 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* value) const { 00656 return Create(document) = ValueType(value, document.GetAllocator()).Move(); 00657 } 00658 00659 #if RAPIDJSON_HAS_STDSTRING 00660 //! Sets a std::basic_string in a document. 00661 template <typename stackAllocator> 00662 ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const { 00663 return Create(document) = ValueType(value, document.GetAllocator()).Move(); 00664 } 00665 #endif 00666 00667 //! Set a primitive value in a document. 00668 /*! 00669 \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool 00670 */ 00671 template <typename T, typename stackAllocator> 00672 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) 00673 Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const { 00674 return Create(document) = value; 00675 } 00676 00677 //@} 00678 00679 //!@name Swap a value 00680 //@{ 00681 00682 //! Swap a value with a value in a subtree. 00683 /*! 00684 It creates all parents if they are not exist or types are different to the tokens. 00685 So this function always succeeds but potentially remove existing values. 00686 00687 \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. 00688 \param value Value to be swapped. 00689 \param allocator Allocator for creating the values if the specified value or its parents are not exist. 00690 \see Create() 00691 */ 00692 ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { 00693 return Create(root, allocator).Swap(value); 00694 } 00695 00696 //! Swap a value with a value in a document. 00697 template <typename stackAllocator> 00698 ValueType& Swap(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const { 00699 return Create(document).Swap(value); 00700 } 00701 00702 //@} 00703 00704 //! Erase a value in a subtree. 00705 /*! 00706 \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. 00707 \return Whether the resolved value is found and erased. 00708 00709 \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false. 00710 */ 00711 bool Erase(ValueType& root) const { 00712 RAPIDJSON_ASSERT(IsValid()); 00713 if (tokenCount_ == 0) // Cannot erase the root 00714 return false; 00715 00716 ValueType* v = &root; 00717 const Token* last = tokens_ + (tokenCount_ - 1); 00718 for (const Token *t = tokens_; t != last; ++t) { 00719 switch (v->GetType()) { 00720 case kObjectType: 00721 { 00722 typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length)); 00723 if (m == v->MemberEnd()) 00724 return false; 00725 v = &m->value; 00726 } 00727 break; 00728 case kArrayType: 00729 if (t->index == kPointerInvalidIndex || t->index >= v->Size()) 00730 return false; 00731 v = &((*v)[t->index]); 00732 break; 00733 default: 00734 return false; 00735 } 00736 } 00737 00738 switch (v->GetType()) { 00739 case kObjectType: 00740 return v->EraseMember(GenericStringRef<Ch>(last->name, last->length)); 00741 case kArrayType: 00742 if (last->index == kPointerInvalidIndex || last->index >= v->Size()) 00743 return false; 00744 v->Erase(v->Begin() + last->index); 00745 return true; 00746 default: 00747 return false; 00748 } 00749 } 00750 00751 private: 00752 //! Clone the content from rhs to this. 00753 /*! 00754 \param rhs Source pointer. 00755 \param extraToken Extra tokens to be allocated. 00756 \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated. 00757 \return Start of non-occupied name buffer, for storing extra names. 00758 */ 00759 Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { 00760 if (!allocator_) // allocator is independently owned. 00761 ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); 00762 00763 size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens 00764 for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) 00765 nameBufferSize += t->length; 00766 00767 tokenCount_ = rhs.tokenCount_ + extraToken; 00768 tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); 00769 nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_); 00770 if (rhs.tokenCount_ > 0) { 00771 std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); 00772 } 00773 if (nameBufferSize > 0) { 00774 std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); 00775 } 00776 00777 // Adjust pointers to name buffer 00778 std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; 00779 for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) 00780 t->name += diff; 00781 00782 return nameBuffer_ + nameBufferSize; 00783 } 00784 00785 //! Check whether a character should be percent-encoded. 00786 /*! 00787 According to RFC 3986 2.3 Unreserved Characters. 00788 \param c The character (code unit) to be tested. 00789 */ 00790 bool NeedPercentEncode(Ch c) const { 00791 return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~'); 00792 } 00793 00794 //! Parse a JSON String or its URI fragment representation into tokens. 00795 #ifndef __clang__ // -Wdocumentation 00796 /*! 00797 \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated. 00798 \param length Length of the source string. 00799 \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped. 00800 */ 00801 #endif 00802 void Parse(const Ch* source, size_t length) { 00803 RAPIDJSON_ASSERT(source != NULL); 00804 RAPIDJSON_ASSERT(nameBuffer_ == 0); 00805 RAPIDJSON_ASSERT(tokens_ == 0); 00806 00807 // Create own allocator if user did not supply. 00808 if (!allocator_) 00809 ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); 00810 00811 // Count number of '/' as tokenCount 00812 tokenCount_ = 0; 00813 for (const Ch* s = source; s != source + length; s++) 00814 if (*s == '/') 00815 tokenCount_++; 00816 00817 Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch))); 00818 Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_); 00819 size_t i = 0; 00820 00821 // Detect if it is a URI fragment 00822 bool uriFragment = false; 00823 if (source[i] == '#') { 00824 uriFragment = true; 00825 i++; 00826 } 00827 00828 if (i != length && source[i] != '/') { 00829 parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus; 00830 goto error; 00831 } 00832 00833 while (i < length) { 00834 RAPIDJSON_ASSERT(source[i] == '/'); 00835 i++; // consumes '/' 00836 00837 token->name = name; 00838 bool isNumber = true; 00839 00840 while (i < length && source[i] != '/') { 00841 Ch c = source[i]; 00842 if (uriFragment) { 00843 // Decoding percent-encoding for URI fragment 00844 if (c == '%') { 00845 PercentDecodeStream is(&source[i], source + length); 00846 GenericInsituStringStream<EncodingType> os(name); 00847 Ch* begin = os.PutBegin(); 00848 if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) { 00849 parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; 00850 goto error; 00851 } 00852 size_t len = os.PutEnd(begin); 00853 i += is.Tell() - 1; 00854 if (len == 1) 00855 c = *name; 00856 else { 00857 name += len; 00858 isNumber = false; 00859 i++; 00860 continue; 00861 } 00862 } 00863 else if (NeedPercentEncode(c)) { 00864 parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode; 00865 goto error; 00866 } 00867 } 00868 00869 i++; 00870 00871 // Escaping "~0" -> '~', "~1" -> '/' 00872 if (c == '~') { 00873 if (i < length) { 00874 c = source[i]; 00875 if (c == '0') c = '~'; 00876 else if (c == '1') c = '/'; 00877 else { 00878 parseErrorCode_ = kPointerParseErrorInvalidEscape; 00879 goto error; 00880 } 00881 i++; 00882 } 00883 else { 00884 parseErrorCode_ = kPointerParseErrorInvalidEscape; 00885 goto error; 00886 } 00887 } 00888 00889 // First check for index: all of characters are digit 00890 if (c < '0' || c > '9') 00891 isNumber = false; 00892 00893 *name++ = c; 00894 } 00895 token->length = static_cast<SizeType>(name - token->name); 00896 if (token->length == 0) 00897 isNumber = false; 00898 *name++ = '\0'; // Null terminator 00899 00900 // Second check for index: more than one digit cannot have leading zero 00901 if (isNumber && token->length > 1 && token->name[0] == '0') 00902 isNumber = false; 00903 00904 // String to SizeType conversion 00905 SizeType n = 0; 00906 if (isNumber) { 00907 for (size_t j = 0; j < token->length; j++) { 00908 SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0'); 00909 if (m < n) { // overflow detection 00910 isNumber = false; 00911 break; 00912 } 00913 n = m; 00914 } 00915 } 00916 00917 token->index = isNumber ? n : kPointerInvalidIndex; 00918 token++; 00919 } 00920 00921 RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer 00922 parseErrorCode_ = kPointerParseErrorNone; 00923 return; 00924 00925 error: 00926 Allocator::Free(tokens_); 00927 nameBuffer_ = 0; 00928 tokens_ = 0; 00929 tokenCount_ = 0; 00930 parseErrorOffset_ = i; 00931 return; 00932 } 00933 00934 //! Stringify to string or URI fragment representation. 00935 /*! 00936 \tparam uriFragment True for stringifying to URI fragment representation. False for string representation. 00937 \tparam OutputStream type of output stream. 00938 \param os The output stream. 00939 */ 00940 template<bool uriFragment, typename OutputStream> 00941 bool Stringify(OutputStream& os) const { 00942 RAPIDJSON_ASSERT(IsValid()); 00943 00944 if (uriFragment) 00945 os.Put('#'); 00946 00947 for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { 00948 os.Put('/'); 00949 for (size_t j = 0; j < t->length; j++) { 00950 Ch c = t->name[j]; 00951 if (c == '~') { 00952 os.Put('~'); 00953 os.Put('0'); 00954 } 00955 else if (c == '/') { 00956 os.Put('~'); 00957 os.Put('1'); 00958 } 00959 else if (uriFragment && NeedPercentEncode(c)) { 00960 // Transcode to UTF8 sequence 00961 GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]); 00962 PercentEncodeStream<OutputStream> target(os); 00963 if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target)) 00964 return false; 00965 j += source.Tell() - 1; 00966 } 00967 else 00968 os.Put(c); 00969 } 00970 } 00971 return true; 00972 } 00973 00974 //! A helper stream for decoding a percent-encoded sequence into code unit. 00975 /*! 00976 This stream decodes %XY triplet into code unit (0-255). 00977 If it encounters invalid characters, it sets output code unit as 0 and 00978 mark invalid, and to be checked by IsValid(). 00979 */ 00980 class PercentDecodeStream { 00981 public: 00982 typedef typename ValueType::Ch Ch; 00983 00984 //! Constructor 00985 /*! 00986 \param source Start of the stream 00987 \param end Past-the-end of the stream. 00988 */ 00989 PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {} 00990 00991 Ch Take() { 00992 if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet 00993 valid_ = false; 00994 return 0; 00995 } 00996 src_++; 00997 Ch c = 0; 00998 for (int j = 0; j < 2; j++) { 00999 c = static_cast<Ch>(c << 4); 01000 Ch h = *src_; 01001 if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0'); 01002 else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10); 01003 else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10); 01004 else { 01005 valid_ = false; 01006 return 0; 01007 } 01008 src_++; 01009 } 01010 return c; 01011 } 01012 01013 size_t Tell() const { return static_cast<size_t>(src_ - head_); } 01014 bool IsValid() const { return valid_; } 01015 01016 private: 01017 const Ch* src_; //!< Current read position. 01018 const Ch* head_; //!< Original head of the string. 01019 const Ch* end_; //!< Past-the-end position. 01020 bool valid_; //!< Whether the parsing is valid. 01021 }; 01022 01023 //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence. 01024 template <typename OutputStream> 01025 class PercentEncodeStream { 01026 public: 01027 PercentEncodeStream(OutputStream& os) : os_(os) {} 01028 void Put(char c) { // UTF-8 must be byte 01029 unsigned char u = static_cast<unsigned char>(c); 01030 static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 01031 os_.Put('%'); 01032 os_.Put(hexDigits[u >> 4]); 01033 os_.Put(hexDigits[u & 15]); 01034 } 01035 private: 01036 OutputStream& os_; 01037 }; 01038 01039 Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. 01040 Allocator* ownAllocator_; //!< Allocator owned by this Pointer. 01041 Ch* nameBuffer_; //!< A buffer containing all names in tokens. 01042 Token* tokens_; //!< A list of tokens. 01043 size_t tokenCount_; //!< Number of tokens in tokens_. 01044 size_t parseErrorOffset_; //!< Offset in code unit when parsing fail. 01045 PointerParseErrorCode parseErrorCode_; //!< Parsing error code. 01046 }; 01047 01048 //! GenericPointer for Value (UTF-8, default allocator). 01049 typedef GenericPointer<Value> Pointer; 01050 01051 //!@name Helper functions for GenericPointer 01052 //@{ 01053 01054 ////////////////////////////////////////////////////////////////////////////// 01055 01056 template <typename T> 01057 typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) { 01058 return pointer.Create(root, a); 01059 } 01060 01061 template <typename T, typename CharType, size_t N> 01062 typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { 01063 return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a); 01064 } 01065 01066 // No allocator parameter 01067 01068 template <typename DocumentType> 01069 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) { 01070 return pointer.Create(document); 01071 } 01072 01073 template <typename DocumentType, typename CharType, size_t N> 01074 typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) { 01075 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document); 01076 } 01077 01078 ////////////////////////////////////////////////////////////////////////////// 01079 01080 template <typename T> 01081 typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) { 01082 return pointer.Get(root, unresolvedTokenIndex); 01083 } 01084 01085 template <typename T> 01086 const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) { 01087 return pointer.Get(root, unresolvedTokenIndex); 01088 } 01089 01090 template <typename T, typename CharType, size_t N> 01091 typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) { 01092 return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex); 01093 } 01094 01095 template <typename T, typename CharType, size_t N> 01096 const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) { 01097 return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex); 01098 } 01099 01100 ////////////////////////////////////////////////////////////////////////////// 01101 01102 template <typename T> 01103 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { 01104 return pointer.GetWithDefault(root, defaultValue, a); 01105 } 01106 01107 template <typename T> 01108 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) { 01109 return pointer.GetWithDefault(root, defaultValue, a); 01110 } 01111 01112 #if RAPIDJSON_HAS_STDSTRING 01113 template <typename T> 01114 typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) { 01115 return pointer.GetWithDefault(root, defaultValue, a); 01116 } 01117 #endif 01118 01119 template <typename T, typename T2> 01120 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) 01121 GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) { 01122 return pointer.GetWithDefault(root, defaultValue, a); 01123 } 01124 01125 template <typename T, typename CharType, size_t N> 01126 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { 01127 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); 01128 } 01129 01130 template <typename T, typename CharType, size_t N> 01131 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { 01132 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); 01133 } 01134 01135 #if RAPIDJSON_HAS_STDSTRING 01136 template <typename T, typename CharType, size_t N> 01137 typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) { 01138 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); 01139 } 01140 #endif 01141 01142 template <typename T, typename CharType, size_t N, typename T2> 01143 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) 01144 GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) { 01145 return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); 01146 } 01147 01148 // No allocator parameter 01149 01150 template <typename DocumentType> 01151 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) { 01152 return pointer.GetWithDefault(document, defaultValue); 01153 } 01154 01155 template <typename DocumentType> 01156 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) { 01157 return pointer.GetWithDefault(document, defaultValue); 01158 } 01159 01160 #if RAPIDJSON_HAS_STDSTRING 01161 template <typename DocumentType> 01162 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) { 01163 return pointer.GetWithDefault(document, defaultValue); 01164 } 01165 #endif 01166 01167 template <typename DocumentType, typename T2> 01168 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) 01169 GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) { 01170 return pointer.GetWithDefault(document, defaultValue); 01171 } 01172 01173 template <typename DocumentType, typename CharType, size_t N> 01174 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) { 01175 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); 01176 } 01177 01178 template <typename DocumentType, typename CharType, size_t N> 01179 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) { 01180 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); 01181 } 01182 01183 #if RAPIDJSON_HAS_STDSTRING 01184 template <typename DocumentType, typename CharType, size_t N> 01185 typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) { 01186 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); 01187 } 01188 #endif 01189 01190 template <typename DocumentType, typename CharType, size_t N, typename T2> 01191 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) 01192 GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) { 01193 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); 01194 } 01195 01196 ////////////////////////////////////////////////////////////////////////////// 01197 01198 template <typename T> 01199 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { 01200 return pointer.Set(root, value, a); 01201 } 01202 01203 template <typename T> 01204 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) { 01205 return pointer.Set(root, value, a); 01206 } 01207 01208 template <typename T> 01209 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) { 01210 return pointer.Set(root, value, a); 01211 } 01212 01213 #if RAPIDJSON_HAS_STDSTRING 01214 template <typename T> 01215 typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) { 01216 return pointer.Set(root, value, a); 01217 } 01218 #endif 01219 01220 template <typename T, typename T2> 01221 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) 01222 SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) { 01223 return pointer.Set(root, value, a); 01224 } 01225 01226 template <typename T, typename CharType, size_t N> 01227 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { 01228 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); 01229 } 01230 01231 template <typename T, typename CharType, size_t N> 01232 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) { 01233 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); 01234 } 01235 01236 template <typename T, typename CharType, size_t N> 01237 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { 01238 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); 01239 } 01240 01241 #if RAPIDJSON_HAS_STDSTRING 01242 template <typename T, typename CharType, size_t N> 01243 typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) { 01244 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); 01245 } 01246 #endif 01247 01248 template <typename T, typename CharType, size_t N, typename T2> 01249 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) 01250 SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) { 01251 return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); 01252 } 01253 01254 // No allocator parameter 01255 01256 template <typename DocumentType> 01257 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) { 01258 return pointer.Set(document, value); 01259 } 01260 01261 template <typename DocumentType> 01262 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) { 01263 return pointer.Set(document, value); 01264 } 01265 01266 template <typename DocumentType> 01267 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) { 01268 return pointer.Set(document, value); 01269 } 01270 01271 #if RAPIDJSON_HAS_STDSTRING 01272 template <typename DocumentType> 01273 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) { 01274 return pointer.Set(document, value); 01275 } 01276 #endif 01277 01278 template <typename DocumentType, typename T2> 01279 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) 01280 SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) { 01281 return pointer.Set(document, value); 01282 } 01283 01284 template <typename DocumentType, typename CharType, size_t N> 01285 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { 01286 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); 01287 } 01288 01289 template <typename DocumentType, typename CharType, size_t N> 01290 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) { 01291 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); 01292 } 01293 01294 template <typename DocumentType, typename CharType, size_t N> 01295 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) { 01296 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); 01297 } 01298 01299 #if RAPIDJSON_HAS_STDSTRING 01300 template <typename DocumentType, typename CharType, size_t N> 01301 typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) { 01302 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); 01303 } 01304 #endif 01305 01306 template <typename DocumentType, typename CharType, size_t N, typename T2> 01307 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) 01308 SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) { 01309 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); 01310 } 01311 01312 ////////////////////////////////////////////////////////////////////////////// 01313 01314 template <typename T> 01315 typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { 01316 return pointer.Swap(root, value, a); 01317 } 01318 01319 template <typename T, typename CharType, size_t N> 01320 typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { 01321 return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a); 01322 } 01323 01324 template <typename DocumentType> 01325 typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) { 01326 return pointer.Swap(document, value); 01327 } 01328 01329 template <typename DocumentType, typename CharType, size_t N> 01330 typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { 01331 return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value); 01332 } 01333 01334 ////////////////////////////////////////////////////////////////////////////// 01335 01336 template <typename T> 01337 bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) { 01338 return pointer.Erase(root); 01339 } 01340 01341 template <typename T, typename CharType, size_t N> 01342 bool EraseValueByPointer(T& root, const CharType(&source)[N]) { 01343 return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root); 01344 } 01345 01346 //@} 01347 01348 RAPIDJSON_NAMESPACE_END 01349 01350 #ifdef __clang__ 01351 RAPIDJSON_DIAG_POP 01352 #endif 01353 01354 #ifdef _MSC_VER 01355 RAPIDJSON_DIAG_POP 01356 #endif 01357 01358 #endif // RAPIDJSON_POINTER_H_
Generated on Tue Jul 12 2022 12:06:49 by 1.7.2