summaryrefslogtreecommitdiff
path: root/indra/llcommon/llsdutil.cpp
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2019-05-30 15:35:54 -0400
committerNat Goodspeed <nat@lindenlab.com>2020-03-25 16:01:31 -0400
commita2379d68713e210187149c05dd20435d7a244503 (patch)
tree25d8aead920ec63ecc63cc1968b002ddd01b03dc /indra/llcommon/llsdutil.cpp
parent5a260e0cc3beec45da1d29578855524977206022 (diff)
SL-11216: Add llsd::drill() function to drill into an LLSD blob.
We include both const and non-const overloads. The latter returns LLSD&, so you can assign to the located element. In fact we already implemented the non-const logic in a less public form as storeToLLSDPath() in lleventcoro.cpp. Reimplement the latter to use the new llsd::drill() function.
Diffstat (limited to 'indra/llcommon/llsdutil.cpp')
-rw-r--r--indra/llcommon/llsdutil.cpp67
1 files changed, 67 insertions, 0 deletions
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index 9d00395c0a..ad27f19e85 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -681,3 +681,70 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs, int bits)
return false; // pacify the compiler
}
}
+
+/*****************************************************************************
+* llsd::drill()
+*****************************************************************************/
+namespace llsd
+{
+
+LLSD& drill(LLSD& blob, const LLSD& rawPath)
+{
+ // Treat rawPath uniformly as an array. If it's not already an array,
+ // store it as the only entry in one.
+ LLSD path;
+ if (rawPath.isArray())
+ {
+ path = rawPath;
+ }
+ else
+ {
+ path.append(rawPath);
+ }
+
+ // Need to indicate a current destination -- but that current destination
+ // must change as we step through the path array. Where normally we'd use
+ // an LLSD& to capture a subscripted LLSD lvalue, this time we must
+ // instead use a pointer -- since it must be reassigned.
+ // Start by pointing to the input blob exactly as is.
+ LLSD* located{&blob};
+
+ // Extract the element of interest by walking path. Use an explicit index
+ // so that, in case of a bogus type in path, we can identify the specific
+ // path entry that's bad.
+ for (LLSD::Integer i = 0; i < path.size(); ++i)
+ {
+ const LLSD& key{path[i]};
+ if (key.isString())
+ {
+ // a string path element is a map key
+ located = &((*located)[key.asString()]);
+ }
+ else if (key.isInteger())
+ {
+ // an integer path element is an array index
+ located = &((*located)[key.asInteger()]);
+ }
+ else
+ {
+ // What do we do with Real or Array or Map or ...?
+ // As it's a coder error -- not a user error -- rub the coder's
+ // face in it so it gets fixed.
+ LL_ERRS("llsdutil") << "drill(" << blob << ", " << rawPath
+ << "): path[" << i << "] bad type "
+ << sTypes.lookup(key.type()) << LL_ENDL;
+ }
+ }
+
+ // dereference the pointer to return a reference to the element we found
+ return *located;
+}
+
+LLSD drill(const LLSD& blob, const LLSD& path)
+{
+ // non-const drill() does exactly what we want. Temporarily cast away
+ // const-ness and use that.
+ return drill(const_cast<LLSD&>(blob), path);
+}
+
+} // namespace llsd