15 #ifndef RAPIDJSON_POINTER_H_
16 #define RAPIDJSON_POINTER_H_
24 RAPIDJSON_DIAG_OFF(
switch-
enum)
25 #elif defined(_MSC_VER)
27 RAPIDJSON_DIAG_OFF(4512)
79 template <
typename ValueType,
typename Allocator = CrtAllocator>
83 typedef typename ValueType::Ch
Ch;
121 #if RAPIDJSON_HAS_STDSTRING
250 Ch *p = r.CopyFromRaw(*
this, 1, token.
length + 1);
251 std::memcpy(p, token.
name, (token.
length + 1) *
sizeof(
Ch));
266 Token token = { name, length, kPointerInvalidIndex };
276 template <
typename T>
282 #if RAPIDJSON_HAS_STDSTRING
304 buffer[length] =
'\0';
306 if (
sizeof(
Ch) == 1) {
307 Token token = {
reinterpret_cast<Ch*
>(buffer), length, index };
312 for (
size_t i = 0; i <= length; i++)
313 name[i] =
static_cast<Ch>(buffer[i]);
314 Token token = { name, length, index };
326 if (token.IsString())
356 const Token* GetTokens()
const {
return tokens_; }
359 size_t GetTokenCount()
const {
return tokenCount_; }
390 bool operator!=(
const GenericPointer& rhs)
const {
return !(*
this == rhs); }
429 template<
typename OutputStream>
430 bool Stringify(OutputStream& os)
const {
431 return Stringify<false, OutputStream>(os);
439 template<
typename OutputStream>
440 bool StringifyUriFragment(OutputStream& os)
const {
441 return Stringify<true, OutputStream>(os);
464 ValueType& Create(ValueType& root,
typename ValueType::AllocatorType&
allocator,
bool* alreadyExist = 0)
const {
466 ValueType* v = &root;
469 if (v->IsArray() && t->name[0] ==
'-' && t->length == 1) {
470 v->PushBack(ValueType().Move(),
allocator);
471 v = &((*v)[v->Size() - 1]);
475 if (t->index == kPointerInvalidIndex) {
480 if (!v->IsArray() && !v->IsObject())
485 if (t->index >= v->Size()) {
487 while (t->index >= v->Size())
488 v->PushBack(ValueType().Move(),
allocator);
491 v = &((*v)[t->index]);
495 if (m == v->MemberEnd()) {
496 v->AddMember(ValueType(t->name, t->length,
allocator).Move(), ValueType().Move(),
allocator);
508 *alreadyExist = exist;
519 template <
typename stackAllocator>
521 return Create(document, document.
GetAllocator(), alreadyExist);
547 static const Ch kIdString[] = {
'i',
'd',
'\0' };
548 static const ValueType kIdValue(kIdString, 2);
551 ValueType* v = &root;
553 switch (v->GetType()) {
557 typename ValueType::MemberIterator m = v->FindMember(kIdValue);
558 if (m != v->MemberEnd() && (m->value).IsString()) {
563 if (m == v->MemberEnd())
569 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
571 v = &((*v)[t->index]);
578 if (unresolvedTokenIndex)
579 *unresolvedTokenIndex =
static_cast<size_t>(t -
tokens_);
586 return GetUri(
const_cast<ValueType&
>(root), rootUri, unresolvedTokenIndex,
allocator);
607 ValueType* Get(ValueType& root,
size_t* unresolvedTokenIndex = 0)
const {
609 ValueType* v = &root;
611 switch (v->GetType()) {
615 if (m == v->MemberEnd())
621 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
623 v = &((*v)[t->index]);
630 if (unresolvedTokenIndex)
631 *unresolvedTokenIndex =
static_cast<size_t>(t -
tokens_);
642 const ValueType* Get(
const ValueType& root,
size_t* unresolvedTokenIndex = 0)
const {
643 return Get(
const_cast<ValueType&
>(root), unresolvedTokenIndex);
661 ValueType& GetWithDefault(ValueType& root,
const ValueType&
defaultValue,
typename ValueType::AllocatorType&
allocator)
const {
663 ValueType& v = Create(root,
allocator, &alreadyExist);
668 ValueType& GetWithDefault(ValueType& root,
const Ch*
defaultValue,
typename ValueType::AllocatorType&
allocator)
const {
670 ValueType& v = Create(root,
allocator, &alreadyExist);
674 #if RAPIDJSON_HAS_STDSTRING
675 ValueType& GetWithDefault(ValueType& root,
const std::basic_string<Ch>&
defaultValue,
typename ValueType::AllocatorType&
allocator)
const {
678 ValueType& v = Create(root,
allocator, &alreadyExist);
687 template <
typename T>
689 GetWithDefault(ValueType& root, T
defaultValue,
typename ValueType::AllocatorType&
allocator)
const {
694 template <
typename stackAllocator>
700 template <
typename stackAllocator>
705 #if RAPIDJSON_HAS_STDSTRING
706 template <
typename stackAllocator>
717 template <
typename T,
typename stackAllocator>
738 ValueType& Set(ValueType& root, ValueType&
value,
typename ValueType::AllocatorType&
allocator)
const {
743 ValueType& Set(ValueType& root,
const ValueType&
value,
typename ValueType::AllocatorType&
allocator)
const {
748 ValueType& Set(ValueType& root,
const Ch*
value,
typename ValueType::AllocatorType&
allocator)
const {
752 #if RAPIDJSON_HAS_STDSTRING
753 ValueType& Set(ValueType& root,
const std::basic_string<Ch>&
value,
typename ValueType::AllocatorType&
allocator)
const {
763 template <
typename T>
765 Set(ValueType& root, T
value,
typename ValueType::AllocatorType&
allocator)
const {
770 template <
typename stackAllocator>
772 return Create(document) =
value;
776 template <
typename stackAllocator>
782 template <
typename stackAllocator>
787 #if RAPIDJSON_HAS_STDSTRING
788 template <
typename stackAllocator>
799 template <
typename T,
typename stackAllocator>
802 return Create(document) =
value;
820 ValueType&
Swap(ValueType& root, ValueType&
value,
typename ValueType::AllocatorType&
allocator)
const {
825 template <
typename stackAllocator>
839 bool Erase(ValueType& root)
const {
844 ValueType* v = &root;
846 for (
const Token *t =
tokens_; t != last; ++t) {
847 switch (v->GetType()) {
851 if (m == v->MemberEnd())
857 if (t->index == kPointerInvalidIndex || t->index >= v->Size())
859 v = &((*v)[t->index]);
866 switch (v->GetType()) {
870 if (last->index == kPointerInvalidIndex || last->index >= v->Size())
872 v->Erase(v->Begin() + last->index);
887 Ch* CopyFromRaw(
const GenericPointer& rhs,
size_t extraToken = 0,
size_t extraNameBufferSize = 0) {
893 nameBufferSize += t->length;
901 if (nameBufferSize > 0) {
918 bool NeedPercentEncode(
Ch c)
const {
919 return !((c >=
'0' && c <=
'9') || (c >=
'A' && c <=
'Z') || (c >=
'a' && c <=
'z') || c ==
'-' || c ==
'.' || c ==
'_' || c ==
'~');
923 #ifndef __clang__ // -Wdocumentation
930 void Parse(
const Ch*
source,
size_t length) {
950 bool uriFragment =
false;
956 if (i != length &&
source[i] !=
'/') {
966 bool isNumber =
true;
968 while (i < length &&
source[i] !=
'/') {
975 Ch* begin = os.PutBegin();
980 size_t len = os.PutEnd(begin);
991 else if (NeedPercentEncode(c)) {
1003 if (c ==
'0') c =
'~';
1004 else if (c ==
'1') c =
'/';
1018 if (c < '0' || c >
'9')
1023 token->length =
static_cast<SizeType>(name - token->name);
1024 if (token->length == 0)
1029 if (isNumber && token->length > 1 && token->name[0] ==
'0')
1035 for (
size_t j = 0; j < token->length; j++) {
1045 token->index = isNumber ? n : kPointerInvalidIndex;
1068 template<
bool uriFragment,
typename OutputStream>
1069 bool Stringify(OutputStream& os)
const {
1077 for (
size_t j = 0; j < t->length; j++) {
1083 else if (c ==
'/') {
1087 else if (uriFragment && NeedPercentEncode(c)) {
1090 PercentEncodeStream<OutputStream> target(os);
1108 class PercentDecodeStream {
1110 typedef typename ValueType::Ch
Ch;
1117 PercentDecodeStream(
const Ch*
source,
const Ch* end) : src_(
source), head_(
source), end_(end), valid_(true) {}
1120 if (*src_ !=
'%' || src_ + 3 > end_) {
1126 for (
int j = 0; j < 2; j++) {
1127 c =
static_cast<Ch>(c << 4);
1129 if (h >=
'0' && h <=
'9') c =
static_cast<Ch>(c + h -
'0');
1130 else if (h >=
'A' && h <=
'F') c =
static_cast<Ch>(c + h -
'A' + 10);
1131 else if (h >=
'a' && h <=
'f') c =
static_cast<Ch>(c + h -
'a' + 10);
1141 size_t Tell()
const {
return static_cast<size_t>(src_ - head_); }
1142 bool IsValid()
const {
return valid_; }
1152 template <
typename OutputStream>
1157 unsigned char u =
static_cast<unsigned char>(c);
1158 static const char hexDigits[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
1160 os_.Put(
static_cast<typename OutputStream::Ch
>(hexDigits[u >> 4]));
1161 os_.Put(
static_cast<typename OutputStream::Ch
>(hexDigits[u & 15]));
1184 template <
typename T>
1189 template <
typename T,
typename CharType,
size_t N>
1196 template <
typename DocumentType>
1198 return pointer.Create(document);
1201 template <
typename DocumentType,
typename CharType,
size_t N>
1208 template <
typename T>
1210 return pointer.Get(root, unresolvedTokenIndex);
1213 template <
typename T>
1215 return pointer.Get(root, unresolvedTokenIndex);
1218 template <
typename T,
typename CharType,
size_t N>
1223 template <
typename T,
typename CharType,
size_t N>
1230 template <
typename T>
1235 template <
typename T>
1240 #if RAPIDJSON_HAS_STDSTRING
1241 template <
typename T>
1247 template <
typename T,
typename T2>
1253 template <
typename T,
typename CharType,
size_t N>
1258 template <
typename T,
typename CharType,
size_t N>
1263 #if RAPIDJSON_HAS_STDSTRING
1264 template <
typename T,
typename CharType,
size_t N>
1270 template <
typename T,
typename CharType,
size_t N,
typename T2>
1278 template <
typename DocumentType>
1283 template <
typename DocumentType>
1288 #if RAPIDJSON_HAS_STDSTRING
1289 template <
typename DocumentType>
1295 template <
typename DocumentType,
typename T2>
1301 template <
typename DocumentType,
typename CharType,
size_t N>
1306 template <
typename DocumentType,
typename CharType,
size_t N>
1311 #if RAPIDJSON_HAS_STDSTRING
1312 template <
typename DocumentType,
typename CharType,
size_t N>
1318 template <
typename DocumentType,
typename CharType,
size_t N,
typename T2>
1326 template <
typename T>
1331 template <
typename T>
1336 template <
typename T>
1341 #if RAPIDJSON_HAS_STDSTRING
1342 template <
typename T>
1348 template <
typename T,
typename T2>
1354 template <
typename T,
typename CharType,
size_t N>
1359 template <
typename T,
typename CharType,
size_t N>
1364 template <
typename T,
typename CharType,
size_t N>
1369 #if RAPIDJSON_HAS_STDSTRING
1370 template <
typename T,
typename CharType,
size_t N>
1371 typename T::ValueType&
SetValueByPointer(T& root,
const CharType(&
source)[N],
const std::basic_string<typename T::Ch>&
value,
typename T::AllocatorType&
a) {
1376 template <
typename T,
typename CharType,
size_t N,
typename T2>
1384 template <
typename DocumentType>
1389 template <
typename DocumentType>
1394 template <
typename DocumentType>
1399 #if RAPIDJSON_HAS_STDSTRING
1400 template <
typename DocumentType>
1406 template <
typename DocumentType,
typename T2>
1412 template <
typename DocumentType,
typename CharType,
size_t N>
1417 template <
typename DocumentType,
typename CharType,
size_t N>
1422 template <
typename DocumentType,
typename CharType,
size_t N>
1427 #if RAPIDJSON_HAS_STDSTRING
1428 template <
typename DocumentType,
typename CharType,
size_t N>
1429 typename DocumentType::ValueType&
SetValueByPointer(DocumentType& document,
const CharType(&
source)[N],
const std::basic_string<typename DocumentType::Ch>&
value) {
1434 template <
typename DocumentType,
typename CharType,
size_t N,
typename T2>
1442 template <
typename T>
1447 template <
typename T,
typename CharType,
size_t N>
1452 template <
typename DocumentType>
1457 template <
typename DocumentType,
typename CharType,
size_t N>
1464 template <
typename T>
1469 template <
typename T,
typename CharType,
size_t N>
1478 #if defined(__clang__) || defined(_MSC_VER)
1482 #endif // RAPIDJSON_POINTER_H_