mirror of
https://github.com/nlohmann/json.git
synced 2025-07-13 20:21:48 +03:00
@ -4535,68 +4535,31 @@ class basic_json
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief escape a string
|
||||
@brief calculates the extra space to escape a JSON string
|
||||
|
||||
Escape a string by replacing certain special characters by a sequence of an
|
||||
escape character (backslash) and another character and other control
|
||||
characters by a sequence of "\u" followed by a four-digit hex
|
||||
representation.
|
||||
|
||||
@param[out] o the stream to write the escaped string to
|
||||
@param[in] s the string to escape
|
||||
@return the number of characters required to escape string @a s
|
||||
|
||||
@complexity Linear in the length of string @a s.
|
||||
*/
|
||||
static void escape_string(std::ostream& o, const string_t& s)
|
||||
static std::size_t extra_space(const string_t& s) noexcept
|
||||
{
|
||||
for (const auto c : s)
|
||||
std::size_t result = 0;
|
||||
|
||||
for (const auto& c : s)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
// quotation mark (0x22)
|
||||
case '"':
|
||||
{
|
||||
o << "\\\"";
|
||||
break;
|
||||
}
|
||||
|
||||
// reverse solidus (0x5c)
|
||||
case '\\':
|
||||
{
|
||||
o << "\\\\";
|
||||
break;
|
||||
}
|
||||
|
||||
// backspace (0x08)
|
||||
case '\b':
|
||||
{
|
||||
o << "\\b";
|
||||
break;
|
||||
}
|
||||
|
||||
// formfeed (0x0c)
|
||||
case '\f':
|
||||
{
|
||||
o << "\\f";
|
||||
break;
|
||||
}
|
||||
|
||||
// newline (0x0a)
|
||||
case '\n':
|
||||
{
|
||||
o << "\\n";
|
||||
break;
|
||||
}
|
||||
|
||||
// carriage return (0x0d)
|
||||
case '\r':
|
||||
{
|
||||
o << "\\r";
|
||||
break;
|
||||
}
|
||||
|
||||
// horizontal tab (0x09)
|
||||
case '\t':
|
||||
{
|
||||
o << "\\t";
|
||||
// from c (1 byte) to \x (2 bytes)
|
||||
result += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4604,19 +4567,121 @@ class basic_json
|
||||
{
|
||||
if (c >= 0x00 and c <= 0x1f)
|
||||
{
|
||||
// control characters (everything between 0x00 and 0x1f)
|
||||
// -> create four-digit hex representation
|
||||
o << "\\u" << std::hex << std::setw(4) << std::setfill('0') << int(c) << std::dec;
|
||||
}
|
||||
else
|
||||
{
|
||||
// all other characters are added as-is
|
||||
o << c;
|
||||
// from c (1 byte) to \uxxxx (6 bytes)
|
||||
result += 5;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief escape a string
|
||||
|
||||
Escape a string by replacing certain special characters by a sequence of an
|
||||
escape character (backslash) and another character and other control
|
||||
characters by a sequence of "\u" followed by a four-digit hex
|
||||
representation.
|
||||
|
||||
@param[in] s the string to escape
|
||||
@return the escaped string
|
||||
|
||||
@complexity Linear in the length of string @a s.
|
||||
*/
|
||||
static string_t escape_string(const string_t& s) noexcept
|
||||
{
|
||||
const auto space = extra_space(s);
|
||||
if (space == 0)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
// create a result string of necessary size
|
||||
string_t result(s.size() + space, '\\');
|
||||
std::size_t pos = 0;
|
||||
|
||||
for (const auto& c : s)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
// quotation mark (0x22)
|
||||
case '"':
|
||||
{
|
||||
result[pos + 1] = '"';
|
||||
pos += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// reverse solidus (0x5c)
|
||||
case '\\':
|
||||
{
|
||||
// nothing to change
|
||||
pos += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// backspace (0x08)
|
||||
case '\b':
|
||||
{
|
||||
result[pos + 1] = 'b';
|
||||
pos += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// formfeed (0x0c)
|
||||
case '\f':
|
||||
{
|
||||
result[pos + 1] = 'f';
|
||||
pos += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// newline (0x0a)
|
||||
case '\n':
|
||||
{
|
||||
result[pos + 1] = 'n';
|
||||
pos += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// carriage return (0x0d)
|
||||
case '\r':
|
||||
{
|
||||
result[pos + 1] = 'r';
|
||||
pos += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// horizontal tab (0x09)
|
||||
case '\t':
|
||||
{
|
||||
result[pos + 1] = 't';
|
||||
pos += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if (c >= 0x00 and c <= 0x1f)
|
||||
{
|
||||
// print character c as \uxxxx
|
||||
sprintf(&result[pos + 1], "u%04x", int(c));
|
||||
pos += 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
// all other characters are added as-is
|
||||
result[pos++] = c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -4667,9 +4732,9 @@ class basic_json
|
||||
{
|
||||
o << (pretty_print ? ",\n" : ",");
|
||||
}
|
||||
o << string_t(new_indent, ' ') << "\"";
|
||||
escape_string(o, i->first);
|
||||
o << "\":" << (pretty_print ? " " : "");
|
||||
o << string_t(new_indent, ' ') << "\""
|
||||
<< escape_string(i->first) << "\":"
|
||||
<< (pretty_print ? " " : "");
|
||||
i->second.dump(o, pretty_print, indent_step, new_indent);
|
||||
}
|
||||
|
||||
@ -4724,9 +4789,7 @@ class basic_json
|
||||
|
||||
case (value_t::string):
|
||||
{
|
||||
o << string_t("\"");
|
||||
escape_string(o, *m_value.string);
|
||||
o << "\"";
|
||||
o << string_t("\"") << escape_string(*m_value.string) << "\"";
|
||||
return;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user