diff --git a/json11.cpp b/json11.cpp index 07a3a71..5f3b7ef 100644 --- a/json11.cpp +++ b/json11.cpp @@ -735,15 +735,18 @@ Json Json::parse(const string &in, string &err, JsonParse strategy) { // Documented in json11.hpp vector Json::parse_multi(const string &in, + std::string::size_type &parser_stop_pos, string &err, JsonParse strategy) { JsonParser parser { in, 0, err, false, strategy }; - + parser_stop_pos = 0; vector json_vec; while (parser.i != in.size() && !parser.failed) { json_vec.push_back(parser.parse_json(0)); // Check for another object parser.consume_garbage(); + if (!parser.failed) + parser_stop_pos = parser.i; } return json_vec; } diff --git a/json11.hpp b/json11.hpp index a99e241..e9fe251 100644 --- a/json11.hpp +++ b/json11.hpp @@ -165,9 +165,18 @@ public: // Parse multiple objects, concatenated or separated by whitespace static std::vector parse_multi( const std::string & in, + std::string::size_type & parser_stop_pos, std::string & err, JsonParse strategy = JsonParse::STANDARD); + static inline std::vector parse_multi( + const std::string & in, + std::string & err, + JsonParse strategy = JsonParse::STANDARD) { + std::string::size_type parser_stop_pos; + return parse_multi(in, parser_stop_pos, err, strategy); + } + bool operator== (const Json &rhs) const; bool operator< (const Json &rhs) const; bool operator!= (const Json &rhs) const { return !(*this == rhs); } diff --git a/test.cpp b/test.cpp index bd60705..b1b52fd 100644 --- a/test.cpp +++ b/test.cpp @@ -1,13 +1,17 @@ +#ifdef NDEBUG +#undef NDEBUG//at now assert will work even in Release build +#endif +#include #include #include #include #include #include #include "json11.hpp" -#include #include #include #include +#include using namespace json11; using std::string; @@ -183,6 +187,36 @@ int main(int argc, char **argv) { assert(nested_array.array_items()[0].is_array()); assert(nested_array.array_items()[0].array_items().size() == 3); + { + const std::string good_json = R"( {"k1" : "v1"})"; + const std::string bad_json1 = good_json + " {"; + const std::string bad_json2 = good_json + R"({"k2":"v2", "k3":[)"; + struct TestMultiParse { + std::string input; + std::string::size_type expect_parser_stop_pos; + size_t expect_not_empty_elms_count; + Json expect_parse_res; + } tests[] = { + {" {", 0, 0, {}}, + {good_json, good_json.size(), 1, Json(std::map{ { "k1", "v1" } })}, + {bad_json1, good_json.size() + 1, 1, Json(std::map{ { "k1", "v1" } })}, + {bad_json2, good_json.size(), 1, Json(std::map{ { "k1", "v1" } })}, + {"{}", 2, 1, Json::object{}}, + }; + for (const auto &tst : tests) { + std::string::size_type parser_stop_pos; + std::string err; + auto res = Json::parse_multi(tst.input, parser_stop_pos, err); + assert(parser_stop_pos == tst.expect_parser_stop_pos); + assert( + std::count_if(res.begin(), res.end(), + [](const Json& j) { return !j.is_null(); }) + == tst.expect_not_empty_elms_count); + if (!res.empty()) { + assert(tst.expect_parse_res == res[0]); + } + } + } Json my_json = Json::object { { "key1", "value1" }, { "key2", false },