Merge pull request #21 from Teemperor/fixed_escaped_chars
Implemented the JSON spec for string parsing for everything but the \uXXXX escaping - see issue #12.
This commit is contained in:
commit
69195e070f
2 changed files with 75 additions and 15 deletions
52
src/json.cc
52
src/json.cc
|
@ -2042,32 +2042,58 @@ Parses a string after opening quotes (\p ") where read.
|
|||
*/
|
||||
std::string json::parser::parseString()
|
||||
{
|
||||
// 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;
|
||||
|
||||
// the result of the parse process
|
||||
std::string result;
|
||||
|
||||
// iterate with pos_ over the whole string
|
||||
for (; pos_ < buffer_.size(); pos_++)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// uneven amount of backslashes means the user wants to escape something
|
||||
if (!evenAmountOfBackslashes) {
|
||||
|
||||
// slash, backslash and quote are copied as is
|
||||
if ( currentChar == '/'
|
||||
|| currentChar == '\\'
|
||||
|| currentChar == '"') {
|
||||
result += currentChar;
|
||||
} else {
|
||||
// All other characters are replaced by their respective special character
|
||||
if (currentChar == 't') {
|
||||
result += '\t';
|
||||
} else if (currentChar == 'b') {
|
||||
result += '\b';
|
||||
} else if (currentChar == 'f') {
|
||||
result += '\f';
|
||||
} else if (currentChar == 'n') {
|
||||
result += '\n';
|
||||
} else if (currentChar == 'r') {
|
||||
result += '\r';
|
||||
} else {
|
||||
error("expected one of \\,/,b,f,n,r,t behind backslash.");
|
||||
}
|
||||
// TODO implement \uXXXX
|
||||
}
|
||||
} else {
|
||||
if (currentChar == '"') {
|
||||
// currentChar is a quote, so we found the end of the string
|
||||
|
||||
|
||||
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);
|
||||
// bring the result of the parsing process back to the caller
|
||||
return result;
|
||||
} else if (currentChar != '\\') {
|
||||
// all non-backslash characters are added to the end of the result string.
|
||||
// the only backslashes we want in the result are the ones that are escaped (which happens above).
|
||||
result += currentChar;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1618,10 +1618,44 @@ TEST_CASE("Parser")
|
|||
CHECK(json::parse("\"\"") == json(""));
|
||||
CHECK(json::parse("\"foo\"") == json("foo"));
|
||||
|
||||
// escape characters
|
||||
// escaping quotes
|
||||
CHECK_THROWS_AS(json::parse("\"\\\""), std::invalid_argument);
|
||||
CHECK_NOTHROW(json::parse("\"\\\"\""));
|
||||
CHECK_NOTHROW(json::parse("\"\\\\\""));
|
||||
|
||||
// escaping backslashes
|
||||
CHECK(json::parse("\"a\\\\z\"") == json("a\\z"));
|
||||
CHECK(json::parse("\"\\\\\"") == json("\\"));
|
||||
CHECK(json::parse("\"\\\\a\\\\\"") == json("\\a\\"));
|
||||
CHECK(json::parse("\"\\\\\\\\\"") == json("\\\\"));
|
||||
|
||||
// escaping slash
|
||||
CHECK(json::parse("\"a\\/z\"") == json("a/z"));
|
||||
CHECK(json::parse("\"\\/\"") == json("/"));
|
||||
|
||||
// escaping tabs
|
||||
CHECK(json::parse("\"a\\tz\"") == json("a\tz"));
|
||||
CHECK(json::parse("\"\\t\"") == json("\t"));
|
||||
|
||||
// escaping formfeed
|
||||
CHECK(json::parse("\"a\\fz\"") == json("a\fz"));
|
||||
CHECK(json::parse("\"\\f\"") == json("\f"));
|
||||
|
||||
// escaping carriage return
|
||||
CHECK(json::parse("\"a\\rz\"") == json("a\rz"));
|
||||
CHECK(json::parse("\"\\r\"") == json("\r"));
|
||||
|
||||
// escaping backspace
|
||||
CHECK(json::parse("\"a\\bz\"") == json("a\bz"));
|
||||
CHECK(json::parse("\"\\b\"") == json("\b"));
|
||||
|
||||
// escaping newline
|
||||
CHECK(json::parse("\"a\\nz\"") == json("a\nz"));
|
||||
CHECK(json::parse("\"\\n\"") == json("\n"));
|
||||
|
||||
// escaping senseless stuff
|
||||
CHECK_THROWS_AS(json::parse("\"\\z\""), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parse("\"\\ \""), std::invalid_argument);
|
||||
CHECK_THROWS_AS(json::parse("\"\\9\""), std::invalid_argument);
|
||||
|
||||
// quotes must be closed
|
||||
CHECK_THROWS_AS(json::parse("\""), std::invalid_argument);
|
||||
|
|
Loading…
Reference in a new issue