Skip to content
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

Fixed escaped quotes #18

Merged
merged 2 commits into from
Jan 9, 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
62 changes: 37 additions & 25 deletions src/json.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2042,34 +2042,46 @@ Parses a string after opening quotes (\p ") where read.
*/
std::string json::parser::parseString()
{
// get position of closing quotes
auto quotepos_ = buffer_.find_first_of("\"", pos_);

// if the closing quotes are escaped (character before the quotes is a
// backslash), we continue looking for the final quotes
while (quotepos_ != std::string::npos and buffer_[quotepos_ - 1] == '\\')
{
quotepos_ = buffer_.find_first_of("\"", quotepos_ + 1);
}
// remember the position where the first character of the string was
const auto startPos = pos_;
// true if and only if the amount of backslashes before the current
// character is even
bool evenAmountOfBackslashes = true;

// iterate with pos_ over the whole string
for (;pos_ < buffer_.size(); pos_++) {
char currentChar = buffer_[pos_];

// currentChar is a quote, so we might have found the end of the string
if (currentChar == '"') {
// but only if the amount of backslashes before that quote is even
if (evenAmountOfBackslashes) {

const auto stringLength = pos_ - startPos;
// set pos_ behind the trailing quote
pos_++;
// find next char to parse
next();

// return string inside the quotes
return buffer_.substr(startPos, stringLength);
}
}

// check if closing quotes were found
if (quotepos_ == std::string::npos)
{
error("expected '\"'");
// remember if we have an even amount of backslashes before the current character
if (currentChar == '\\') {
// jump between even/uneven for each backslash we encounter
evenAmountOfBackslashes = !evenAmountOfBackslashes;
} else {
// zero backslashes are also an even number, so as soon as we encounter a non-backslash
// the chain of backslashes breaks and we start again from zero
evenAmountOfBackslashes = true;
}
}

// store the coordinates of the string for the later return value
const auto stringBegin = pos_;
const auto stringLength = quotepos_ - pos_;

// set buffer position to the position behind (+1) the closing quote
pos_ = quotepos_ + 1;

// read next character
next();

// return the string value
return buffer_.substr(stringBegin, stringLength);
// we iterated over the whole string without finding a unescaped quote
// so the given string is malformed
error("expected '\"'");
}

/*!
Expand Down
1 change: 1 addition & 0 deletions test/json_unit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1621,6 +1621,7 @@ TEST_CASE("Parser")
// escape characters
CHECK_THROWS_AS(json::parse("\"\\\""), std::invalid_argument);
CHECK_NOTHROW(json::parse("\"\\\"\""));
CHECK_NOTHROW(json::parse("\"\\\\\""));

// quotes must be closed
CHECK_THROWS_AS(json::parse("\""), std::invalid_argument);
Expand Down