15 #ifndef RAPIDJSON_POINTER_H_ 16 #define RAPIDJSON_POINTER_H_ 23 RAPIDJSON_DIAG_OFF(
switch-
enum)
24 #elif defined(_MSC_VER) 26 RAPIDJSON_DIAG_OFF(4512)
78 template <
typename ValueType,
typename Allocator = CrtAllocator>
82 typedef typename ValueType::Ch
Ch;
118 #if RAPIDJSON_HAS_STDSTRING 126 Parse(source.c_str(), source.size());
138 Parse(source, length);
247 Ch *p = r.CopyFromRaw(*
this, 1, token.
length + 1);
248 std::memcpy(p, token.
name, (token.
length + 1) *
sizeof(Ch));
273 template <
typename T>
279 #if RAPIDJSON_HAS_STDSTRING 303 if (
sizeof(
Ch) == 1) {
304 Token token = {
reinterpret_cast<Ch*
>(buffer), length, index };
309 for (
size_t i = 0; i <=
length; i++)
310 name[i] = static_cast<Ch>(buffer[i]);
323 if (token.IsString())
347 Allocator& GetAllocator() {
return *
allocator_; }
356 size_t GetTokenCount()
const {
return tokenCount_; }
387 bool operator!=(
const GenericPointer& rhs)
const {
return !(*
this == rhs); }
426 template<
typename OutputStream>
427 bool Stringify(OutputStream& os)
const {
428 return Stringify<false, OutputStream>(os);
436 template<
typename OutputStream>
437 bool StringifyUriFragment(OutputStream& os)
const {
438 return Stringify<true, OutputStream>(os);
461 ValueType& Create(ValueType& root,
typename ValueType::AllocatorType&
allocator,
bool* alreadyExist = 0)
const {
463 ValueType* v = &root;
466 if (v->IsArray() && t->name[0] ==
'-' && t->length == 1) {
467 v->PushBack(ValueType().Move(), allocator);
468 v = &((*v)[v->Size() - 1]);
472 if (t->index == kPointerInvalidIndex) {
477 if (!v->IsArray() && !v->IsObject())
482 if (t->index >= v->Size()) {
483 v->Reserve(t->index + 1, allocator);
484 while (t->index >= v->Size())
485 v->PushBack(ValueType().Move(), allocator);
488 v = &((*v)[t->index]);
492 if (m == v->MemberEnd()) {
493 v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(),
allocator);
494 v = &(--v->MemberEnd())->
value;
504 *alreadyExist = exist;
515 template <
typename stackAllocator>
517 return Create(document, document.
GetAllocator(), alreadyExist);
539 ValueType* Get(ValueType& root,
size_t* unresolvedTokenIndex = 0)
const {
541 ValueType* v = &root;
543 switch (v->GetType()) {
547 if (m == v->MemberEnd())
553 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
555 v = &((*v)[t->index]);
562 if (unresolvedTokenIndex)
563 *unresolvedTokenIndex =
static_cast<size_t>(t -
tokens_);
574 const ValueType* Get(
const ValueType& root,
size_t* unresolvedTokenIndex = 0)
const {
575 return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
593 ValueType& GetWithDefault(ValueType& root,
const ValueType&
defaultValue,
typename ValueType::AllocatorType& allocator)
const {
595 ValueType& v = Create(root, allocator, &alreadyExist);
596 return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
600 ValueType& GetWithDefault(ValueType& root,
const Ch* defaultValue,
typename ValueType::AllocatorType& allocator)
const {
602 ValueType& v = Create(root, allocator, &alreadyExist);
603 return alreadyExist ? v : v.SetString(defaultValue, allocator);
606 #if RAPIDJSON_HAS_STDSTRING 607 ValueType& GetWithDefault(ValueType& root,
const std::basic_string<Ch>& defaultValue,
typename ValueType::AllocatorType& allocator)
const {
610 ValueType& v = Create(root, allocator, &alreadyExist);
611 return alreadyExist ? v : v.SetString(defaultValue, allocator);
619 template <
typename T>
621 GetWithDefault(ValueType& root, T defaultValue,
typename ValueType::AllocatorType& allocator)
const {
622 return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
626 template <
typename stackAllocator>
628 return GetWithDefault(document, defaultValue, document.
GetAllocator());
632 template <
typename stackAllocator>
634 return GetWithDefault(document, defaultValue, document.
GetAllocator());
637 #if RAPIDJSON_HAS_STDSTRING 638 template <
typename stackAllocator>
641 return GetWithDefault(document, defaultValue, document.
GetAllocator());
649 template <
typename T,
typename stackAllocator>
652 return GetWithDefault(document, defaultValue, document.
GetAllocator());
670 ValueType& Set(ValueType& root, ValueType&
value,
typename ValueType::AllocatorType& allocator)
const {
671 return Create(root, allocator) =
value;
675 ValueType& Set(ValueType& root,
const ValueType& value,
typename ValueType::AllocatorType& allocator)
const {
676 return Create(root, allocator).CopyFrom(value, allocator);
680 ValueType& Set(ValueType& root,
const Ch* value,
typename ValueType::AllocatorType& allocator)
const {
681 return Create(root, allocator) = ValueType(value, allocator).Move();
684 #if RAPIDJSON_HAS_STDSTRING 685 ValueType& Set(ValueType& root,
const std::basic_string<Ch>& value,
typename ValueType::AllocatorType& allocator)
const {
687 return Create(root, allocator) = ValueType(value, allocator).Move();
695 template <
typename T>
697 Set(ValueType& root, T value,
typename ValueType::AllocatorType& allocator)
const {
698 return Create(root, allocator) = ValueType(value).Move();
702 template <
typename stackAllocator>
704 return Create(document) =
value;
708 template <
typename stackAllocator>
710 return Create(document).CopyFrom(value, document.
GetAllocator());
714 template <
typename stackAllocator>
716 return Create(document) = ValueType(value, document.
GetAllocator()).Move();
719 #if RAPIDJSON_HAS_STDSTRING 720 template <
typename stackAllocator>
723 return Create(document) = ValueType(value, document.
GetAllocator()).Move();
731 template <
typename T,
typename stackAllocator>
734 return Create(document) =
value;
752 ValueType&
Swap(ValueType& root, ValueType& value,
typename ValueType::AllocatorType& allocator)
const {
753 return Create(root, allocator).
Swap(value);
757 template <
typename stackAllocator>
759 return Create(document).
Swap(value);
771 bool Erase(ValueType& root)
const {
776 ValueType* v = &root;
779 switch (v->GetType()) {
783 if (m == v->MemberEnd())
789 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
791 v = &((*v)[t->index]);
798 switch (v->GetType()) {
802 if (last->
index == kPointerInvalidIndex || last->
index >= v->Size())
804 v->Erase(v->Begin() + last->
index);
819 Ch* CopyFromRaw(
const GenericPointer& rhs,
size_t extraToken = 0,
size_t extraNameBufferSize = 0) {
825 nameBufferSize += t->length;
833 if (nameBufferSize > 0) {
850 bool NeedPercentEncode(
Ch c)
const {
851 return !((c >=
'0' && c <= '9') || (c >=
'A' && c <='Z') || (c >=
'a' && c <=
'z') || c ==
'-' || c ==
'.' || c ==
'_' || c ==
'~');
855 #ifndef __clang__ // -Wdocumentation 873 for (
const Ch* s = source; s != source +
length; s++)
882 bool uriFragment =
false;
883 if (source[i] ==
'#') {
888 if (i != length && source[i] !=
'/') {
898 bool isNumber =
true;
900 while (i < length && source[i] !=
'/') {
905 PercentDecodeStream is(&source[i], source + length);
912 size_t len = os.
PutEnd(begin);
923 else if (NeedPercentEncode(c)) {
935 if (c ==
'0') c =
'~';
936 else if (c ==
'1') c =
'/';
950 if (c < '0' || c >
'9')
961 if (isNumber && token->
length > 1 && token->
name[0] ==
'0')
967 for (
size_t j = 0; j < token->
length; j++) {
1000 template<
bool uriFragment,
typename OutputStream>
1001 bool Stringify(OutputStream& os)
const {
1009 for (
size_t j = 0; j < t->length; j++) {
1015 else if (c ==
'/') {
1019 else if (uriFragment && NeedPercentEncode(c)) {
1025 j += source.
Tell() - 1;
1040 class PercentDecodeStream {
1042 typedef typename ValueType::Ch
Ch;
1049 PercentDecodeStream(
const Ch* source,
const Ch* end) : src_(source), head_(source), end_(end), valid_(
true) {}
1052 if (*src_ !=
'%' || src_ + 3 > end_) {
1058 for (
int j = 0; j < 2; j++) {
1059 c =
static_cast<Ch
>(c << 4);
1061 if (h >=
'0' && h <=
'9') c =
static_cast<Ch
>(c + h -
'0');
1062 else if (h >=
'A' && h <=
'F') c =
static_cast<Ch
>(c + h -
'A' + 10);
1063 else if (h >=
'a' && h <=
'f') c =
static_cast<Ch
>(c + h -
'a' + 10);
1073 size_t Tell()
const {
return static_cast<size_t>(src_ - head_); }
1074 bool IsValid()
const {
return valid_; }
1084 template <
typename OutputStream>
1089 unsigned char u =
static_cast<unsigned char>(c);
1090 static const char hexDigits[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
1092 os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
1093 os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
1116 template <
typename T>
1118 return pointer.Create(root, a);
1121 template <
typename T,
typename CharType,
size_t N>
1128 template <
typename DocumentType>
1130 return pointer.Create(document);
1133 template <
typename DocumentType,
typename CharType,
size_t N>
1140 template <
typename T>
1142 return pointer.Get(root, unresolvedTokenIndex);
1145 template <
typename T>
1147 return pointer.Get(root, unresolvedTokenIndex);
1150 template <
typename T,
typename CharType,
size_t N>
1155 template <
typename T,
typename CharType,
size_t N>
1162 template <
typename T>
1164 return pointer.GetWithDefault(root, defaultValue, a);
1167 template <
typename T>
1169 return pointer.GetWithDefault(root, defaultValue, a);
1172 #if RAPIDJSON_HAS_STDSTRING 1173 template <
typename T>
1175 return pointer.GetWithDefault(root, defaultValue, a);
1179 template <
typename T,
typename T2>
1182 return pointer.GetWithDefault(root, defaultValue, a);
1185 template <
typename T,
typename CharType,
size_t N>
1190 template <
typename T,
typename CharType,
size_t N>
1195 #if RAPIDJSON_HAS_STDSTRING 1196 template <
typename T,
typename CharType,
size_t N>
1202 template <
typename T,
typename CharType,
size_t N,
typename T2>
1210 template <
typename DocumentType>
1212 return pointer.GetWithDefault(document, defaultValue);
1215 template <
typename DocumentType>
1217 return pointer.GetWithDefault(document, defaultValue);
1220 #if RAPIDJSON_HAS_STDSTRING 1221 template <
typename DocumentType>
1223 return pointer.GetWithDefault(document, defaultValue);
1227 template <
typename DocumentType,
typename T2>
1230 return pointer.GetWithDefault(document, defaultValue);
1233 template <
typename DocumentType,
typename CharType,
size_t N>
1238 template <
typename DocumentType,
typename CharType,
size_t N>
1243 #if RAPIDJSON_HAS_STDSTRING 1244 template <
typename DocumentType,
typename CharType,
size_t N>
1245 typename DocumentType::ValueType&
GetValueByPointerWithDefault(DocumentType& document,
const CharType(&
source)[N],
const std::basic_string<typename DocumentType::Ch>& defaultValue) {
1250 template <
typename DocumentType,
typename CharType,
size_t N,
typename T2>
1258 template <
typename T>
1260 return pointer.Set(root, value, a);
1263 template <
typename T>
1265 return pointer.Set(root, value, a);
1268 template <
typename T>
1270 return pointer.Set(root, value, a);
1273 #if RAPIDJSON_HAS_STDSTRING 1274 template <
typename T>
1276 return pointer.Set(root, value, a);
1280 template <
typename T,
typename T2>
1283 return pointer.Set(root, value, a);
1286 template <
typename T,
typename CharType,
size_t N>
1291 template <
typename T,
typename CharType,
size_t N>
1296 template <
typename T,
typename CharType,
size_t N>
1301 #if RAPIDJSON_HAS_STDSTRING 1302 template <
typename T,
typename CharType,
size_t N>
1303 typename T::ValueType&
SetValueByPointer(T& root,
const CharType(&
source)[N],
const std::basic_string<typename T::Ch>&
value,
typename T::AllocatorType&
a) {
1308 template <
typename T,
typename CharType,
size_t N,
typename T2>
1316 template <
typename DocumentType>
1318 return pointer.Set(document, value);
1321 template <
typename DocumentType>
1323 return pointer.Set(document, value);
1326 template <
typename DocumentType>
1328 return pointer.Set(document, value);
1331 #if RAPIDJSON_HAS_STDSTRING 1332 template <
typename DocumentType>
1334 return pointer.Set(document, value);
1338 template <
typename DocumentType,
typename T2>
1341 return pointer.Set(document, value);
1344 template <
typename DocumentType,
typename CharType,
size_t N>
1345 typename DocumentType::ValueType&
SetValueByPointer(DocumentType& document,
const CharType(&
source)[N],
typename DocumentType::ValueType& value) {
1349 template <
typename DocumentType,
typename CharType,
size_t N>
1350 typename DocumentType::ValueType&
SetValueByPointer(DocumentType& document,
const CharType(&
source)[N],
const typename DocumentType::ValueType& value) {
1354 template <
typename DocumentType,
typename CharType,
size_t N>
1355 typename DocumentType::ValueType&
SetValueByPointer(DocumentType& document,
const CharType(&
source)[N],
const typename DocumentType::Ch* value) {
1359 #if RAPIDJSON_HAS_STDSTRING 1360 template <
typename DocumentType,
typename CharType,
size_t N>
1361 typename DocumentType::ValueType&
SetValueByPointer(DocumentType& document,
const CharType(&
source)[N],
const std::basic_string<typename DocumentType::Ch>& value) {
1366 template <
typename DocumentType,
typename CharType,
size_t N,
typename T2>
1374 template <
typename T>
1376 return pointer.
Swap(root, value, a);
1379 template <
typename T,
typename CharType,
size_t N>
1380 typename T::ValueType&
SwapValueByPointer(T& root,
const CharType(&
source)[N],
typename T::ValueType& value,
typename T::AllocatorType& a) {
1384 template <
typename DocumentType>
1386 return pointer.
Swap(document, value);
1389 template <
typename DocumentType,
typename CharType,
size_t N>
1390 typename DocumentType::ValueType&
SwapValueByPointer(DocumentType& document,
const CharType(&
source)[N],
typename DocumentType::ValueType& value) {
1396 template <
typename T>
1398 return pointer.Erase(root);
1401 template <
typename T,
typename CharType,
size_t N>
1410 #if defined(__clang__) || defined(_MSC_VER) 1414 #endif // RAPIDJSON_POINTER_H_ SizeType length
Length of the name.
T::ValueType & GetValueByPointerWithDefault(T &root, const GenericPointer< typename T::ValueType > &pointer, const typename T::ValueType &defaultValue, typename T::AllocatorType &a)
char * u64toa(uint64_t value, char *buffer)
PointerParseErrorCode
Error code of parsing.
const CharType(& source)[N]
GenericPointer(const Token *tokens, size_t tokenCount)
Constructor with user-supplied tokens.
A token is the basic units of internal representation.
GenericPointer Append(const Token &token, Allocator *allocator=0) const
Append a token and return a new Pointer.
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
GenericPointer & Swap(GenericPointer &other) RAPIDJSON_NOEXCEPT
Swap the content of this pointer with an other.
Allocator * ownAllocator_
Allocator owned by this Pointer.
Invalid percent encoding in URI fragment.
GenericPointer(const Ch *source, Allocator *allocator=0)
Constructor that parses a string or URI fragment representation.
PercentEncodeStream(OutputStream &os)
ValueType::EncodingType EncodingType
Encoding type from Value.
const Ch * name
Name of the token. It has null character at the end but it can contain null character.
Allocator * allocator_
The current allocator. It is either user-supplied or equal to ownAllocator_.
GenericPointer(const GenericPointer &rhs)
Copy constructor.
GenericPointer(Allocator *allocator=0)
Default constructor.
static RAPIDJSON_NAMESPACE_BEGIN const SizeType kPointerInvalidIndex
Represents an invalid index in GenericPointer::Token.
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Allocator & GetAllocator()
Get the allocator of this document.
T::ValueType & SwapValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, typename T::ValueType &value, typename T::AllocatorType &a)
GenericPointer(const Ch *source, size_t length, Allocator *allocator=0)
Constructor that parses a string or URI fragment representation, with length of the source string...
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Reference to a constant string (not taking a copy)
GenericPointer< Value > Pointer
GenericPointer for Value (UTF-8, default allocator).
A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.
size_t parseErrorOffset_
Offset in code unit when parsing fail.
RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr< internal::IsSame< typename internal::RemoveConst< T >::Type, Ch > >),(GenericPointer)) Append(T *name
Append a name token without length, and return a new Pointer.
Ch * nameBuffer_
A buffer containing all names in tokens.
Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
~GenericPointer()
Destructor.
void Swap(T &a, T &b) RAPIDJSON_NOEXCEPT
Custom swap() to avoid dependency on C++ <algorithm> header.
GenericPointer(const GenericPointer &rhs, Allocator *allocator)
Copy constructor.
#define RAPIDJSON_DELETE(x)
! customization point for global delete
char * u32toa(uint32_t value, char *buffer)
T::ValueType & CreateValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, typename T::AllocatorType &a)
PointerParseErrorCode parseErrorCode_
Parsing error code.
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Token * tokens_
A list of tokens.
SizeType index
A valid array index, if it is not equal to kPointerInvalidIndex.
A character must percent encoded in URI fragment.
size_t tokenCount_
Number of tokens in tokens_.
const GenericPointer< typename T::ValueType > T2 value
ValueType::Ch Ch
Character type from Value.
A token must begin with a '/'.
friend void swap(GenericPointer &a, GenericPointer &b) RAPIDJSON_NOEXCEPT
free-standing swap function helper
bool EraseValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer)
const GenericPointer< typename T::ValueType > T2 defaultValue
SizeType StrLen(const Ch *s)
Custom strlen() which works on different character types.
const GenericPointer< typename T::ValueType > & pointer
A read-write string stream.
T::ValueType & SetValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, typename T::ValueType &value, typename T::AllocatorType &a)
#define RAPIDJSON_ASSERT(x)
Assertion.
GenericPointer & operator=(const GenericPointer &rhs)
Assignment operator.
A document for parsing JSON text as DOM.
T::ValueType * GetValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, size_t *unresolvedTokenIndex=0)
GenericPointer Append(const Ch *name, SizeType length, Allocator *allocator=0) const
Append a name token with length, and return a new Pointer.