Skip to content

Allow single quote #183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 25, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/json/reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,8 @@ class JSON_API CharReaderBuilder : public CharReader::Factory {
- 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.
Expand Down
44 changes: 31 additions & 13 deletions src/lib_json/json_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -923,20 +923,15 @@ class OurFeatures {
// ////////////////////////////////

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
// ////////////////////////////////

Expand Down Expand Up @@ -1006,6 +1001,7 @@ class OurReader {
bool readCStyleComment();
bool readCppStyleComment();
bool readString();
bool readStringSingleQuote();
void readNumber();
bool readValue();
bool readObject(Token& token);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -1371,7 +1373,6 @@ void OurReader::readNumber() {
c = (current_ = p) < end_ ? *p++ : 0;
}
}

bool OurReader::readString() {
Char c = 0;
while (current_ != end_) {
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -1890,6 +1905,7 @@ static void getValidReaderKeys(std::set<std::string>* 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");
}
Expand Down Expand Up @@ -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]
}
Expand All @@ -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]
Expand Down
35 changes: 34 additions & 1 deletion src/test_lib_json/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1861,7 +1861,6 @@ JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterBool) {
JSONTEST_ASSERT_EQUAL(true, root.asBool());
delete reader;
}

struct CharReaderAllowDropNullTest : JsonTest::TestCase {};

JSONTEST_FIXTURE(CharReaderAllowDropNullTest, issue178) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down