From b9229b74007a63b1696dca28c3dc58193c946127 Mon Sep 17 00:00:00 2001 From: Christopher Dunn Date: Mon, 23 Feb 2015 16:35:32 -0600 Subject: [PATCH 1/2] failing test for allowSingleQuotes --- src/test_lib_json/main.cpp | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp index f2b1c56..244c82d 100644 --- a/src/test_lib_json/main.cpp +++ b/src/test_lib_json/main.cpp @@ -1861,7 +1861,6 @@ JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterBool) { JSONTEST_ASSERT_EQUAL(true, root.asBool()); delete reader; } - struct CharReaderAllowDropNullTest : JsonTest::TestCase {}; JSONTEST_FIXTURE(CharReaderAllowDropNullTest, issue178) { @@ -2014,6 +2013,38 @@ JSONTEST_FIXTURE(CharReaderAllowDropNullTest, issue178) { delete reader; } +struct CharReaderAllowSingleQuotesTest : JsonTest::TestCase {}; + +JSONTEST_FIXTURE(CharReaderAllowSingleQuotesTest, issue182) { + Json::CharReaderBuilder b; + b.settings_["allowSingleQuotes"] = true; + Json::Value root; + std::string errs; + Json::CharReader* reader(b.newCharReader()); + { + char const doc[] = "{'a':true,\"b\":true}"; + bool ok = reader->parse( + doc, doc + std::strlen(doc), + &root, &errs); + JSONTEST_ASSERT(ok); + JSONTEST_ASSERT_STRING_EQUAL("", errs); + JSONTEST_ASSERT_EQUAL(2u, root.size()); + JSONTEST_ASSERT_EQUAL(true, root.get("a", false)); + JSONTEST_ASSERT_EQUAL(true, root.get("b", false)); + } + { + char const doc[] = "{'a': 'x', \"b\":'y'}"; + bool ok = reader->parse( + doc, doc + std::strlen(doc), + &root, &errs); + JSONTEST_ASSERT(ok); + JSONTEST_ASSERT_STRING_EQUAL("", errs); + JSONTEST_ASSERT_EQUAL(2u, root.size()); + JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString()); + JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString()); + } +} + struct IteratorTest : JsonTest::TestCase {}; JSONTEST_FIXTURE(IteratorTest, distance) { @@ -2079,6 +2110,8 @@ int main(int argc, const char* argv[]) { JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowDropNullTest, issue178); + JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowSingleQuotesTest, issue182); + JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, distance); return runner.runCommandLine(argc, argv); From 0c66e698fb5bf0e595d0bb914c5e0498d93043ca Mon Sep 17 00:00:00 2001 From: Christopher Dunn Date: Mon, 23 Feb 2015 15:55:12 -0600 Subject: [PATCH 2/2] allowSingleQuotes issue #182 --- include/json/reader.h | 2 ++ src/lib_json/json_reader.cpp | 44 +++++++++++++++++++++++++----------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/include/json/reader.h b/include/json/reader.h index b59e183..154acbd 100644 --- a/include/json/reader.h +++ b/include/json/reader.h @@ -310,6 +310,8 @@ public: - true if dropped null placeholders are allowed. (See StreamWriterBuilder.) - `"allowNumericKeys": false or true` - true if numeric object keys are allowed. + - `"allowSingleQuotes": false or true` + - true if '' are allowed for strings (both keys and values) - `"stackLimit": integer` - Exceeding stackLimit (recursive depth of `readValue()`) will cause an exception. diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index 8bbaeab..372b832 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -909,12 +909,12 @@ bool Reader::good() const { class OurFeatures { public: static OurFeatures all(); - static OurFeatures strictMode(); OurFeatures(); bool allowComments_; bool strictRoot_; bool allowDroppedNullPlaceholders_; bool allowNumericKeys_; + bool allowSingleQuotes_; bool failIfExtra_; int stackLimit_; }; // OurFeatures @@ -923,20 +923,15 @@ public: // //////////////////////////////// OurFeatures::OurFeatures() - : allowComments_(true), strictRoot_(false), - allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} + : allowComments_(true), strictRoot_(false) + , allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) + , allowSingleQuotes_(false) + , failIfExtra_(false) +{ +} OurFeatures OurFeatures::all() { return OurFeatures(); } -OurFeatures OurFeatures::strictMode() { - OurFeatures features; - features.allowComments_ = false; - features.strictRoot_ = true; - features.allowDroppedNullPlaceholders_ = false; - features.allowNumericKeys_ = false; - return features; -} - // Implementation of class Reader // //////////////////////////////// @@ -1006,6 +1001,7 @@ private: bool readCStyleComment(); bool readCppStyleComment(); bool readString(); + bool readStringSingleQuote(); void readNumber(); bool readValue(); bool readObject(Token& token); @@ -1220,6 +1216,12 @@ bool OurReader::readToken(Token& token) { token.type_ = tokenString; ok = readString(); break; + case '\'': + if (features_.allowSingleQuotes_) { + token.type_ = tokenString; + ok = readStringSingleQuote(); + break; + } // else continue case '/': token.type_ = tokenComment; ok = readComment(); @@ -1371,7 +1373,6 @@ void OurReader::readNumber() { c = (current_ = p) < end_ ? *p++ : 0; } } - bool OurReader::readString() { Char c = 0; while (current_ != end_) { @@ -1384,6 +1385,19 @@ bool OurReader::readString() { return c == '"'; } + +bool OurReader::readStringSingleQuote() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '\'') + break; + } + return c == '\''; +} + bool OurReader::readObject(Token& tokenStart) { Token tokenName; std::string name; @@ -1878,6 +1892,7 @@ CharReader* CharReaderBuilder::newCharReader() const features.strictRoot_ = settings_["strictRoot"].asBool(); features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool(); features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); + features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); features.stackLimit_ = settings_["stackLimit"].asInt(); features.failIfExtra_ = settings_["failIfExtra"].asBool(); return new OurCharReader(collectComments, features); @@ -1890,6 +1905,7 @@ static void getValidReaderKeys(std::set* valid_keys) valid_keys->insert("strictRoot"); valid_keys->insert("allowDroppedNullPlaceholders"); valid_keys->insert("allowNumericKeys"); + valid_keys->insert("allowSingleQuotes"); valid_keys->insert("stackLimit"); valid_keys->insert("failIfExtra"); } @@ -1919,6 +1935,7 @@ void CharReaderBuilder::strictMode(Json::Value* settings) (*settings)["strictRoot"] = true; (*settings)["allowDroppedNullPlaceholders"] = false; (*settings)["allowNumericKeys"] = false; + (*settings)["allowSingleQuotes"] = false; (*settings)["failIfExtra"] = true; //! [CharReaderBuilderStrictMode] } @@ -1931,6 +1948,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) (*settings)["strictRoot"] = false; (*settings)["allowDroppedNullPlaceholders"] = false; (*settings)["allowNumericKeys"] = false; + (*settings)["allowSingleQuotes"] = false; (*settings)["stackLimit"] = 1000; (*settings)["failIfExtra"] = false; //! [CharReaderBuilderDefaults]