From fc58a73523cd67d721ce79b66dd3466b20369538 Mon Sep 17 00:00:00 2001
From: Niels <niels.lohmann@gmail.com>
Date: Fri, 24 Apr 2015 22:06:57 +0200
Subject: [PATCH] fix #60 (double escaping)

---
 .gitignore        |  2 ++
 src/json.hpp      | 12 +++++-------
 src/json.hpp.re2c | 12 +++++-------
 test/unit.cpp     | 23 ++++++++++++++++++-----
 4 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/.gitignore b/.gitignore
index a434324f..bfba1a89 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
 json_unit
 html
+
+benchmark
diff --git a/src/json.hpp b/src/json.hpp
index 89fd9a41..04bd1acd 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -2251,7 +2251,7 @@ class basic_json
                     {
                         // control characters (everything between 0x00 and 0x1f)
                         // -> create four-digit hex representation
-                        std::stringstream ss;
+                        std::basic_stringstream<typename string_t::value_type> ss;
                         ss << "\\u" << std::hex << std::setw(4) << std::setfill('0') << int(c);
                         result += ss.str();
                     }
@@ -2391,7 +2391,7 @@ class basic_json
                 // 15 digits of precision allows round-trip IEEE 754
                 // string->double->string
                 const auto sz = static_cast<unsigned int>(std::snprintf(nullptr, 0, "%.15g", m_value.number_float));
-                std::vector<char> buf(sz + 1);
+                std::vector<typename string_t::value_type> buf(sz + 1);
                 std::snprintf(&buf[0], buf.size(), "%.15g", m_value.number_float);
                 return string_t(buf.data());
             }
@@ -4577,21 +4577,19 @@ basic_json_parser_59:
                             result += "\r";
                             break;
                         }
-
-                        // characters that are not "un"escsaped
                         case '\\':
                         {
-                            result += "\\\\";
+                            result += "\\";
                             break;
                         }
                         case '/':
                         {
-                            result += "\\/";
+                            result += "/";
                             break;
                         }
                         case '"':
                         {
-                            result += "\\\"";
+                            result += "\"";
                             break;
                         }
 
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index d2414298..48682339 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -2251,7 +2251,7 @@ class basic_json
                     {
                         // control characters (everything between 0x00 and 0x1f)
                         // -> create four-digit hex representation
-                        std::stringstream ss;
+                        std::basic_stringstream<typename string_t::value_type> ss;
                         ss << "\\u" << std::hex << std::setw(4) << std::setfill('0') << int(c);
                         result += ss.str();
                     }
@@ -2391,7 +2391,7 @@ class basic_json
                 // 15 digits of precision allows round-trip IEEE 754
                 // string->double->string
                 const auto sz = static_cast<unsigned int>(std::snprintf(nullptr, 0, "%.15g", m_value.number_float));
-                std::vector<char> buf(sz + 1);
+                std::vector<typename string_t::value_type> buf(sz + 1);
                 std::snprintf(&buf[0], buf.size(), "%.15g", m_value.number_float);
                 return string_t(buf.data());
             }
@@ -3883,21 +3883,19 @@ class basic_json
                             result += "\r";
                             break;
                         }
-
-                        // characters that are not "un"escsaped
                         case '\\':
                         {
-                            result += "\\\\";
+                            result += "\\";
                             break;
                         }
                         case '/':
                         {
-                            result += "\\/";
+                            result += "/";
                             break;
                         }
                         case '"':
                         {
-                            result += "\\\"";
+                            result += "\"";
                             break;
                         }
 
diff --git a/test/unit.cpp b/test/unit.cpp
index 92360fb5..f3fe37d4 100644
--- a/test/unit.cpp
+++ b/test/unit.cpp
@@ -7328,12 +7328,12 @@ TEST_CASE("parser class")
 
             SECTION("escaped")
             {
-                // quotation mark
-                CHECK(json::parser("\"\\\"\"").parse() == json("\\\""));
-                // reverse solidus
-                CHECK(json::parser("\"\\\\\"").parse() == json("\\\\"));
+                // quotation mark "\""
+                CHECK(json::parser("\"\\\"\"").parse() == R"("\"")"_json);
+                // reverse solidus "\\"
+                CHECK(json::parser("\"\\\\\"").parse() == R"("\\")"_json);
                 // solidus
-                CHECK(json::parser("\"\\/\"").parse() == json("\\/"));
+                CHECK(json::parser("\"\\/\"").parse() == R"("/")"_json);
                 // backspace
                 CHECK(json::parser("\"\\b\"").parse() == json("\b"));
                 // formfeed
@@ -8267,3 +8267,16 @@ TEST_CASE("concepts")
         }
     }
 }
+
+TEST_CASE("regression tests")
+{
+    SECTION("issue #60 - Double quotation mark is not parsed correctly")
+    {
+        SECTION("escape_dobulequote")
+        {
+            auto s = "[\"\\\"foo\\\"\"]";
+            json j = json::parse(s);
+            CHECK(j == R"(["\"foo\""])"_json);
+        }
+    }
+}