feat: add arrayIndexOf to Json

This commit is contained in:
dualfroz committed 2026-09-08 13:58:31 +02:00
1 parent bd549ca34f
commit 38068617a9
1 file changed
+99
+99
View File
@@ -788,3 +788,102 @@ std::string JsonWriter::indented(const JsonValue& value, int indentWidth) {
return writer.write(value); 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