Add optional unresolvedTokenIndex parameter to Pointer::Get() and related
This commit is contained in:
parent
e702d3dc70
commit
cec8dcbc7a
@ -460,9 +460,18 @@ public:
|
|||||||
//! Query a value in a subtree.
|
//! Query a value in a subtree.
|
||||||
/*!
|
/*!
|
||||||
\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
|
\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
|
||||||
|
\param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
|
||||||
\return Pointer to the value if it can be resolved. Otherwise null.
|
\return Pointer to the value if it can be resolved. Otherwise null.
|
||||||
|
|
||||||
|
\note
|
||||||
|
There are only 3 situations when a value cannot be resolved:
|
||||||
|
1. A value in the path is not an array nor object.
|
||||||
|
2. An object value does not contain the token.
|
||||||
|
3. A token is out of range of an array value.
|
||||||
|
|
||||||
|
Use unresolvedTokenIndex to retrieve the token index.
|
||||||
*/
|
*/
|
||||||
ValueType* Get(ValueType& root) const {
|
ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
|
||||||
RAPIDJSON_ASSERT(IsValid());
|
RAPIDJSON_ASSERT(IsValid());
|
||||||
ValueType* v = &root;
|
ValueType* v = &root;
|
||||||
for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
|
for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
|
||||||
@ -471,18 +480,23 @@ public:
|
|||||||
{
|
{
|
||||||
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
|
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
|
||||||
if (m == v->MemberEnd())
|
if (m == v->MemberEnd())
|
||||||
return 0;
|
break;
|
||||||
v = &m->value;
|
v = &m->value;
|
||||||
}
|
}
|
||||||
break;
|
continue;
|
||||||
case kArrayType:
|
case kArrayType:
|
||||||
if (t->index == kPointerInvalidIndex || t->index >= v->Size())
|
if (t->index == kPointerInvalidIndex || t->index >= v->Size())
|
||||||
return 0;
|
break;
|
||||||
v = &((*v)[t->index]);
|
v = &((*v)[t->index]);
|
||||||
break;
|
continue;
|
||||||
default:
|
default:
|
||||||
return 0;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Error: unresolved token
|
||||||
|
if (unresolvedTokenIndex)
|
||||||
|
*unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -492,7 +506,9 @@ public:
|
|||||||
\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
|
\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
|
||||||
\return Pointer to the value if it can be resolved. Otherwise null.
|
\return Pointer to the value if it can be resolved. Otherwise null.
|
||||||
*/
|
*/
|
||||||
const ValueType* Get(const ValueType& root) const { return Get(const_cast<ValueType&>(root)); }
|
const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
|
||||||
|
return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
|
||||||
|
}
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
@ -1053,23 +1069,23 @@ typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, c
|
|||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
|
typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
|
||||||
return pointer.Get(root);
|
return pointer.Get(root, unresolvedTokenIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer) {
|
const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
|
||||||
return pointer.Get(root);
|
return pointer.Get(root, unresolvedTokenIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename CharType, size_t N>
|
template <typename T, typename CharType, size_t N>
|
||||||
typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N]) {
|
typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).Get(root);
|
return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename CharType, size_t N>
|
template <typename T, typename CharType, size_t N>
|
||||||
const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N]) {
|
const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
|
||||||
return GenericPointer<typename T::ValueType>(source, N - 1).Get(root);
|
return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -627,10 +627,15 @@ TEST(Pointer, Get) {
|
|||||||
EXPECT_EQ(&d[" "], Pointer("/ ").Get(d));
|
EXPECT_EQ(&d[" "], Pointer("/ ").Get(d));
|
||||||
EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d));
|
EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d));
|
||||||
EXPECT_TRUE(Pointer("/abc").Get(d) == 0);
|
EXPECT_TRUE(Pointer("/abc").Get(d) == 0);
|
||||||
EXPECT_TRUE(Pointer("/foo/2").Get(d) == 0); // Out of boundary
|
size_t unresolvedTokenIndex;
|
||||||
EXPECT_TRUE(Pointer("/foo/a").Get(d) == 0); // "/foo" is an array, cannot query by "a"
|
EXPECT_TRUE(Pointer("/foo/2").Get(d, &unresolvedTokenIndex) == 0); // Out of boundary
|
||||||
EXPECT_TRUE(Pointer("/foo/0/0").Get(d) == 0); // "/foo/0" is an string, cannot further query
|
EXPECT_EQ(1, unresolvedTokenIndex);
|
||||||
EXPECT_TRUE(Pointer("/foo/0/a").Get(d) == 0); // "/foo/0" is an string, cannot further query
|
EXPECT_TRUE(Pointer("/foo/a").Get(d, &unresolvedTokenIndex) == 0); // "/foo" is an array, cannot query by "a"
|
||||||
|
EXPECT_EQ(1, unresolvedTokenIndex);
|
||||||
|
EXPECT_TRUE(Pointer("/foo/0/0").Get(d, &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
|
||||||
|
EXPECT_EQ(2, unresolvedTokenIndex);
|
||||||
|
EXPECT_TRUE(Pointer("/foo/0/a").Get(d, &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
|
||||||
|
EXPECT_EQ(2, unresolvedTokenIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Pointer, GetWithDefault) {
|
TEST(Pointer, GetWithDefault) {
|
||||||
@ -947,10 +952,30 @@ TEST(Pointer, GetValueByPointer) {
|
|||||||
EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, Pointer("/foo/0")));
|
EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, Pointer("/foo/0")));
|
||||||
EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, "/foo/0"));
|
EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, "/foo/0"));
|
||||||
|
|
||||||
|
size_t unresolvedTokenIndex;
|
||||||
|
EXPECT_TRUE(GetValueByPointer(d, "/foo/2", &unresolvedTokenIndex) == 0); // Out of boundary
|
||||||
|
EXPECT_EQ(1, unresolvedTokenIndex);
|
||||||
|
EXPECT_TRUE(GetValueByPointer(d, "/foo/a", &unresolvedTokenIndex) == 0); // "/foo" is an array, cannot query by "a"
|
||||||
|
EXPECT_EQ(1, unresolvedTokenIndex);
|
||||||
|
EXPECT_TRUE(GetValueByPointer(d, "/foo/0/0", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
|
||||||
|
EXPECT_EQ(2, unresolvedTokenIndex);
|
||||||
|
EXPECT_TRUE(GetValueByPointer(d, "/foo/0/a", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
|
||||||
|
EXPECT_EQ(2, unresolvedTokenIndex);
|
||||||
|
|
||||||
// const version
|
// const version
|
||||||
const Value& v = d;
|
const Value& v = d;
|
||||||
EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, Pointer("/foo/0")));
|
EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, Pointer("/foo/0")));
|
||||||
EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, "/foo/0"));
|
EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, "/foo/0"));
|
||||||
|
|
||||||
|
EXPECT_TRUE(GetValueByPointer(v, "/foo/2", &unresolvedTokenIndex) == 0); // Out of boundary
|
||||||
|
EXPECT_EQ(1, unresolvedTokenIndex);
|
||||||
|
EXPECT_TRUE(GetValueByPointer(v, "/foo/a", &unresolvedTokenIndex) == 0); // "/foo" is an array, cannot query by "a"
|
||||||
|
EXPECT_EQ(1, unresolvedTokenIndex);
|
||||||
|
EXPECT_TRUE(GetValueByPointer(v, "/foo/0/0", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
|
||||||
|
EXPECT_EQ(2, unresolvedTokenIndex);
|
||||||
|
EXPECT_TRUE(GetValueByPointer(v, "/foo/0/a", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
|
||||||
|
EXPECT_EQ(2, unresolvedTokenIndex);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Pointer, GetValueByPointerWithDefault_Pointer) {
|
TEST(Pointer, GetValueByPointerWithDefault_Pointer) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user