feat: add parseJson to Json

This commit is contained in:
dualfroz committed 2026-09-08 13:16:58 +02:00
1 parent 9be045c7da
commit bd549ca34f
1 file changed
+160
+160
View File
@@ -628,3 +628,163 @@ std::string JsonValue::stringOr(const std::string& key, const std::string& fallb
return member ? member->stringOr(fallback) : fallback;
}
bool JsonValue::operator==(const JsonValue& other) const {
if (type != other.type) return false;
switch (type) {
case JsonType::Null: return true;
case JsonType::Bool: return boolPayload == other.boolPayload;
case JsonType::Number: return numberValue() == other.numberValue();
case JsonType::String: return stringPayload == other.stringPayload;
case JsonType::Array: return arrayPayload == other.arrayPayload;
case JsonType::Object: return objectPayload == other.objectPayload;
}
return false;
}
std::string JsonParseError::text() const {
if (!present()) return "no error";
return std::to_string(line) + ":" + std::to_string(column) + ": " + message;
}
JsonParseResult parseJson(const std::string& text, int maxDepth) {
Parser parser(text, maxDepth < 1 ? 1 : maxDepth);
return parser.run();
}
void JsonWriter::writeString(const std::string& value, std::string& out) const {
static const char* hexDigits = "0123456789abcdef";
out.push_back('"');
std::size_t at = 0u;
while (at < value.size()) {
unsigned char c = static_cast<unsigned char>(value[at]);
if (c == '"' || c == '\\') {
out.push_back('\\');
out.push_back(static_cast<char>(c));
++at;
continue;
}
if (c == '\b') { out += "\\b"; ++at; continue; }
if (c == '\f') { out += "\\f"; ++at; continue; }
if (c == '\n') { out += "\\n"; ++at; continue; }
if (c == '\r') { out += "\\r"; ++at; continue; }
if (c == '\t') { out += "\\t"; ++at; continue; }
if (c < 0x20u) {
out += "\\u00";
out.push_back(hexDigits[(c >> 4) & 0xFu]);
out.push_back(hexDigits[c & 0xFu]);
++at;
continue;
}
if (c < 0x80u || !escapeNonAscii) {
out.push_back(value[at]);
++at;
continue;
}
uint32_t codePoint = 0u;
std::size_t length = decodeUtf8(value, at, codePoint);
if (length == 0u) {
// Only reachable for a hand built string that never went through the
// parser; the byte is kept so nothing is silently rewritten.
out.push_back(value[at]);
++at;
continue;
}
if (codePoint >= 0x10000u) {
uint32_t rest = codePoint - 0x10000u;
uint32_t high = 0xD800u + (rest >> 10);
uint32_t low = 0xDC00u + (rest & 0x3FFu);
for (uint32_t unit : {high, low}) {
out += "\\u";
for (int shift = 12; shift >= 0; shift -= 4)
out.push_back(hexDigits[(unit >> shift) & 0xFu]);
}
} else {
out += "\\u";
for (int shift = 12; shift >= 0; shift -= 4)
out.push_back(hexDigits[(codePoint >> shift) & 0xFu]);
}
at += length;
}
out.push_back('"');
}
void JsonWriter::writeValue(const JsonValue& value, int depth, std::string& out) const {
const bool pretty = indentWidth > 0;
const std::string inner = pretty ? std::string(static_cast<std::size_t>(indentWidth * (depth + 1)), ' ')
: std::string();
const std::string outer = pretty ? std::string(static_cast<std::size_t>(indentWidth * depth), ' ')
: std::string();
switch (value.kind()) {
case JsonType::Null: out += "null"; return;
case JsonType::Bool: out += value.boolValue() ? "true" : "false"; return;
case JsonType::Number: out += formatNumber(value); return;
case JsonType::String: writeString(value.stringValue(), out); return;
case JsonType::Array: {
if (value.elements().empty()) {
out += "[]";
return;
}
out.push_back('[');
bool first = true;
for (const JsonValue& element : value.elements()) {
if (!first) out.push_back(',');
first = false;
if (pretty) {
out.push_back('\n');
out += inner;
}
writeValue(element, depth + 1, out);
}
if (pretty) {
out.push_back('\n');
out += outer;
}
out.push_back(']');
return;
}
case JsonType::Object: {
if (value.members().empty()) {
out += "{}";
return;
}
out.push_back('{');
bool first = true;
for (const JsonValue::Member& member : value.members()) {
if (!first) out.push_back(',');
first = false;
if (pretty) {
out.push_back('\n');
out += inner;
}
writeString(member.first, out);
out.push_back(':');
if (pretty) out.push_back(' ');
writeValue(member.second, depth + 1, out);
}
if (pretty) {
out.push_back('\n');
out += outer;
}
out.push_back('}');
return;
}
}
}
std::string JsonWriter::write(const JsonValue& value) const {
std::string out;
writeValue(value, 0, out);
return out;
}
std::string JsonWriter::compact(const JsonValue& value) {
JsonWriter writer;
return writer.write(value);
}
std::string JsonWriter::indented(const JsonValue& value, int indentWidth) {
JsonWriter writer;
writer.indentWidth = indentWidth;
return writer.write(value);
}