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

Dependencies:   MaximInterface

The MAXREFDES155# is an internet-of-things (IoT) embedded-security reference design, built to authenticate and control a sensing node using elliptic-curve-based public-key cryptography with control and notification from a web server.

The hardware includes an ARM® mbed™ shield and attached sensor endpoint. The shield contains a DS2476 DeepCover® ECDSA/SHA-2 coprocessor, Wifi communication, LCD push-button controls, and status LEDs. The sensor endpoint is attached to the shield using a 300mm cable and contains a DS28C36 DeepCover ECDSA/SHA-2 authenticator, IR-thermal sensor, and aiming laser for the IR sensor. The MAXREFDES155# is equipped with a standard Arduino® form-factor shield connector for immediate testing using an mbed board such as the MAX32600MBED#. The combination of these two devices represent an IoT device. Communication to the web server is accomplished with the shield Wifi circuitry. Communication from the shield to the attached sensor module is accomplished over I2C . The sensor module represents an IoT endpoint that generates small data with a requirement for message authenticity/integrity and secure on/off operational control.

The design is hierarchical with each mbed platform and shield communicating data from the sensor node to a web server that maintains a centralized log and dispatches notifications as necessary. The simplicity of this design enables rapid integration into any star-topology IoT network to provide security with the low overhead and cost provided by the ECDSA-P256 asymmetric-key and SHA-256 symmetric-key algorithms.

More information about the MAXREFDES155# is available on the Maxim Integrated website.

Committer:
IanBenzMaxim
Date:
Thu Oct 03 11:40:13 2019 -0500
Revision:
16:a004191a79ab
Parent:
rapidjson/pointer.h@0:33d4e66780c0
Updated MaximInterface to version 2.0. Updated mbed-os to version 5.5.7. Cleaned up code styling.

Who changed what in which revision?

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