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>
118 #if RAPIDJSON_HAS_STDSTRING 178 Allocator::Free(tokens_);
187 Allocator::Free(tokens_);
189 tokenCount_ = rhs.tokenCount_;
190 parseErrorOffset_ = rhs.parseErrorOffset_;
191 parseErrorCode_ = rhs.parseErrorCode_;
196 tokens_ = rhs.tokens_;
217 Ch *p = r.CopyFromRaw(*
this, 1, token.
length + 1);
219 r.tokens_[tokenCount_].
name = p;
233 Token token = {
name, length, kPointerInvalidIndex };
243 template <
typename T>
249 #if RAPIDJSON_HAS_STDSTRING 271 buffer[length] =
'\0';
273 if (
sizeof(
Ch) == 1) {
274 Token token = {
reinterpret_cast<Ch*
>(buffer), length, index };
279 for (
size_t i = 0; i <= length; i++)
280 name[i] = static_cast<Ch>(buffer[i]);
281 Token token = {
name, length, index };
293 if (token.IsString())
309 size_t GetParseErrorOffset()
const {
return parseErrorOffset_; }
317 Allocator& GetAllocator() {
return *allocator_; }
323 const Token* GetTokens()
const {
return tokens_; }
326 size_t GetTokenCount()
const {
return tokenCount_; }
338 if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
341 for (
size_t i = 0; i < tokenCount_; i++) {
342 if (tokens_[i].index != rhs.tokens_[i].
index ||
343 tokens_[i].length != rhs.tokens_[i].
length ||
344 (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].
name,
sizeof(
Ch)* tokens_[i].length) != 0))
369 template<
typename OutputStream>
370 bool Stringify(OutputStream& os)
const {
371 return Stringify<false, OutputStream>(os);
379 template<
typename OutputStream>
380 bool StringifyUriFragment(OutputStream& os)
const {
381 return Stringify<true, OutputStream>(os);
404 ValueType& Create(ValueType& root,
typename ValueType::AllocatorType&
allocator,
bool* alreadyExist = 0)
const {
406 ValueType* v = &root;
408 for (
const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
409 if (v->IsArray() && t->name[0] ==
'-' && t->length == 1) {
410 v->PushBack(ValueType().Move(),
allocator);
411 v = &((*v)[v->Size() - 1]);
415 if (t->index == kPointerInvalidIndex) {
420 if (!v->IsArray() && !v->IsObject())
425 if (t->index >= v->Size()) {
427 while (t->index >= v->Size())
428 v->PushBack(ValueType().Move(),
allocator);
431 v = &((*v)[t->index]);
435 if (m == v->MemberEnd()) {
436 v->AddMember(ValueType(t->name, t->length,
allocator).Move(), ValueType().Move(),
allocator);
437 v = &(--v->MemberEnd())->
value;
447 *alreadyExist = exist;
458 template <
typename stackAllocator>
482 ValueType* Get(ValueType& root,
size_t* unresolvedTokenIndex = 0)
const {
484 ValueType* v = &root;
485 for (
const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
486 switch (v->GetType()) {
490 if (m == v->MemberEnd())
496 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
498 v = &((*v)[t->index]);
505 if (unresolvedTokenIndex)
506 *unresolvedTokenIndex =
static_cast<size_t>(t - tokens_);
517 const ValueType* Get(
const ValueType& root,
size_t* unresolvedTokenIndex = 0)
const {
518 return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
536 ValueType& GetWithDefault(ValueType& root,
const ValueType&
defaultValue,
typename ValueType::AllocatorType&
allocator)
const {
538 ValueType& v = Create(root,
allocator, &alreadyExist);
543 ValueType& GetWithDefault(ValueType& root,
const Ch*
defaultValue,
typename ValueType::AllocatorType&
allocator)
const {
545 ValueType& v = Create(root,
allocator, &alreadyExist);
549 #if RAPIDJSON_HAS_STDSTRING 550 ValueType& GetWithDefault(ValueType& root,
const std::basic_string<Ch>&
defaultValue,
typename ValueType::AllocatorType&
allocator)
const {
553 ValueType& v = Create(root,
allocator, &alreadyExist);
562 template <
typename T>
569 template <
typename stackAllocator>
575 template <
typename stackAllocator>
580 #if RAPIDJSON_HAS_STDSTRING 581 template <
typename stackAllocator>
592 template <
typename T,
typename stackAllocator>
613 ValueType&
Set(ValueType& root, ValueType&
value,
typename ValueType::AllocatorType&
allocator)
const {
618 ValueType&
Set(ValueType& root,
const ValueType&
value,
typename ValueType::AllocatorType&
allocator)
const {
627 #if RAPIDJSON_HAS_STDSTRING 628 ValueType&
Set(ValueType& root,
const std::basic_string<Ch>&
value,
typename ValueType::AllocatorType&
allocator)
const {
638 template <
typename T>
645 template <
typename stackAllocator>
651 template <
typename stackAllocator>
657 template <
typename stackAllocator>
662 #if RAPIDJSON_HAS_STDSTRING 663 template <
typename stackAllocator>
674 template <
typename T,
typename stackAllocator>
695 ValueType&
Swap(ValueType& root, ValueType&
value,
typename ValueType::AllocatorType&
allocator)
const {
700 template <
typename stackAllocator>
716 if (tokenCount_ == 0)
719 ValueType* v = &root;
720 const Token* last = tokens_ + (tokenCount_ - 1);
721 for (
const Token *t = tokens_; t != last; ++t) {
722 switch (v->GetType()) {
726 if (m == v->MemberEnd())
732 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
734 v = &((*v)[t->index]);
741 switch (v->GetType()) {
745 if (last->
index == kPointerInvalidIndex || last->
index >= v->Size())
747 v->Erase(v->Begin() + last->
index);
762 Ch* CopyFromRaw(
const GenericPointer& rhs,
size_t extraToken = 0,
size_t extraNameBufferSize = 0) {
766 size_t nameBufferSize = rhs.tokenCount_;
767 for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
768 nameBufferSize += t->length;
770 tokenCount_ = rhs.tokenCount_ + extraToken;
771 tokens_ =
static_cast<Token *
>(allocator_->Malloc(tokenCount_ *
sizeof(Token) + (nameBufferSize + extraNameBufferSize) *
sizeof(
Ch)));
772 nameBuffer_ =
reinterpret_cast<Ch *
>(tokens_ + tokenCount_);
773 if (rhs.tokenCount_ > 0) {
774 std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ *
sizeof(Token));
776 if (nameBufferSize > 0) {
777 std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize *
sizeof(
Ch));
781 std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
782 for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
785 return nameBuffer_ + nameBufferSize;
793 bool NeedPercentEncode(
Ch c)
const {
794 return !((c >=
'0' && c <= '9') || (c >=
'A' && c <='Z') || (c >=
'a' && c <=
'z') || c ==
'-' || c ==
'.' || c ==
'_' || c ==
'~');
798 #ifndef __clang__ // -Wdocumentation 805 void Parse(
const Ch*
source,
size_t length) {
820 Token* token = tokens_ =
static_cast<Token *
>(allocator_->Malloc(tokenCount_ *
sizeof(Token) + length *
sizeof(
Ch)));
821 Ch*
name = nameBuffer_ =
reinterpret_cast<Ch *
>(tokens_ + tokenCount_);
825 bool uriFragment =
false;
831 if (i != length &&
source[i] !=
'/') {
841 bool isNumber =
true;
843 while (i < length &&
source[i] !=
'/') {
850 Ch* begin = os.PutBegin();
855 size_t len = os.PutEnd(begin);
866 else if (NeedPercentEncode(c)) {
878 if (c ==
'0') c =
'~';
879 else if (c ==
'1') c =
'/';
893 if (c < '0' || c >
'9')
898 token->length =
static_cast<SizeType>(
name - token->name);
899 if (token->length == 0)
904 if (isNumber && token->length > 1 && token->name[0] ==
'0')
910 for (
size_t j = 0; j < token->length; j++) {
920 token->index = isNumber ? n : kPointerInvalidIndex;
929 Allocator::Free(tokens_);
933 parseErrorOffset_ = i;
943 template<
bool uriFragment,
typename OutputStream>
944 bool Stringify(OutputStream& os)
const {
950 for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
952 for (
size_t j = 0; j < t->length; j++) {
962 else if (uriFragment && NeedPercentEncode(c)) {
965 PercentEncodeStream<OutputStream> target(os);
983 class PercentDecodeStream {
995 if (*src_ !=
'%' || src_ + 3 > end_) {
1001 for (
int j = 0; j < 2; j++) {
1002 c =
static_cast<Ch>(c << 4);
1004 if (h >=
'0' && h <=
'9') c =
static_cast<Ch>(c + h -
'0');
1005 else if (h >=
'A' && h <=
'F') c =
static_cast<Ch>(c + h -
'A' + 10);
1006 else if (h >=
'a' && h <=
'f') c =
static_cast<Ch>(c + h -
'a' + 10);
1016 size_t Tell()
const {
return static_cast<size_t>(src_ - head_); }
1017 bool IsValid()
const {
return valid_; }
1027 template <
typename OutputStream>
1028 class PercentEncodeStream {
1030 PercentEncodeStream(OutputStream& os) : os_(os) {}
1032 unsigned char u =
static_cast<unsigned char>(c);
1033 static const char hexDigits[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
1035 os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
1036 os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
1042 Allocator* allocator_;
1043 Allocator* ownAllocator_;
1047 size_t parseErrorOffset_;
1059 template <
typename T>
1064 template <
typename T,
typename CharType,
size_t N>
1071 template <
typename DocumentType>
1073 return pointer.Create(document);
1076 template <
typename DocumentType,
typename CharType,
size_t N>
1083 template <
typename T>
1085 return pointer.Get(root, unresolvedTokenIndex);
1088 template <
typename T>
1090 return pointer.Get(root, unresolvedTokenIndex);
1093 template <
typename T,
typename CharType,
size_t N>
1098 template <
typename T,
typename CharType,
size_t N>
1105 template <
typename T>
1110 template <
typename T>
1115 #if RAPIDJSON_HAS_STDSTRING 1116 template <
typename T>
1122 template <
typename T,
typename T2>
1128 template <
typename T,
typename CharType,
size_t N>
1133 template <
typename T,
typename CharType,
size_t N>
1138 #if RAPIDJSON_HAS_STDSTRING 1139 template <
typename T,
typename CharType,
size_t N>
1145 template <
typename T,
typename CharType,
size_t N,
typename T2>
1153 template <
typename DocumentType>
1158 template <
typename DocumentType>
1163 #if RAPIDJSON_HAS_STDSTRING 1164 template <
typename DocumentType>
1170 template <
typename DocumentType,
typename T2>
1176 template <
typename DocumentType,
typename CharType,
size_t N>
1181 template <
typename DocumentType,
typename CharType,
size_t N>
1186 #if RAPIDJSON_HAS_STDSTRING 1187 template <
typename DocumentType,
typename CharType,
size_t N>
1193 template <
typename DocumentType,
typename CharType,
size_t N,
typename T2>
1201 template <
typename T>
1206 template <
typename T>
1211 template <
typename T>
1216 #if RAPIDJSON_HAS_STDSTRING 1217 template <
typename T>
1223 template <
typename T,
typename T2>
1229 template <
typename T,
typename CharType,
size_t N>
1234 template <
typename T,
typename CharType,
size_t N>
1239 template <
typename T,
typename CharType,
size_t N>
1244 #if RAPIDJSON_HAS_STDSTRING 1245 template <
typename T,
typename CharType,
size_t N>
1246 typename T::ValueType&
SetValueByPointer(
T& root,
const CharType(&
source)[N],
const std::basic_string<typename T::Ch>&
value,
typename T::AllocatorType&
a) {
1251 template <
typename T,
typename CharType,
size_t N,
typename T2>
1259 template <
typename DocumentType>
1264 template <
typename DocumentType>
1269 template <
typename DocumentType>
1274 #if RAPIDJSON_HAS_STDSTRING 1275 template <
typename DocumentType>
1281 template <
typename DocumentType,
typename T2>
1287 template <
typename DocumentType,
typename CharType,
size_t N>
1292 template <
typename DocumentType,
typename CharType,
size_t N>
1297 template <
typename DocumentType,
typename CharType,
size_t N>
1302 #if RAPIDJSON_HAS_STDSTRING 1303 template <
typename DocumentType,
typename CharType,
size_t N>
1304 typename DocumentType::ValueType&
SetValueByPointer(DocumentType& document,
const CharType(&
source)[N],
const std::basic_string<typename DocumentType::Ch>&
value) {
1309 template <
typename DocumentType,
typename CharType,
size_t N,
typename T2>
1317 template <
typename T>
1322 template <
typename T,
typename CharType,
size_t N>
1327 template <
typename DocumentType>
1332 template <
typename DocumentType,
typename CharType,
size_t N>
1339 template <
typename T>
1344 template <
typename T,
typename CharType,
size_t N>
1353 #if defined(__clang__) || defined(_MSC_VER) 1357 #endif // RAPIDJSON_POINTER_H_ T::ValueType & GetValueByPointerWithDefault(T &root, const GenericPointer< typename T::ValueType > &pointer, const typename T::ValueType &defaultValue, typename T::AllocatorType &a)
ValueType & Set(ValueType &root, ValueType &value, typename ValueType::AllocatorType &allocator) const
Set a value in a subtree, with move semantics.
char * u64toa(uint64_t value, char *buffer)
PointerParseErrorCode
Error code of parsing.
const CharType(& source)[N]
GenericPointer(const Ch *source, Allocator *allocator=0)
Constructor that parses a string or URI fragment representation.
SizeType length
Length of the name.
A token is the basic units of internal representation.
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...
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Invalid percent encoding in URI fragment.
~GenericPointer()
Destructor.
GenericPointer(const GenericPointer &rhs, Allocator *allocator)
Copy constructor.
GenericPointer(const Token *tokens, size_t tokenCount)
Constructor with user-supplied tokens.
bool operator==(const some_test_data &a, const some_test_data &b)
ValueType & Set(ValueType &root, const Ch *value, typename ValueType::AllocatorType &allocator) const
Set a null-terminated string in a subtree.
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
bool operator!=(const some_test_subdata &a, const some_test_subdata &b)
ValueType::EncodingType EncodingType
Encoding type from Value.
bool Erase(ValueType &root) const
Erase a value in a subtree.
T::ValueType & SwapValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, typename T::ValueType &value, typename T::AllocatorType &a)
ValueType::Ch Ch
Character type from Value.
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Reference to a constant string (not taking a copy)
SizeType index
A valid array index, if it is not equal to kPointerInvalidIndex.
GenericPointer< Value > Pointer
GenericPointer for Value (UTF-8, default allocator).
Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
ValueType & Set(GenericDocument< EncodingType, typename ValueType::AllocatorType, stackAllocator > &document, const Ch *value) const
Set a null-terminated string in a document.
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
void Swap(T &a, T &b) RAPIDJSON_NOEXCEPT
Custom swap() to avoid dependency on C++ <algorithm> header.
#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)
GenericPointer Append(const Ch *name, SizeType length, Allocator *allocator=0) const
Append a name token with length, and return a new Pointer.
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
ValueType & Swap(ValueType &root, ValueType &value, typename ValueType::AllocatorType &allocator) const
Swap a value with a value in a subtree.
A character must percent encoded in URI fragment.
ValueType & Set(ValueType &root, const ValueType &value, typename ValueType::AllocatorType &allocator) const
Set a value in a subtree, with copy semantics.
GenericPointer(const GenericPointer &rhs)
Copy constructor.
const GenericPointer< typename T::ValueType > T2 value
void * memcpy(void *a, const void *b, size_t c)
GenericPointer Append(const Token &token, Allocator *allocator=0) const
Append a token and return a new Pointer.
A token must begin with a '/'.
ValueType & Swap(GenericDocument< EncodingType, typename ValueType::AllocatorType, stackAllocator > &document, ValueType &value) const
Swap a value with a value in a document.
bool EraseValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer)
GenericPointer(Allocator *allocator=0)
Default constructor.
const GenericPointer< typename T::ValueType > T2 defaultValue
SizeType StrLen(const Ch *s)
Custom strlen() which works on different character types.
ValueType & Set(GenericDocument< EncodingType, typename ValueType::AllocatorType, stackAllocator > &document, ValueType &value) const
Set a value in a document, with move semantics.
const GenericPointer< typename T::ValueType > & pointer
A read-write string stream.
Allocator stackAllocator stackAllocator & document
error
Tracks LMDB error codes.
T::ValueType & SetValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, typename T::ValueType &value, typename T::AllocatorType &a)
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr< internal::IsPointer< T2 >, internal::IsGenericValue< T2 > >),(typename T::ValueType &)) GetValueByPointerWithDefault(T &root
#define RAPIDJSON_ASSERT(x)
Assertion.
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.
const Ch * name
Name of the token. It has null character at the end but it can contain null character.
A document for parsing JSON text as DOM.
GenericPointer & operator=(const GenericPointer &rhs)
Assignment operator.
T::ValueType * GetValueByPointer(T &root, const GenericPointer< typename T::ValueType > &pointer, size_t *unresolvedTokenIndex=0)
ValueType & Set(GenericDocument< EncodingType, typename ValueType::AllocatorType, stackAllocator > &document, const ValueType &value) const
Set a value in a document, with copy semantics.