#include #include "commons/commons_byteparser.h" #include "commons/commons_base.h" #include "commons/commons_json_parser.h" #include "commons/commons_json_value.h" #include "commons/commons_stringparser.h" static auto PushOut(json_parser& self, const json_value& value) -> json_value* { if (self.outSize == 0) return nullptr; json_value* ret = self.out; *ret = value; ++self.out; --self.outSize; return ret; } static auto ParseLiteral(json_parser& self) -> json_value* { switch (ByteParser_Read(self)) { case 'n': { if (!ByteParser_HasNext(self) || ByteParser_Read(self) != 'u' || !ByteParser_HasNext(self) || ByteParser_Read(self) != 'l' || !ByteParser_HasNext(self) || ByteParser_Read(self) != 'l') return nullptr; json_value val; JsonValue_SetValue(val, json_tag::Null); return PushOut(self, val); } case 't': { if (!ByteParser_HasNext(self) || ByteParser_Read(self) != 'r' || !ByteParser_HasNext(self) || ByteParser_Read(self) != 'u' || !ByteParser_HasNext(self) || ByteParser_Read(self) != 'e') return nullptr; json_value val; JsonValue_SetValue(val, true); return PushOut(self, val); } case 'f': { if (!ByteParser_HasNext(self) || ByteParser_Read(self) != 'a' || !ByteParser_HasNext(self) || ByteParser_Read(self) != 'l' || !ByteParser_HasNext(self) || ByteParser_Read(self) != 's' || !ByteParser_HasNext(self) || ByteParser_Read(self) != 'e') return nullptr; json_value val; JsonValue_SetValue(val, false); return PushOut(self, val); } default: { return nullptr; } } } static auto ParseNumber(json_parser& self) -> json_value* { double doubleVal; int64_t longVal; json_value val; switch (StringParser_ParseDecimal(self, doubleVal, longVal)) { case StringParser_ParseNumberResult::Double: { JsonValue_SetValue(val, doubleVal); break; } case StringParser_ParseNumberResult::Long: { JsonValue_SetValue(val, longVal); break; } } return PushOut(self, val); } static auto ParseString(json_parser& self) -> json_value* { const uint8_t* base = self.at; uint64_t count = 0; bool closed = false; while (ByteParser_HasNext(self)) { const uint8_t ch = ByteParser_Read(self); if (ch == '"') { closed = true; break; } ++count; // Skip escaped character — backslash escapes the next char if (ch == '\\' && ByteParser_HasNext(self)) { ByteParser_Read(self); ++count; } } if (!closed) return nullptr; json_value val; JsonValue_SetValue(val, byteview { base, count }); return PushOut(self, val); } static auto ParseArray(json_parser& self) -> json_value* { json_value* begin = PushOut(self, json_value()); if (!begin) return nullptr; int32_t count = 0; for (;;) { if (!ByteParser_HasNext(self)) return nullptr; if (ByteParser_Peek(self) == ']') { ByteParser_Advance(self); break; } ++count; json_value* elem = JsonParser_ParseNext(self); if (!elem) return nullptr; StringParser_SkipWhitespace(self); if (!ByteParser_HasNext(self)) return nullptr; const uint8_t ch = ByteParser_Read(self); if (ch == ']') break; if (ch != ',') return nullptr; } json_value* end = PushOut(self, json_value()); if (!end) return nullptr; JsonValue_SetValue(*begin, json_tag::ArrayBegin, count, end); JsonValue_SetValue(*end, json_tag::ArrayEnd); return begin; } static auto ParseObject(json_parser& self) -> json_value* { auto* begin = PushOut(self, json_value { }); if (!begin) return nullptr; uint32_t count = 0; for (;;) { if (!ByteParser_HasNext(self)) return nullptr; if (ByteParser_Peek(self) == '}') { ByteParser_Advance(self); break; } ++count; json_value* key = JsonParser_ParseNext(self); if (!key || key->tag != json_tag::String) return nullptr; StringParser_SkipWhitespace(self); if (!ByteParser_HasNext(self) || ByteParser_Read(self) != ':') return nullptr; json_value* val = JsonParser_ParseNext(self); if (!val) return nullptr; StringParser_SkipWhitespace(self); if (!ByteParser_HasNext(self)) return nullptr; const uint8_t ch = ByteParser_Read(self); if (ch == '}') break; if (ch != ',') return nullptr; } json_value* end = PushOut(self, json_value()); if (!end) return nullptr; JsonValue_SetValue(*begin, json_tag::ObjectBegin, count, end); JsonValue_SetValue(*end, json_tag::ObjectEnd); return begin; } auto API JsonParser_ParseNext(json_parser& self) -> json_value* { StringParser_SkipWhitespace(self); if (!ByteParser_HasNext(self)) return nullptr; uint8_t ch = ByteParser_Peek(self); if (IsNumber(ch) || ch == '-') return ParseNumber(self); if (IsAlpha(ch)) return ParseLiteral(self); if (!ByteParser_HasNext(self)) return nullptr; ByteParser_Advance(self); if (ch == '"') return ParseString(self); if (ch == '[') return ParseArray(self); if (ch == '{') return ParseObject(self); return nullptr; }