feat: extend Json
This commit is contained in:
1 parent
fde84ea3d7
commit
1656cdc870
1 file changed
+143
@@ -155,3 +155,146 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseValue(int depth, JsonValue& out) {
|
||||
if (atEnd()) {
|
||||
fail("unexpected end of input, expected a value");
|
||||
return false;
|
||||
}
|
||||
char c = peek();
|
||||
if (c == '{') return parseObject(depth, out);
|
||||
if (c == '[') return parseArray(depth, out);
|
||||
if (c == '"') {
|
||||
std::string text;
|
||||
if (!parseString(text)) return false;
|
||||
out = JsonValue::makeString(std::move(text));
|
||||
return true;
|
||||
}
|
||||
if (c == '-' || (c >= '0' && c <= '9')) return parseNumber(out);
|
||||
if (c == 't') return parseLiteral("true", JsonValue::makeBool(true), out);
|
||||
if (c == 'f') return parseLiteral("false", JsonValue::makeBool(false), out);
|
||||
if (c == 'n') return parseLiteral("null", JsonValue::makeNull(), out);
|
||||
fail(std::string("unexpected character '") + c + "', expected a value");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool parseLiteral(const char* word, JsonValue value, JsonValue& out) {
|
||||
std::size_t length = std::strlen(word);
|
||||
if (src.compare(cursor, length, word) != 0) {
|
||||
fail(std::string("unknown literal, expected ") + word);
|
||||
return false;
|
||||
}
|
||||
for (std::size_t i = 0u; i < length; ++i) advance();
|
||||
out = std::move(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseObject(int depth, JsonValue& out) {
|
||||
if (depth > depthLimit) {
|
||||
fail("nesting deeper than the " + std::to_string(depthLimit) + " level limit");
|
||||
return false;
|
||||
}
|
||||
advance();
|
||||
out = JsonValue::makeObject();
|
||||
skipWhitespace();
|
||||
if (!atEnd() && peek() == '}') {
|
||||
advance();
|
||||
return true;
|
||||
}
|
||||
for (;;) {
|
||||
skipWhitespace();
|
||||
if (atEnd() || peek() != '"') {
|
||||
fail("expected a quoted member name");
|
||||
return false;
|
||||
}
|
||||
std::string key;
|
||||
if (!parseString(key)) return false;
|
||||
skipWhitespace();
|
||||
if (!expect(':', "expected ':' after the member name")) return false;
|
||||
skipWhitespace();
|
||||
JsonValue member;
|
||||
if (!parseValue(depth + 1, member)) return false;
|
||||
out.set(key, std::move(member));
|
||||
skipWhitespace();
|
||||
if (atEnd()) {
|
||||
fail("unexpected end of input, expected ',' or '}'");
|
||||
return false;
|
||||
}
|
||||
char c = peek();
|
||||
if (c == ',') {
|
||||
advance();
|
||||
skipWhitespace();
|
||||
if (!atEnd() && peek() == '}') {
|
||||
fail("trailing comma before '}'");
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (c == '}') {
|
||||
advance();
|
||||
return true;
|
||||
}
|
||||
fail(std::string("unexpected character '") + c + "', expected ',' or '}'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool parseArray(int depth, JsonValue& out) {
|
||||
if (depth > depthLimit) {
|
||||
fail("nesting deeper than the " + std::to_string(depthLimit) + " level limit");
|
||||
return false;
|
||||
}
|
||||
advance();
|
||||
out = JsonValue::makeArray();
|
||||
skipWhitespace();
|
||||
if (!atEnd() && peek() == ']') {
|
||||
advance();
|
||||
return true;
|
||||
}
|
||||
for (;;) {
|
||||
skipWhitespace();
|
||||
JsonValue element;
|
||||
if (!parseValue(depth + 1, element)) return false;
|
||||
out.push(std::move(element));
|
||||
skipWhitespace();
|
||||
if (atEnd()) {
|
||||
fail("unexpected end of input, expected ',' or ']'");
|
||||
return false;
|
||||
}
|
||||
char c = peek();
|
||||
if (c == ',') {
|
||||
advance();
|
||||
skipWhitespace();
|
||||
if (!atEnd() && peek() == ']') {
|
||||
fail("trailing comma before ']'");
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (c == ']') {
|
||||
advance();
|
||||
return true;
|
||||
}
|
||||
fail(std::string("unexpected character '") + c + "', expected ',' or ']'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool parseHexQuad(uint32_t& out) {
|
||||
uint32_t value = 0u;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (atEnd()) {
|
||||
fail("unexpected end of input inside a \\u escape");
|
||||
return false;
|
||||
}
|
||||
int digit = hexDigitValue(peek());
|
||||
if (digit < 0) {
|
||||
fail(std::string("'") + peek() + "' is not a hexadecimal digit");
|
||||
return false;
|
||||
}
|
||||
value = (value << 4) | static_cast<uint32_t>(digit);
|
||||
advance();
|
||||
}
|
||||
out = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user