DeepCover Embedded Security in IoT: Public-key Secured Data Paths

Dependencies:   MaximInterface

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pointer.h Source File

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_