From 38068617a900151a8de7b9975027fd7bd2ee148d Mon Sep 17 00:00:00 2001 From: DualFroz Date: Tue, 8 Sep 2026 13:58:31 +0200 Subject: [PATCH] feat: add arrayIndexOf to Json --- core/src/Json.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/core/src/Json.cpp b/core/src/Json.cpp index 924e1e1..dd43dec 100644 --- a/core/src/Json.cpp +++ b/core/src/Json.cpp @@ -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(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(resolve(static_cast(root))); +} + +const JsonValue* JsonPointer::find(const JsonValue& root, const std::string& pointer) { + JsonPointer path(pointer); + return path.resolve(root); +} + +} // namespace vf