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()
|
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
|
// true if and only if the amount of backslashes before the current
|
||||||
// character is even
|
// character is even
|
||||||
bool evenAmountOfBackslashes = true;
|
bool evenAmountOfBackslashes = true;
|
||||||
|
|
||||||
|
// the result of the parse process
|
||||||
|
std::string result;
|
||||||
|
|
||||||
// iterate with pos_ over the whole string
|
// iterate with pos_ over the whole string
|
||||||
for (; pos_ < buffer_.size(); pos_++)
|
for (; pos_ < buffer_.size(); pos_++) {
|
||||||
{
|
|
||||||
char currentChar = buffer_[pos_];
|
char currentChar = buffer_[pos_];
|
||||||
|
|
||||||
// currentChar is a quote, so we might have found the end of the string
|
// uneven amount of backslashes means the user wants to escape something
|
||||||
if (currentChar == '"')
|
if (!evenAmountOfBackslashes) {
|
||||||
{
|
|
||||||
// but only if the amount of backslashes before that quote is even
|
// slash, backslash and quote are copied as is
|
||||||
if (evenAmountOfBackslashes)
|
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
|
// set pos_ behind the trailing quote
|
||||||
pos_++;
|
pos_++;
|
||||||
// find next char to parse
|
// find next char to parse
|
||||||
next();
|
next();
|
||||||
|
|
||||||
// return string inside the quotes
|
// bring the result of the parsing process back to the caller
|
||||||
return buffer_.substr(startPos, stringLength);
|
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("\"\"") == json(""));
|
||||||
CHECK(json::parse("\"foo\"") == json("foo"));
|
CHECK(json::parse("\"foo\"") == json("foo"));
|
||||||
|
|
||||||
// escape characters
|
// escaping quotes
|
||||||
CHECK_THROWS_AS(json::parse("\"\\\""), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse("\"\\\""), std::invalid_argument);
|
||||||
CHECK_NOTHROW(json::parse("\"\\\"\""));
|
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
|
// quotes must be closed
|
||||||
CHECK_THROWS_AS(json::parse("\""), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse("\""), std::invalid_argument);
|
||||||
|
|
Loading…
Reference in a new issue