6 #if !defined(JSON_IS_AMALGAMATION)
10 #endif // if !defined(JSON_IS_AMALGAMATION)
17 #include <cpptl/conststring.h>
23 #if defined(_MSC_VER) && _MSC_VER < 1900
26 const char* format, va_list ap) {
29 count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
31 count = _vscprintf(format, ap);
36 const char* format, ...) {
47 #pragma warning(disable : 4702)
50 #define JSON_ASSERT_UNREACHABLE assert(false)
54 static std::unique_ptr<T>
cloneUnique(
const std::unique_ptr<T>& p) {
57 r = std::unique_ptr<T>(
new T(*p));
65 #if defined(__ARMEL__)
66 #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
68 #define ALIGNAS(byte_alignment)
73 static Value const nullStatic;
87 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
88 template <
typename T,
typename U>
89 static inline bool InRange(
double d, T min, U max) {
92 return d >= static_cast<double>(min) && d <= static_cast<double>(max);
94 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
95 static inline double integerToDouble(
Json::UInt64 value) {
96 return static_cast<double>(
Int64(value / 2)) * 2.0 +
97 static_cast<double>(
Int64(value & 1));
100 template <
typename T>
static inline double integerToDouble(T value) {
101 return static_cast<double>(value);
104 template <
typename T,
typename U>
105 static inline bool InRange(
double d, T min, U max) {
106 return d >= integerToDouble(min) && d <= integerToDouble(max);
108 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
123 char* newString = static_cast<char*>(malloc(length + 1));
124 if (newString ==
nullptr) {
125 throwRuntimeError(
"in Json::Value::duplicateStringValue(): "
126 "Failed to allocate string value buffer");
128 memcpy(newString, value, length);
129 newString[length] = 0;
136 unsigned int length) {
140 sizeof(
unsigned) - 1U,
141 "in Json::Value::duplicateAndPrefixStringValue(): "
142 "length too big for prefixing");
143 unsigned actualLength = length + static_cast<unsigned>(
sizeof(
unsigned)) + 1U;
144 char* newString = static_cast<char*>(malloc(actualLength));
145 if (newString ==
nullptr) {
146 throwRuntimeError(
"in Json::Value::duplicateAndPrefixStringValue(): "
147 "Failed to allocate string value buffer");
149 *reinterpret_cast<unsigned*>(newString) = length;
150 memcpy(newString +
sizeof(
unsigned), value, length);
151 newString[actualLength - 1U] =
156 unsigned* length,
char const** value) {
158 *length = static_cast<unsigned>(strlen(prefixed));
161 *length = *reinterpret_cast<unsigned const*>(prefixed);
162 *value = prefixed +
sizeof(unsigned);
168 #if JSONCPP_USING_SECURE_MEMORY
171 char const* valueDecoded;
173 size_t const size =
sizeof(unsigned) + length + 1U;
174 memset(value, 0, size);
179 size_t size = (length == 0) ? strlen(value) : length;
180 memset(value, 0, size);
183 #else // !JSONCPP_USING_SECURE_MEMORY
186 #endif // JSONCPP_USING_SECURE_MEMORY
197 #if !defined(JSON_IS_AMALGAMATION)
200 #endif // if !defined(JSON_IS_AMALGAMATION)
204 #if JSON_USE_EXCEPTION
214 throw LogicError(msg);
216 #else // !JSON_USE_EXCEPTION
232 Value::CZString::CZString(
ArrayIndex index) : cstr_(nullptr), index_(index) {}
234 Value::CZString::CZString(
char const* str,
unsigned length,
235 DuplicationPolicy allocate)
238 storage_.policy_ = allocate & 0x3;
239 storage_.length_ = length & 0x3FFFFFFF;
242 Value::CZString::CZString(
const CZString& other) {
243 cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ !=
nullptr
247 static_cast<unsigned>(
249 ? (static_cast<DuplicationPolicy>(other.storage_.policy_) ==
253 : static_cast<DuplicationPolicy>(other.storage_.policy_)) &
255 storage_.length_ = other.storage_.length_;
258 Value::CZString::CZString(CZString&& other)
259 : cstr_(other.cstr_), index_(other.index_) {
260 other.cstr_ =
nullptr;
263 Value::CZString::~CZString() {
264 if (cstr_ && storage_.policy_ == duplicate) {
266 storage_.length_ + 1U);
278 Value::CZString& Value::CZString::operator=(
const CZString& other) {
280 index_ = other.index_;
284 Value::CZString& Value::CZString::operator=(CZString&& other) {
286 index_ = other.index_;
287 other.cstr_ =
nullptr;
291 bool Value::CZString::operator<(
const CZString& other)
const {
293 return index_ < other.index_;
296 unsigned this_len = this->storage_.length_;
297 unsigned other_len = other.storage_.length_;
298 unsigned min_len = std::min<unsigned>(this_len, other_len);
300 int comp = memcmp(this->cstr_, other.cstr_, min_len);
305 return (this_len < other_len);
310 return index_ == other.index_;
313 unsigned this_len = this->storage_.length_;
314 unsigned other_len = other.storage_.length_;
315 if (this_len != other_len)
318 int comp = memcmp(this->cstr_, other.cstr_, this_len);
322 ArrayIndex Value::CZString::index()
const {
return index_; }
325 const char* Value::CZString::data()
const {
return cstr_; }
326 unsigned Value::CZString::length()
const {
return storage_.length_; }
327 bool Value::CZString::isStaticString()
const {
328 return storage_.policy_ == noDuplication;
344 static char const emptyString[] =
"";
358 value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
362 value_.map_ =
new ObjectValues();
365 value_.bool_ =
false;
379 value_.uint_ = value;
381 #if defined(JSON_HAS_INT64)
388 value_.uint_ = value;
390 #endif // defined(JSON_HAS_INT64)
392 Value::Value(
double value) {
394 value_.real_ = value;
397 Value::Value(
const char* value) {
400 "Null Value Passed to Value Constructor");
402 value, static_cast<unsigned>(strlen(value)));
405 Value::Value(
const char* begin,
const char* end) {
414 value.data(), static_cast<unsigned>(value.length()));
419 value_.string_ = const_cast<char*>(value.
c_str());
422 #ifdef JSON_USE_CPPTL
423 Value::Value(
const CppTL::ConstString& value) {
426 value, static_cast<unsigned>(value.length()));
430 Value::Value(
bool value) {
432 value_.bool_ = value;
460 void Value::swapPayload(
Value& other) {
465 void Value::copyPayload(
const Value& other) {
477 void Value::copy(
const Value& other) {
483 return static_cast<ValueType>(bits_.value_type_);
486 int Value::compare(
const Value& other)
const {
494 bool Value::operator<(
const Value& other)
const {
495 int typeDelta = type() - other.
type();
497 return typeDelta < 0;
502 return value_.int_ < other.value_.int_;
504 return value_.uint_ < other.value_.uint_;
506 return value_.real_ < other.value_.real_;
508 return value_.bool_ < other.value_.bool_;
510 if ((value_.string_ ==
nullptr) || (other.value_.string_ ==
nullptr)) {
511 return other.value_.string_ !=
nullptr;
515 char const* this_str;
516 char const* other_str;
521 unsigned min_len = std::min<unsigned>(this_len, other_len);
523 int comp = memcmp(this_str, other_str, min_len);
528 return (this_len < other_len);
532 int delta = int(value_.map_->size() - other.value_.map_->size());
535 return (*value_.map_) < (*other.value_.map_);
543 bool Value::operator<=(
const Value& other)
const {
return !(other < *
this); }
545 bool Value::operator>=(
const Value& other)
const {
return !(*
this < other); }
547 bool Value::operator>(
const Value& other)
const {
return other < *
this; }
550 if (type() != other.
type())
556 return value_.int_ == other.value_.int_;
558 return value_.uint_ == other.value_.uint_;
560 return value_.real_ == other.value_.real_;
562 return value_.bool_ == other.value_.bool_;
564 if ((value_.string_ ==
nullptr) || (other.value_.string_ ==
nullptr)) {
565 return (value_.string_ == other.value_.string_);
569 char const* this_str;
570 char const* other_str;
575 if (this_len != other_len)
578 int comp = memcmp(this_str, other_str, this_len);
583 return value_.map_->size() == other.value_.map_->size() &&
584 (*value_.map_) == (*other.value_.map_);
593 const char* Value::asCString()
const {
595 "in Json::Value::asCString(): requires stringValue");
596 if (value_.string_ ==
nullptr)
599 char const* this_str;
605 #if JSONCPP_USING_SECURE_MEMORY
606 unsigned Value::getCStringLength()
const {
608 "in Json::Value::asCString(): requires stringValue");
609 if (value_.string_ == 0)
612 char const* this_str;
619 bool Value::getString(
char const** begin,
char const** end)
const {
622 if (value_.string_ ==
nullptr)
627 *end = *begin + length;
636 if (value_.string_ ==
nullptr)
639 char const* this_str;
642 return String(this_str, this_len);
645 return value_.bool_ ?
"true" :
"false";
657 #ifdef JSON_USE_CPPTL
658 CppTL::ConstString Value::asConstString()
const {
662 return CppTL::ConstString(str, len);
670 return Int(value_.int_);
673 return Int(value_.uint_);
676 "double out of Int range");
677 return Int(value_.real_);
681 return value_.bool_ ? 1 : 0;
692 return UInt(value_.int_);
695 return UInt(value_.uint_);
698 "double out of UInt range");
699 return UInt(value_.real_);
703 return value_.bool_ ? 1 : 0;
710 #if defined(JSON_HAS_INT64)
715 return Int64(value_.int_);
718 return Int64(value_.uint_);
721 "double out of Int64 range");
722 return Int64(value_.real_);
726 return value_.bool_ ? 1 : 0;
737 return UInt64(value_.int_);
739 return UInt64(value_.uint_);
742 "double out of UInt64 range");
743 return UInt64(value_.real_);
747 return value_.bool_ ? 1 : 0;
753 #endif // if defined(JSON_HAS_INT64)
756 #if defined(JSON_NO_INT64)
764 #if defined(JSON_NO_INT64)
771 double Value::asDouble()
const {
774 return static_cast<double>(value_.int_);
776 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
777 return static_cast<double>(value_.uint_);
778 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
779 return integerToDouble(value_.uint_);
780 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
786 return value_.bool_ ? 1.0 : 0.0;
793 float Value::asFloat()
const {
796 return static_cast<float>(value_.int_);
798 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
799 return static_cast<float>(value_.uint_);
800 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
802 return static_cast<float>(integerToDouble(value_.uint_));
803 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
805 return static_cast<float>(value_.real_);
809 return value_.bool_ ? 1.0F : 0.0F;
816 bool Value::asBool()
const {
823 return value_.int_ != 0;
825 return value_.uint_ != 0;
828 const auto value_classification = std::fpclassify(value_.real_);
829 return value_classification != FP_ZERO && value_classification != FP_NAN;
840 return (isNumeric() && asDouble() == 0.0) ||
843 (type() ==
arrayValue && value_.map_->empty()) ||
881 if (!value_.map_->empty()) {
882 ObjectValues::const_iterator itLast = value_.map_->end();
884 return (*itLast).first.index() + 1;
894 bool Value::empty()
const {
895 if (isNull() || isArray() || isObject())
901 Value::operator bool()
const {
return !isNull(); }
903 void Value::clear() {
906 "in Json::Value::clear(): requires complex value");
912 value_.map_->clear();
921 "in Json::Value::resize(): requires arrayValue");
927 else if (newSize > oldSize)
928 this->operator[](newSize - 1);
930 for (
ArrayIndex index = newSize; index < oldSize; ++index) {
931 value_.map_->erase(index);
940 "in Json::Value::operator[](ArrayIndex): requires arrayValue");
944 auto it = value_.map_->lower_bound(key);
945 if (it != value_.map_->end() && (*it).first == key)
948 ObjectValues::value_type defaultValue(key, nullSingleton());
949 it = value_.map_->insert(it, defaultValue);
953 Value& Value::operator[](
int index) {
956 "in Json::Value::operator[](int index): index cannot be negative");
963 "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
965 return nullSingleton();
967 ObjectValues::const_iterator it = value_.map_->find(key);
968 if (it == value_.map_->end())
969 return nullSingleton();
973 const Value& Value::operator[](
int index)
const {
976 "in Json::Value::operator[](int index) const: index cannot be negative");
980 void Value::initBasic(
ValueType type,
bool allocated) {
982 setIsAllocated(allocated);
983 comments_ = Comments{};
988 void Value::dupPayload(
const Value& other) {
989 setType(other.type());
990 setIsAllocated(
false);
997 value_ = other.value_;
1000 if (other.value_.string_ && other.isAllocated()) {
1006 setIsAllocated(
true);
1008 value_.string_ = other.value_.string_;
1013 value_.map_ =
new ObjectValues(*other.value_.map_);
1020 void Value::releasePayload() {
1041 void Value::dupMeta(
const Value& other) {
1042 comments_ = other.comments_;
1043 start_ = other.start_;
1044 limit_ = other.limit_;
1050 Value& Value::resolveReference(
const char* key) {
1053 "in Json::Value::resolveReference(): requires objectValue");
1056 CZString actualKey(key, static_cast<unsigned>(strlen(key)),
1057 CZString::noDuplication);
1058 auto it = value_.map_->lower_bound(actualKey);
1059 if (it != value_.map_->end() && (*it).first == actualKey)
1060 return (*it).second;
1062 ObjectValues::value_type defaultValue(actualKey, nullSingleton());
1063 it = value_.map_->insert(it, defaultValue);
1064 Value& value = (*it).second;
1069 Value& Value::resolveReference(
char const* key,
char const* end) {
1072 "in Json::Value::resolveReference(key, end): requires objectValue");
1075 CZString actualKey(key, static_cast<unsigned>(end - key),
1076 CZString::duplicateOnCopy);
1077 auto it = value_.map_->lower_bound(actualKey);
1078 if (it != value_.map_->end() && (*it).first == actualKey)
1079 return (*it).second;
1081 ObjectValues::value_type defaultValue(actualKey, nullSingleton());
1082 it = value_.map_->insert(it, defaultValue);
1083 Value& value = (*it).second;
1088 const Value* value = &((*this)[index]);
1089 return value == &nullSingleton() ? defaultValue : *value;
1092 bool Value::isValidIndex(
ArrayIndex index)
const {
return index < size(); }
1094 Value const* Value::find(
char const* begin,
char const* end)
const {
1096 "in Json::Value::find(begin, end): requires "
1097 "objectValue or nullValue");
1100 CZString actualKey(begin, static_cast<unsigned>(end - begin),
1101 CZString::noDuplication);
1102 ObjectValues::const_iterator it = value_.map_->find(actualKey);
1103 if (it == value_.map_->end())
1105 return &(*it).second;
1107 Value* Value::demand(
char const* begin,
char const* end) {
1109 "in Json::Value::demand(begin, end): requires "
1110 "objectValue or nullValue");
1111 return &resolveReference(begin, end);
1113 const Value& Value::operator[](
const char* key)
const {
1114 Value const* found = find(key, key + strlen(key));
1116 return nullSingleton();
1120 Value const* found = find(key.data(), key.data() + key.length());
1122 return nullSingleton();
1126 Value& Value::operator[](
const char* key) {
1127 return resolveReference(key, key + strlen(key));
1131 return resolveReference(key.data(), key.data() + key.length());
1135 return resolveReference(key.
c_str());
1138 #ifdef JSON_USE_CPPTL
1139 Value& Value::operator[](
const CppTL::ConstString& key) {
1140 return resolveReference(key.c_str(), key.end_c_str());
1142 Value
const& Value::operator[](CppTL::ConstString
const& key)
const {
1143 Value
const* found = find(key.c_str(), key.end_c_str());
1145 return nullSingleton();
1154 "in Json::Value::append: requires arrayValue");
1158 return this->value_.map_->emplace(size(), std::move(value)).first->second;
1163 "in Json::Value::insert: requires arrayValue");
1165 if (index > length) {
1168 for (
ArrayIndex i = length; i > index; i--) {
1169 (*this)[i] = std::move((*
this)[i - 1]);
1171 (*this)[index] = std::move(newValue);
1176 Value Value::get(
char const* begin,
char const* end,
1177 Value const& defaultValue)
const {
1178 Value const* found = find(begin, end);
1179 return !found ? defaultValue : *found;
1181 Value Value::get(
char const* key,
Value const& defaultValue)
const {
1182 return get(key, key + strlen(key), defaultValue);
1185 return get(key.data(), key.data() + key.length(), defaultValue);
1188 bool Value::removeMember(
const char* begin,
const char* end,
Value* removed) {
1192 CZString actualKey(begin, static_cast<unsigned>(end - begin),
1193 CZString::noDuplication);
1194 auto it = value_.map_->find(actualKey);
1195 if (it == value_.map_->end())
1198 *removed = std::move(it->second);
1199 value_.map_->erase(it);
1202 bool Value::removeMember(
const char* key,
Value* removed) {
1203 return removeMember(key, key + strlen(key), removed);
1206 return removeMember(key.data(), key.data() + key.length(), removed);
1208 void Value::removeMember(
const char* key) {
1210 "in Json::Value::removeMember(): requires objectValue");
1214 CZString actualKey(key,
unsigned(strlen(key)), CZString::noDuplication);
1215 value_.map_->erase(actualKey);
1217 void Value::removeMember(
const String& key) { removeMember(key.c_str()); }
1223 CZString key(index);
1224 auto it = value_.map_->find(key);
1225 if (it == value_.map_->end()) {
1229 *removed = it->second;
1232 for (
ArrayIndex i = index; i < (oldSize - 1); ++i) {
1234 (*value_.map_)[keey] = (*
this)[i + 1];
1237 CZString keyLast(oldSize - 1);
1238 auto itLast = value_.map_->find(keyLast);
1239 value_.map_->erase(itLast);
1243 #ifdef JSON_USE_CPPTL
1244 Value Value::get(
const CppTL::ConstString& key,
1245 const Value& defaultValue)
const {
1246 return get(key.c_str(), key.end_c_str(), defaultValue);
1250 bool Value::isMember(
char const* begin,
char const* end)
const {
1251 Value const* value = find(begin, end);
1252 return nullptr != value;
1254 bool Value::isMember(
char const* key)
const {
1255 return isMember(key, key + strlen(key));
1257 bool Value::isMember(
String const& key)
const {
1258 return isMember(key.data(), key.data() + key.length());
1261 #ifdef JSON_USE_CPPTL
1262 bool Value::isMember(
const CppTL::ConstString& key)
const {
1263 return isMember(key.c_str(), key.end_c_str());
1270 "in Json::Value::getMemberNames(), value must be objectValue");
1274 members.reserve(value_.map_->size());
1275 ObjectValues::const_iterator it = value_.map_->begin();
1276 ObjectValues::const_iterator itEnd = value_.map_->end();
1277 for (; it != itEnd; ++it) {
1278 members.push_back(
String((*it).first.data(), (*it).first.length()));
1309 double integral_part;
1310 return modf(d, &integral_part) == 0.0;
1317 bool Value::isInt()
const {
1320 #if defined(JSON_HAS_INT64)
1321 return value_.int_ >= minInt && value_.int_ <= maxInt;
1326 return value_.uint_ <=
UInt(maxInt);
1328 return value_.real_ >= minInt && value_.real_ <= maxInt &&
1336 bool Value::isUInt()
const {
1339 #if defined(JSON_HAS_INT64)
1342 return value_.int_ >= 0;
1345 #if defined(JSON_HAS_INT64)
1346 return value_.uint_ <= maxUInt;
1351 return value_.real_ >= 0 && value_.real_ <= maxUInt &&
1359 bool Value::isInt64()
const {
1360 #if defined(JSON_HAS_INT64)
1365 return value_.uint_ <=
UInt64(maxInt64);
1370 return value_.real_ >= double(minInt64) &&
1371 value_.real_ < double(maxInt64) &&
IsIntegral(value_.real_);
1375 #endif // JSON_HAS_INT64
1379 bool Value::isUInt64()
const {
1380 #if defined(JSON_HAS_INT64)
1383 return value_.int_ >= 0;
1390 return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
1395 #endif // JSON_HAS_INT64
1399 bool Value::isIntegral()
const {
1405 #if defined(JSON_HAS_INT64)
1409 return value_.real_ >= double(minInt64) &&
1410 value_.real_ < maxUInt64AsDouble &&
IsIntegral(value_.real_);
1412 return value_.real_ >= minInt && value_.real_ <= maxUInt &&
1414 #endif // JSON_HAS_INT64
1421 bool Value::isDouble()
const {
1425 bool Value::isNumeric()
const {
return isDouble(); }
1433 Value::Comments::Comments(
const Comments& that)
1436 Value::Comments::Comments(Comments&& that) : ptr_{std::move(that.ptr_)} {}
1438 Value::Comments& Value::Comments::operator=(
const Comments& that) {
1443 Value::Comments& Value::Comments::operator=(Comments&& that) {
1444 ptr_ = std::move(that.ptr_);
1449 return ptr_ && !(*ptr_)[slot].empty();
1455 return (*ptr_)[slot];
1460 ptr_ = std::unique_ptr<Array>(
new Array());
1464 (*ptr_)[slot] = std::move(comment);
1469 if (!comment.empty() && (comment.back() ==
'\n')) {
1475 comment[0] ==
'\0' || comment[0] ==
'/',
1476 "in Json::Value::setComment(): Comments must start with /");
1477 comments_.set(
placement, std::move(comment));
1537 return iterator(value_.map_->begin());
1550 return iterator(value_.map_->end());
1564 : index_(index), kind_(kindIndex) {}
1586 void Path::makePath(
const String& path,
const InArgs& in) {
1587 const char* current = path.c_str();
1588 const char* end = current + path.length();
1589 auto itInArg = in.begin();
1590 while (current != end) {
1591 if (*current ==
'[') {
1593 if (*current ==
'%')
1594 addPathInArg(path, in, itInArg, PathArgument::kindIndex);
1597 for (; current != end && *current >=
'0' && *current <=
'9'; ++current)
1598 index = index * 10 +
ArrayIndex(*current -
'0');
1599 args_.push_back(index);
1601 if (current == end || *++current !=
']')
1602 invalidPath(path,
int(current - path.c_str()));
1603 }
else if (*current ==
'%') {
1604 addPathInArg(path, in, itInArg, PathArgument::kindKey);
1606 }
else if (*current ==
'.' || *current ==
']') {
1609 const char* beginName = current;
1610 while (current != end && !strchr(
"[.", *current))
1612 args_.push_back(
String(beginName, current));
1617 void Path::addPathInArg(
const String& ,
const InArgs& in,
1618 InArgs::const_iterator& itInArg,
1619 PathArgument::Kind kind) {
1620 if (itInArg == in.end()) {
1622 }
else if ((*itInArg)->kind_ != kind) {
1625 args_.push_back(**itInArg++);
1629 void Path::invalidPath(
const String& ,
int ) {
1634 const Value* node = &root;
1635 for (
const auto& arg : args_) {
1636 if (arg.kind_ == PathArgument::kindIndex) {
1641 node = &((*node)[arg.index_]);
1642 }
else if (arg.kind_ == PathArgument::kindKey) {
1647 node = &((*node)[arg.key_]);
1659 const Value* node = &root;
1660 for (
const auto& arg : args_) {
1661 if (arg.kind_ == PathArgument::kindIndex) {
1663 return defaultValue;
1664 node = &((*node)[arg.index_]);
1665 }
else if (arg.kind_ == PathArgument::kindKey) {
1667 return defaultValue;
1668 node = &((*node)[arg.key_]);
1670 return defaultValue;
1677 Value* node = &root;
1678 for (
const auto& arg : args_) {
1679 if (arg.kind_ == PathArgument::kindIndex) {
1683 node = &((*node)[arg.index_]);
1684 }
else if (arg.kind_ == PathArgument::kindKey) {
1688 node = &((*node)[arg.key_]);