From a2379d68713e210187149c05dd20435d7a244503 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 30 May 2019 15:35:54 -0400 Subject: 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. --- indra/llcommon/llsdutil.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'indra/llcommon/llsdutil.cpp') 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(blob), path); +} + +} // namespace llsd -- cgit v1.2.3