Unverified Commit 65ecf353 authored by Noir's avatar Noir Committed by GitHub

Merge pull request #1332

Fix bookkeeping of the field name
parents d8c9e70b 16244d21
......@@ -203,13 +203,14 @@ public:
bool value(span<std::byte> x) override;
/// @private
std::string current_field_name();
private:
[[nodiscard]] position pos() const noexcept;
void append_current_field_name(std::string& str);
std::string current_field_name();
std::string mandatory_field_missing_str(std::string_view name);
template <bool PopOrAdvanceOnSuccess, class F>
......
......@@ -166,6 +166,7 @@ void json_reader::revert() {
err_.reset();
st_->clear();
st_->emplace_back(root_);
field_.clear();
}
}
......@@ -173,6 +174,7 @@ void json_reader::reset() {
buf_.reclaim();
st_ = nullptr;
err_.reset();
field_.clear();
}
// -- interface functions ------------------------------------------------------
......@@ -260,8 +262,8 @@ bool json_reader::end_object() {
bool json_reader::begin_field(std::string_view name) {
SCOPE(position::object);
field_.push_back(name);
if (auto member = find_member(top<position::object>(), name)) {
field_.push_back(name);
push(member->val);
return true;
} else {
......@@ -273,10 +275,10 @@ bool json_reader::begin_field(std::string_view name) {
bool json_reader::begin_field(std::string_view name, bool& is_present) {
SCOPE(position::object);
field_.push_back(name);
if (auto member = find_member(top<position::object>(), name);
member != nullptr
&& member->val->data.index() != detail::json::value::null_index) {
field_.push_back(name);
push(member->val);
is_present = true;
} else {
......@@ -304,6 +306,7 @@ bool json_reader::begin_field(std::string_view name,
bool json_reader::begin_field(std::string_view name, bool& is_present,
span<const type_id_t> types, size_t& index) {
SCOPE(position::object);
field_.push_back(name);
if (auto member = find_member(top<position::object>(), name);
member != nullptr
&& member->val->data.index() != detail::json::value::null_index) {
......@@ -312,7 +315,6 @@ bool json_reader::begin_field(std::string_view name, bool& is_present,
if (auto i = std::find(types.begin(), types.end(), id);
i != types.end()) {
index = static_cast<size_t>(std::distance(types.begin(), i));
field_.push_back(name);
push(member->val);
is_present = true;
return true;
......@@ -327,7 +329,8 @@ bool json_reader::end_field() {
SCOPE(position::object);
// Note: no pop() here, because the value(s) were already consumed. Only
// update the field_ for debugging.
field_.pop_back();
if (!field_.empty())
field_.pop_back();
return true;
}
......@@ -631,10 +634,15 @@ json_reader::position json_reader::pos() const noexcept {
}
void json_reader::append_current_field_name(std::string& result) {
result += "ROOT";
for (auto& key : field_) {
result += '.';
result.insert(result.end(), key.begin(), key.end());
if (field_.empty()) {
result += "null";
} else {
auto i = field_.begin();
result += *i++;
while (i != field_.end()) {
result += '.';
result += *i++;
}
}
}
......
......@@ -124,4 +124,64 @@ CAF_TEST(json baselines) {
}
}
constexpr std::string_view foo_json = R"_({
"@first-type": "int32_t",
"first": 42,
"top": {
"mid": {
"bottom": null
}
}
})_";
SCENARIO("the json reader keeps track of the current field") {
GIVEN("a sequence of member functions calls for type inspection") {
WHEN("encountering new fields") {
THEN("the json reader updates the current field name") {
auto dummy = int32_t{0};
auto first_present = false;
auto types_vec = std::vector{type_id_v<int32_t>, type_id_v<double>};
auto types = make_span(types_vec);
auto first_index = size_t{0};
auto top_present = false;
auto bottom_present = false;
auto bottom_index = size_t{0};
json_reader uut;
CHECK(uut.load(foo_json));
CHECK_EQ(uut.current_field_name(), "null");
// clang-format off
uut.begin_object(invalid_type_id, "foo");
// begin_field overload #4
uut.begin_field("first", first_present, types, first_index);
CHECK_EQ(first_present, true);
CHECK_EQ(first_index, 0u);
CHECK_EQ(uut.current_field_name(), "first");
uut.value(dummy);
CHECK_EQ(dummy, 42);
uut.end_field();
// begin_field overload #2
uut.begin_field("top", top_present);
CHECK_EQ(top_present, true);
CHECK_EQ(uut.current_field_name(), "top");
uut.begin_object(invalid_type_id, "top");
// begin_field overload #1
uut.begin_field("mid");
CHECK_EQ(uut.current_field_name(), "top.mid");
uut.begin_object(invalid_type_id, "bottom");
// begin_field overload #3
uut.begin_field("bottom", bottom_present, types, bottom_index);
CHECK_EQ(bottom_present, false);
CHECK_EQ(uut.current_field_name(), "top.mid.bottom");
uut.end_field();
uut.end_object();
uut.end_field();
uut.end_object();
uut.end_field();
uut.end_object();
// clang-format on
}
}
}
}
END_FIXTURE_SCOPE()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment