feat: add arrayIndexOf to Json
This commit is contained in:
1 parent
bd549ca34f
commit
38068617a9
1 file changed
+99
@@ -788,3 +788,102 @@ std::string JsonWriter::indented(const JsonValue& value, int indentWidth) {
|
||||
return writer.write(value);
|
||||
}
|
||||
|
||||
JsonPointer::JsonPointer(const std::string& pointer) {
|
||||
if (pointer.empty()) return;
|
||||
if (pointer[0] != '/') {
|
||||
wellFormed = false;
|
||||
return;
|
||||
}
|
||||
std::string token;
|
||||
for (std::size_t i = 1u; i <= pointer.size(); ++i) {
|
||||
if (i == pointer.size() || pointer[i] == '/') {
|
||||
parts.push_back(token);
|
||||
token.clear();
|
||||
continue;
|
||||
}
|
||||
if (pointer[i] == '~') {
|
||||
if (i + 1u >= pointer.size()) {
|
||||
wellFormed = false;
|
||||
return;
|
||||
}
|
||||
char next = pointer[i + 1u];
|
||||
if (next == '0') {
|
||||
token.push_back('~');
|
||||
} else if (next == '1') {
|
||||
token.push_back('/');
|
||||
} else {
|
||||
wellFormed = false;
|
||||
return;
|
||||
}
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
token.push_back(pointer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
std::string JsonPointer::text() const {
|
||||
std::string out;
|
||||
for (const std::string& token : parts) {
|
||||
out.push_back('/');
|
||||
for (char c : token) {
|
||||
if (c == '~') {
|
||||
out += "~0";
|
||||
} else if (c == '/') {
|
||||
out += "~1";
|
||||
} else {
|
||||
out.push_back(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool arrayIndexOf(const std::string& token, std::size_t& out) {
|
||||
if (token.empty()) return false;
|
||||
if (token.size() > 1u && token[0] == '0') return false;
|
||||
std::size_t index = 0u;
|
||||
for (char c : token) {
|
||||
if (c < '0' || c > '9') return false;
|
||||
index = index * 10u + static_cast<std::size_t>(c - '0');
|
||||
if (index > 100000000u) return false;
|
||||
}
|
||||
out = index;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const JsonValue* JsonPointer::resolve(const JsonValue& root) const {
|
||||
if (!wellFormed) return nullptr;
|
||||
const JsonValue* here = &root;
|
||||
for (const std::string& token : parts) {
|
||||
if (here->isObject()) {
|
||||
here = here->find(token);
|
||||
if (here == nullptr) return nullptr;
|
||||
continue;
|
||||
}
|
||||
if (here->isArray()) {
|
||||
std::size_t index = 0u;
|
||||
if (!arrayIndexOf(token, index)) return nullptr;
|
||||
here = here->at(index);
|
||||
if (here == nullptr) return nullptr;
|
||||
continue;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
return here;
|
||||
}
|
||||
|
||||
JsonValue* JsonPointer::resolve(JsonValue& root) const {
|
||||
return const_cast<JsonValue*>(resolve(static_cast<const JsonValue&>(root)));
|
||||
}
|
||||
|
||||
const JsonValue* JsonPointer::find(const JsonValue& root, const std::string& pointer) {
|
||||
JsonPointer path(pointer);
|
||||
return path.resolve(root);
|
||||
}
|
||||
|
||||
} // namespace vf
|
||||
Reference in new issue
Block a user