60 lines
1.7 KiB
C++
60 lines
1.7 KiB
C++
#include "pointer.hpp"
|
|
|
|
#include "tree.hpp"
|
|
#include "../parse.hpp"
|
|
|
|
#include <algorithm>
|
|
#include <stdexcept>
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
::json::tree::node&
|
|
util::json::pointer::resolve (std::string const &path,
|
|
::json::tree::node &root)
|
|
{
|
|
// we only handle fragment represenations currently, which start with a '#'
|
|
auto cursor = path.begin ();
|
|
if (cursor == path.end () || *cursor != '#')
|
|
throw std::invalid_argument ("must be fragment representation");
|
|
++cursor;
|
|
|
|
auto obj = &root;
|
|
|
|
// * step over each path segment
|
|
// * index into the current node
|
|
// * advance the node
|
|
// * repeat until we reach the end of the query string
|
|
for ( ; cursor != path.end (); ) {
|
|
// step over the delimiting '/'
|
|
if (*cursor != '/')
|
|
break;
|
|
++cursor;
|
|
|
|
// find the start of the next segment (or the end of the string)
|
|
// and extract the key.
|
|
auto next = std::find (cursor, path.end (), '/');
|
|
std::string const key { cursor, next };
|
|
|
|
// try to index into the node and advance the node we're operating on
|
|
switch (obj->type ()) {
|
|
case ::json::tree::OBJECT:
|
|
obj = &(*obj)[key];
|
|
break;
|
|
|
|
case ::json::tree::ARRAY:
|
|
obj = &(*obj)[util::parse<size_t> (key)];
|
|
break;
|
|
|
|
case ::json::tree::STRING:
|
|
case ::json::tree::NUMBER:
|
|
case ::json::tree::BOOLEAN:
|
|
case ::json::tree::NONE:
|
|
throw std::invalid_argument ("indexing into wrong type");
|
|
}
|
|
|
|
// step to the beginning of the next component
|
|
cursor = next;
|
|
}
|
|
|
|
return *obj;
|
|
} |