Skip to content

Commit

Permalink
json: Support parsing arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
robinlinden committed Jan 14, 2025
1 parent f848bf0 commit 38639e2
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 0 deletions.
41 changes: 41 additions & 0 deletions json/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <string_view>
#include <system_error>
#include <tuple>
#include <utility>
#include <variant>
#include <vector>

Expand Down Expand Up @@ -105,6 +106,7 @@ class Parser {
return v;
}

// NOLINTNEXTLINE(misc-no-recursion)
constexpr std::optional<Value> parse_value() {
skip_whitespace();
auto c = peek();
Expand All @@ -121,11 +123,50 @@ class Parser {
return parse_false();
case 'n':
return parse_null();
case '[':
return parse_array();
default:
return std::nullopt;
}
}

// NOLINTNEXTLINE(misc-no-recursion)
constexpr std::optional<Value> parse_array() {
std::ignore = consume(); // '['
if (peek() == ']') {
std::ignore = consume();
return Array{};
}

Array array;
while (true) {
auto v = parse_value();
if (!v) {
return std::nullopt;
}

array.values.push_back(*std::move(v));
skip_whitespace();

auto c = peek();
if (!c) {
return std::nullopt;
}

if (*c == ',') {
std::ignore = consume();
continue;
}

if (*c == ']') {
std::ignore = consume();
return array;
}

return std::nullopt;
}
}

constexpr std::optional<Value> parse_true() {
std::ignore = consume(); // 't'
auto r = consume();
Expand Down
15 changes: 15 additions & 0 deletions json/json_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <optional>

int main() {
using json::Value;
etest::Suite s{};

s.add_test("bad input", [](etest::IActions &a) {
Expand Down Expand Up @@ -70,5 +71,19 @@ int main() {
a.expect_eq(json::parse("null!"), std::nullopt);
});

s.add_test("array", [](etest::IActions &a) {
a.expect_eq(json::parse("[]"), Value{json::Array{}});
a.expect_eq(json::parse(R"(["1"])"), Value{json::Array{{Value{"1"}}}});
a.expect_eq(json::parse(R"([null, true, "hello", false, []])"),
Value{json::Array{
{Value{json::Null{}}, Value{true}, Value{"hello"}, Value{false}, Value{json::Array{}}},
}});

a.expect_eq(json::parse("["), std::nullopt);
a.expect_eq(json::parse("[blah"), std::nullopt);
a.expect_eq(json::parse("[null"), std::nullopt);
a.expect_eq(json::parse("[null,"), std::nullopt);
});

return s.run();
}

0 comments on commit 38639e2

Please sign in to comment.