From 271db9a6f1a14dd3f76a1f1a8a8f43059fbd0f12 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 16 Sep 2024 22:23:22 +0300 Subject: [PATCH] add dv::value support to json::parse --- src/coders/json.cpp | 125 ++++++++++++++++++++++++++++++++++++++++++- src/coders/json.hpp | 3 ++ test/coders/json.cpp | 24 ++++----- 3 files changed, 139 insertions(+), 13 deletions(-) diff --git a/src/coders/json.cpp b/src/coders/json.cpp index aa8294b9..a57f5b1f 100644 --- a/src/coders/json.cpp +++ b/src/coders/json.cpp @@ -23,6 +23,16 @@ public: std::unique_ptr parse(); }; +class ParserDV : BasicParser { + dv::value parseList(); + dv::value parseObject(); + dv::value parseValue(); +public: + ParserDV(std::string_view filename, std::string_view source); + + dv::value parse(); +}; + inline void newline( std::stringstream& ss, bool nice, uint indent, const std::string& indentstr ) { @@ -362,7 +372,11 @@ std::unique_ptr Parser::parseList() { Value Parser::parseValue() { char next = peek(); if (next == '-' || next == '+' || is_digit(next)) { - return parseNumber(); + auto numeric = parseNumber(); + if (std::holds_alternative(numeric)) { + return std::get(numeric); + } + return std::get(numeric); } if (is_identifier_start(next)) { std::string literal = parseName(); @@ -400,3 +414,112 @@ dynamic::Map_sptr json::parse( dynamic::Map_sptr json::parse(std::string_view source) { return parse("", source); } + +ParserDV::ParserDV(std::string_view filename, std::string_view source) + : BasicParser(filename, source) { +} + +dv::value ParserDV::parse() { + char next = peek(); + if (next != '{') { + throw error("'{' expected"); + } + return parseObject(); +} + +dv::value ParserDV::parseObject() { + expect('{'); + auto object = dv::object(); + while (peek() != '}') { + if (peek() == '#') { + skipLine(); + continue; + } + std::string key = parseName(); + char next = peek(); + if (next != ':') { + throw error("':' expected"); + } + pos++; + object[key] = parseValue(); + next = peek(); + if (next == ',') { + pos++; + } else if (next == '}') { + break; + } else { + throw error("',' expected"); + } + } + pos++; + return object; +} + +dv::value ParserDV::parseList() { + expect('['); + auto list = dv::list(); + while (peek() != ']') { + if (peek() == '#') { + skipLine(); + continue; + } + list.add(parseValue()); + + char next = peek(); + if (next == ',') { + pos++; + } else if (next == ']') { + break; + } else { + throw error("',' expected"); + } + } + pos++; + return list; +} + +dv::value ParserDV::parseValue() { + char next = peek(); + if (next == '-' || next == '+' || is_digit(next)) { + auto numeric = parseNumber(); + if (std::holds_alternative(numeric)) { + return std::get(numeric); + } + return std::get(numeric); + } + if (is_identifier_start(next)) { + std::string literal = parseName(); + if (literal == "true") { + return true; + } else if (literal == "false") { + return false; + } else if (literal == "inf") { + return INFINITY; + } else if (literal == "nan") { + return NAN; + } + throw error("invalid literal "); + } + if (next == '{') { + return parseObject(); + } + if (next == '[') { + return parseList(); + } + if (next == '"' || next == '\'') { + pos++; + return parseString(next); + } + throw error("unexpected character '" + std::string({next}) + "'"); +} + +dv::value json::parseDV( + std::string_view filename, std::string_view source +) { + ParserDV parser(filename, source); + return parser.parse(); +} + +dv::value json::parseDV(std::string_view source) { + return parseDV("", source); +} diff --git a/src/coders/json.hpp b/src/coders/json.hpp index 45d1866f..a9ce5b1e 100644 --- a/src/coders/json.hpp +++ b/src/coders/json.hpp @@ -11,6 +11,9 @@ namespace json { dynamic::Map_sptr parse(std::string_view filename, std::string_view source); dynamic::Map_sptr parse(std::string_view source); + dv::value parseDV(std::string_view filename, std::string_view source); + dv::value parseDV(std::string_view source); + std::string stringify( const dynamic::Map* obj, bool nice, const std::string& indent ); diff --git a/test/coders/json.cpp b/test/coders/json.cpp index c8c75c00..7d2f0dbe 100644 --- a/test/coders/json.cpp +++ b/test/coders/json.cpp @@ -48,22 +48,22 @@ TEST(JSON, EncodeDecodeDV) { srcBytes[i] = rand(); } - std::string text; + std::string text; { - auto map = dv::object(); - map["name"] = name; - map["year"] = year; - map["score"] = score; - map["data"] = srcBytes; + auto object = dv::object(); + object["name"] = name; + object["year"] = year; + object["score"] = score; + object["data"] = srcBytes; - text = json::stringifyDV(map, false, ""); + text = json::stringifyDV(object, false, ""); } { - auto map = json::parse(text); - EXPECT_EQ(map->get("name"), name); - EXPECT_EQ(map->get("year"), year); - EXPECT_FLOAT_EQ(map->get("score"), score); - auto b64string = map->get("data"); + auto object = json::parseDV(text); + EXPECT_EQ(object["name"].asString(), name); + EXPECT_EQ(object["year"].asInteger(), year); + EXPECT_FLOAT_EQ(object["score"].asNumber(), score); + auto b64string = object["data"].asString(); auto bytes = util::base64_decode(b64string); EXPECT_EQ(bytes.size(), bytesSize);