From c40c33467875a50f11e939d53e5d1c51dec41f1c Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Tue, 6 Apr 2021 16:11:35 -0400 Subject: [PATCH] CharReader: Add StructuredError --- include/json/reader.h | 13 +++++++++++++ src/lib_json/json_reader.cpp | 18 +++++++++--------- src/test_lib_json/main.cpp | 37 ++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/include/json/reader.h b/include/json/reader.h index 917546608..847cd3777 100644 --- a/include/json/reader.h +++ b/include/json/reader.h @@ -244,6 +244,13 @@ class JSONCPP_DEPRECATED( */ class JSON_API CharReader { public: + class JSON_API StructuredError { + public: + ptrdiff_t offset_start; + ptrdiff_t offset_limit; + String message; + }; + virtual ~CharReader() = default; /** \brief Read a Value from a JSON * document. The document must be a UTF-8 encoded string containing the @@ -264,6 +271,12 @@ class JSON_API CharReader { virtual bool parse(char const* beginDoc, char const* endDoc, Value* root, String* errs) = 0; + /** \brief Get a list of structured error messages from parsing the document. + * + * \return list of error messages. + */ + virtual std::vector getStructuredErrors() const = 0; + class JSON_API Factory { public: virtual ~Factory() = default; diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index a34017d99..63fc11603 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -884,17 +884,12 @@ class OurReader { public: using Char = char; using Location = const Char*; - struct StructuredError { - ptrdiff_t offset_start; - ptrdiff_t offset_limit; - String message; - }; explicit OurReader(OurFeatures const& features); bool parse(const char* beginDoc, const char* endDoc, Value& root, bool collectComments = true); String getFormattedErrorMessages() const; - std::vector getStructuredErrors() const; + std::vector getStructuredErrors() const; private: OurReader(OurReader const&); // no impl @@ -1849,10 +1844,11 @@ String OurReader::getFormattedErrorMessages() const { return formattedMessage; } -std::vector OurReader::getStructuredErrors() const { - std::vector allErrors; +std::vector +OurReader::getStructuredErrors() const { + std::vector allErrors; for (const auto& error : errors_) { - OurReader::StructuredError structured; + CharReader::StructuredError structured; structured.offset_start = error.token_.start_ - begin_; structured.offset_limit = error.token_.end_ - begin_; structured.message = error.message_; @@ -1876,6 +1872,10 @@ class OurCharReader : public CharReader { } return ok; } + + std::vector getStructuredErrors() const override { + return reader_.getStructuredErrors(); + } }; CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); } diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp index d0f5364ac..d75cddf5c 100644 --- a/src/test_lib_json/main.cpp +++ b/src/test_lib_json/main.cpp @@ -3903,6 +3903,43 @@ JSONTEST_FIXTURE_LOCAL(FuzzTest, fuzzDoesntCrash) { example.size())); } +struct ParseWithStructuredErrorsTest : JsonTest::TestCase { + void + testErrors(const std::string& doc, bool success, + const std::vector& errors) { + Json::CharReaderBuilder b; + CharReaderPtr reader(b.newCharReader()); + Json::Value root; + JSONTEST_ASSERT_EQUAL( + success, + reader->parse(doc.data(), doc.data() + doc.length(), &root, nullptr)); + auto actualErrors = reader->getStructuredErrors(); + JSONTEST_ASSERT_EQUAL(errors.size(), actualErrors.size()); + for (std::size_t i = 0; i < errors.size() && i < actualErrors.size(); i++) { + JSONTEST_ASSERT_EQUAL(errors[i].offset_start, + actualErrors[i].offset_start); + JSONTEST_ASSERT_EQUAL(errors[i].offset_limit, + actualErrors[i].offset_limit); + JSONTEST_ASSERT_STRING_EQUAL(errors[i].message, actualErrors[i].message); + } + } +}; + +JSONTEST_FIXTURE_LOCAL(ParseWithStructuredErrorsTest, success) { + testErrors("{}", true, {}); +} + +JSONTEST_FIXTURE_LOCAL(ParseWithStructuredErrorsTest, singleError) { + testErrors("{ 1 : 2 }", false, + { + { + /*offset_start=*/2, + /*offset_limit=*/3, + /*message=*/"Missing '}' or object member name", + }, + }); +} + int main(int argc, const char* argv[]) { JsonTest::Runner runner;