Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
json
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
json
Commits
9dbb4402
Commit
9dbb4402
authored
Jun 03, 2015
by
Niels
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
improved performance for dump()
parent
cb873a42
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
184 additions
and
155 deletions
+184
-155
Makefile
Makefile
+1
-1
appveyor.yml
appveyor.yml
+1
-1
benchmarks.cpp
benchmarks/benchmarks.cpp
+8
-2
json.hpp
src/json.hpp
+64
-56
json.hpp.re2c
src/json.hpp.re2c
+64
-56
unit.cpp
test/unit.cpp
+46
-39
No files found.
Makefile
View file @
9dbb4402
...
@@ -33,6 +33,6 @@ pretty:
...
@@ -33,6 +33,6 @@ pretty:
src/json.hpp src/json.hpp.re2c
test
/unit.cpp benchmarks/benchmarks.cpp
src/json.hpp src/json.hpp.re2c
test
/unit.cpp benchmarks/benchmarks.cpp
# benchmarks
# benchmarks
json_benchmarks
:
benchmarks/benchmarks.cpp benchmarks/benchpress.hpp benchmarks/cxxopts.hpp
json_benchmarks
:
benchmarks/benchmarks.cpp benchmarks/benchpress.hpp benchmarks/cxxopts.hpp
src/json.hpp
$(CXX)
-std
=
c++11
$(CXXFLAGS)
-O3
-flto
-I
src
-I
benchmarks
$<
$(LDFLAGS)
-o
$@
$(CXX)
-std
=
c++11
$(CXXFLAGS)
-O3
-flto
-I
src
-I
benchmarks
$<
$(LDFLAGS)
-o
$@
./json_benchmarks
./json_benchmarks
appveyor.yml
View file @
9dbb4402
version
:
'
{build}'
version
:
'
{build}'
os
:
Visual Studio 2015 RC
os
:
MinGW
init
:
[]
init
:
[]
install
:
[]
install
:
[]
build_script
:
build_script
:
...
...
benchmarks/benchmarks.cpp
View file @
9dbb4402
...
@@ -49,12 +49,15 @@ BENCHMARK("dump jeopardy.json", [](benchpress::context* ctx)
...
@@ -49,12 +49,15 @@ BENCHMARK("dump jeopardy.json", [](benchpress::context* ctx)
std
::
ifstream
input_file
(
"benchmarks/files/jeopardy/jeopardy.json"
);
std
::
ifstream
input_file
(
"benchmarks/files/jeopardy/jeopardy.json"
);
nlohmann
::
json
j
;
nlohmann
::
json
j
;
j
<<
input_file
;
j
<<
input_file
;
std
::
ofstream
output_file
(
"jeopardy.dump.json"
);
ctx
->
reset_timer
();
ctx
->
reset_timer
();
for
(
size_t
i
=
0
;
i
<
ctx
->
num_iterations
();
++
i
)
for
(
size_t
i
=
0
;
i
<
ctx
->
num_iterations
();
++
i
)
{
{
j
.
dump
()
;
output_file
<<
j
;
}
}
std
::
remove
(
"jeopardy.dump.json"
);
})
})
BENCHMARK
(
"dump jeopardy.json with indent"
,
[](
benchpress
::
context
*
ctx
)
BENCHMARK
(
"dump jeopardy.json with indent"
,
[](
benchpress
::
context
*
ctx
)
...
@@ -62,10 +65,13 @@ BENCHMARK("dump jeopardy.json with indent", [](benchpress::context* ctx)
...
@@ -62,10 +65,13 @@ BENCHMARK("dump jeopardy.json with indent", [](benchpress::context* ctx)
std
::
ifstream
input_file
(
"benchmarks/files/jeopardy/jeopardy.json"
);
std
::
ifstream
input_file
(
"benchmarks/files/jeopardy/jeopardy.json"
);
nlohmann
::
json
j
;
nlohmann
::
json
j
;
j
<<
input_file
;
j
<<
input_file
;
std
::
ofstream
output_file
(
"jeopardy.dump.json"
);
ctx
->
reset_timer
();
ctx
->
reset_timer
();
for
(
size_t
i
=
0
;
i
<
ctx
->
num_iterations
();
++
i
)
for
(
size_t
i
=
0
;
i
<
ctx
->
num_iterations
();
++
i
)
{
{
j
.
dump
(
4
)
;
output_file
<<
std
::
setw
(
4
)
<<
j
;
}
}
std
::
remove
(
"jeopardy.dump.json"
);
})
})
src/json.hpp
View file @
9dbb4402
...
@@ -779,14 +779,18 @@ class basic_json
...
@@ -779,14 +779,18 @@ class basic_json
*/
*/
inline
string_t
dump
(
const
int
indent
=
-
1
)
const
noexcept
inline
string_t
dump
(
const
int
indent
=
-
1
)
const
noexcept
{
{
std
::
stringstream
ss
;
if
(
indent
>=
0
)
if
(
indent
>=
0
)
{
{
return
dump
(
true
,
static_cast
<
unsigned
int
>
(
indent
));
dump
(
ss
,
true
,
static_cast
<
unsigned
int
>
(
indent
));
}
}
else
else
{
{
return
dump
(
false
,
0
);
dump
(
ss
,
false
,
0
);
}
}
return
ss
.
str
();
}
}
/// return the type of the object (explicit)
/// return the type of the object (explicit)
...
@@ -1964,19 +1968,21 @@ class basic_json
...
@@ -1964,19 +1968,21 @@ class basic_json
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
o
,
const
basic_json
&
j
)
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
o
,
const
basic_json
&
j
)
{
{
// read width member and use it as indentation parameter if nonzero
// read width member and use it as indentation parameter if nonzero
const
int
indentation
=
(
o
.
width
()
==
0
)
?
-
1
:
o
.
width
();
const
bool
prettyPrint
=
(
o
.
width
()
>
0
);
const
auto
indentation
=
(
prettyPrint
?
o
.
width
()
:
0
);
o
<<
j
.
dump
(
indentation
);
// reset width to 0 for subsequent calls to this stream
o
.
width
(
0
);
// do the actual serialization
j
.
dump
(
o
,
prettyPrint
,
indentation
);
return
o
;
return
o
;
}
}
/// serialize to stream
/// serialize to stream
friend
std
::
ostream
&
operator
>>
(
const
basic_json
&
j
,
std
::
ostream
&
o
)
friend
std
::
ostream
&
operator
>>
(
const
basic_json
&
j
,
std
::
ostream
&
o
)
{
{
// read width member and use it as indentation parameter if nonzero
o
<<
j
;
const
int
indentation
=
(
o
.
width
()
==
0
)
?
-
1
:
o
.
width
();
o
<<
j
.
dump
(
indentation
);
return
o
;
return
o
;
}
}
...
@@ -2067,15 +2073,11 @@ class basic_json
...
@@ -2067,15 +2073,11 @@ class basic_json
characters by a sequence of "\u" followed by a four-digit hex
characters by a sequence of "\u" followed by a four-digit hex
representation.
representation.
@param o the stream to write the escaped string to
@param s the string to escape
@param s the string to escape
@return escaped string
*/
*/
static
string_t
escape_string
(
const
string_t
&
s
)
noexcept
static
void
escape_string
(
std
::
ostream
&
o
,
const
string_t
&
s
)
noexcept
{
{
// create a result string of at least the size than s
string_t
result
;
result
.
reserve
(
s
.
size
());
for
(
const
auto
c
:
s
)
for
(
const
auto
c
:
s
)
{
{
switch
(
c
)
switch
(
c
)
...
@@ -2083,49 +2085,49 @@ class basic_json
...
@@ -2083,49 +2085,49 @@ class basic_json
// quotation mark (0x22)
// quotation mark (0x22)
case
'"'
:
case
'"'
:
{
{
result
+=
"
\\\"
"
;
o
<<
"
\\\"
"
;
break
;
break
;
}
}
// reverse solidus (0x5c)
// reverse solidus (0x5c)
case
'\\'
:
case
'\\'
:
{
{
result
+=
"
\\\\
"
;
o
<<
"
\\\\
"
;
break
;
break
;
}
}
// backspace (0x08)
// backspace (0x08)
case
'\b'
:
case
'\b'
:
{
{
result
+=
"
\\
b"
;
o
<<
"
\\
b"
;
break
;
break
;
}
}
// formfeed (0x0c)
// formfeed (0x0c)
case
'\f'
:
case
'\f'
:
{
{
result
+=
"
\\
f"
;
o
<<
"
\\
f"
;
break
;
break
;
}
}
// newline (0x0a)
// newline (0x0a)
case
'\n'
:
case
'\n'
:
{
{
result
+=
"
\\
n"
;
o
<<
"
\\
n"
;
break
;
break
;
}
}
// carriage return (0x0d)
// carriage return (0x0d)
case
'\r'
:
case
'\r'
:
{
{
result
+=
"
\\
r"
;
o
<<
"
\\
r"
;
break
;
break
;
}
}
// horizontal tab (0x09)
// horizontal tab (0x09)
case
'\t'
:
case
'\t'
:
{
{
result
+=
"
\\
t"
;
o
<<
"
\\
t"
;
break
;
break
;
}
}
...
@@ -2135,24 +2137,19 @@ class basic_json
...
@@ -2135,24 +2137,19 @@ class basic_json
{
{
// control characters (everything between 0x00 and 0x1f)
// control characters (everything between 0x00 and 0x1f)
// -> create four-digit hex representation
// -> create four-digit hex representation
std
::
basic_stringstream
<
typename
string_t
::
value_type
>
ss
;
o
<<
"
\\
u"
<<
std
::
hex
<<
std
::
setw
(
4
)
<<
std
::
setfill
(
'0'
)
<<
int
(
c
);
ss
<<
"
\\
u"
<<
std
::
hex
<<
std
::
setw
(
4
)
<<
std
::
setfill
(
'0'
)
<<
int
(
c
);
result
+=
ss
.
str
();
}
}
else
else
{
{
// all other characters are added as-is
// all other characters are added as-is
result
.
append
(
1
,
c
)
;
o
<<
c
;
}
}
break
;
break
;
}
}
}
}
}
}
return
result
;
}
}
/*!
/*!
@brief internal implementation of the serialization function
@brief internal implementation of the serialization function
...
@@ -2166,108 +2163,115 @@ class basic_json
...
@@ -2166,108 +2163,115 @@ class basic_json
std::to_string()
std::to_string()
- floating-point numbers are converted to a string using "%g" format
- floating-point numbers are converted to a string using "%g" format
@param o stream to write to
@param prettyPrint whether the output shall be pretty-printed
@param prettyPrint whether the output shall be pretty-printed
@param indentStep the indent level
@param indentStep the indent level
@param currentIndent the current indent level (only used internally)
@param currentIndent the current indent level (only used internally)
*/
*/
inline
string_t
dump
(
const
bool
prettyPrint
,
const
unsigned
int
indentStep
,
inline
void
dump
(
std
::
ostream
&
o
,
const
bool
prettyPrint
,
const
unsigned
int
indentStep
,
const
unsigned
int
currentIndent
=
0
)
const
noexcept
const
unsigned
int
currentIndent
=
0
)
const
noexcept
{
{
// variable to hold indentation for recursive calls
// variable to hold indentation for recursive calls
auto
new_indent
=
currentIndent
;
auto
new_indent
=
currentIndent
;
// helper function to return whitespace as indentation
const
auto
indent
=
[
prettyPrint
,
&
new_indent
]()
{
return
prettyPrint
?
string_t
(
new_indent
,
' '
)
:
string_t
();
};
switch
(
m_type
)
switch
(
m_type
)
{
{
case
(
value_t
:
:
object
)
:
case
(
value_t
:
:
object
)
:
{
{
if
(
m_value
.
object
->
empty
())
if
(
m_value
.
object
->
empty
())
{
{
return
"{}"
;
o
<<
"{}"
;
return
;
}
}
string_t
result
=
"{"
;
o
<<
"{"
;
// increase indentation
// increase indentation
if
(
prettyPrint
)
if
(
prettyPrint
)
{
{
new_indent
+=
indentStep
;
new_indent
+=
indentStep
;
result
+=
"
\n
"
;
o
<<
"
\n
"
;
}
}
for
(
auto
i
=
m_value
.
object
->
cbegin
();
i
!=
m_value
.
object
->
cend
();
++
i
)
for
(
auto
i
=
m_value
.
object
->
cbegin
();
i
!=
m_value
.
object
->
cend
();
++
i
)
{
{
if
(
i
!=
m_value
.
object
->
cbegin
())
if
(
i
!=
m_value
.
object
->
cbegin
())
{
{
result
+=
prettyPrint
?
",
\n
"
:
","
;
o
<<
(
prettyPrint
?
",
\n
"
:
","
)
;
}
}
result
+=
indent
()
+
"
\"
"
+
escape_string
(
i
->
first
)
+
"
\"
:"
+
(
prettyPrint
?
" "
:
""
)
o
<<
string_t
(
new_indent
,
' '
)
<<
"
\"
"
;
+
i
->
second
.
dump
(
prettyPrint
,
indentStep
,
new_indent
);
escape_string
(
o
,
i
->
first
);
o
<<
"
\"
:"
<<
(
prettyPrint
?
" "
:
""
);
i
->
second
.
dump
(
o
,
prettyPrint
,
indentStep
,
new_indent
);
}
}
// decrease indentation
// decrease indentation
if
(
prettyPrint
)
if
(
prettyPrint
)
{
{
new_indent
-=
indentStep
;
new_indent
-=
indentStep
;
result
+=
"
\n
"
;
o
<<
"
\n
"
;
}
}
return
result
+
indent
()
+
"}"
;
o
<<
string_t
(
new_indent
,
' '
)
+
"}"
;
return
;
}
}
case
(
value_t
:
:
array
)
:
case
(
value_t
:
:
array
)
:
{
{
if
(
m_value
.
array
->
empty
())
if
(
m_value
.
array
->
empty
())
{
{
return
"[]"
;
o
<<
"[]"
;
return
;
}
}
string_t
result
=
"["
;
o
<<
"["
;
// increase indentation
// increase indentation
if
(
prettyPrint
)
if
(
prettyPrint
)
{
{
new_indent
+=
indentStep
;
new_indent
+=
indentStep
;
result
+=
"
\n
"
;
o
<<
"
\n
"
;
}
}
for
(
auto
i
=
m_value
.
array
->
cbegin
();
i
!=
m_value
.
array
->
cend
();
++
i
)
for
(
auto
i
=
m_value
.
array
->
cbegin
();
i
!=
m_value
.
array
->
cend
();
++
i
)
{
{
if
(
i
!=
m_value
.
array
->
cbegin
())
if
(
i
!=
m_value
.
array
->
cbegin
())
{
{
result
+=
prettyPrint
?
",
\n
"
:
","
;
o
<<
(
prettyPrint
?
",
\n
"
:
","
)
;
}
}
result
+=
indent
()
+
i
->
dump
(
prettyPrint
,
indentStep
,
new_indent
);
o
<<
string_t
(
new_indent
,
' '
);
i
->
dump
(
o
,
prettyPrint
,
indentStep
,
new_indent
);
}
}
// decrease indentation
// decrease indentation
if
(
prettyPrint
)
if
(
prettyPrint
)
{
{
new_indent
-=
indentStep
;
new_indent
-=
indentStep
;
result
+=
"
\n
"
;
o
<<
"
\n
"
;
}
}
return
result
+
indent
()
+
"]"
;
o
<<
string_t
(
new_indent
,
' '
)
<<
"]"
;
return
;
}
}
case
(
value_t
:
:
string
)
:
case
(
value_t
:
:
string
)
:
{
{
return
string_t
(
"
\"
"
)
+
escape_string
(
*
m_value
.
string
)
+
"
\"
"
;
o
<<
string_t
(
"
\"
"
);
escape_string
(
o
,
*
m_value
.
string
);
o
<<
"
\"
"
;
return
;
}
}
case
(
value_t
:
:
boolean
)
:
case
(
value_t
:
:
boolean
)
:
{
{
return
m_value
.
boolean
?
"true"
:
"false"
;
o
<<
(
m_value
.
boolean
?
"true"
:
"false"
);
return
;
}
}
case
(
value_t
:
:
number_integer
)
:
case
(
value_t
:
:
number_integer
)
:
{
{
return
std
::
to_string
(
m_value
.
number_integer
);
o
<<
m_value
.
number_integer
;
return
;
}
}
case
(
value_t
:
:
number_float
)
:
case
(
value_t
:
:
number_float
)
:
...
@@ -2277,16 +2281,20 @@ class basic_json
...
@@ -2277,16 +2281,20 @@ class basic_json
const
auto
sz
=
static_cast
<
unsigned
int
>
(
std
::
snprintf
(
nullptr
,
0
,
"%.15g"
,
m_value
.
number_float
));
const
auto
sz
=
static_cast
<
unsigned
int
>
(
std
::
snprintf
(
nullptr
,
0
,
"%.15g"
,
m_value
.
number_float
));
std
::
vector
<
typename
string_t
::
value_type
>
buf
(
sz
+
1
);
std
::
vector
<
typename
string_t
::
value_type
>
buf
(
sz
+
1
);
std
::
snprintf
(
&
buf
[
0
],
buf
.
size
(),
"%.15g"
,
m_value
.
number_float
);
std
::
snprintf
(
&
buf
[
0
],
buf
.
size
(),
"%.15g"
,
m_value
.
number_float
);
return
string_t
(
buf
.
data
());
o
<<
buf
.
data
();
return
;
}
}
case
(
value_t
:
:
discarded
)
:
case
(
value_t
:
:
discarded
)
:
{
{
return
"<discarded>"
;
o
<<
"<discarded>"
;
return
;
}
}
default
:
default
:
{
{
return
"null"
;
o
<<
"null"
;
return
;
}
}
}
}
}
}
...
...
src/json.hpp.re2c
View file @
9dbb4402
...
@@ -779,14 +779,18 @@ class basic_json
...
@@ -779,14 +779,18 @@ class basic_json
*/
*/
inline string_t dump(const int indent = -1) const noexcept
inline string_t dump(const int indent = -1) const noexcept
{
{
std::stringstream ss;
if (indent >= 0)
if (indent >= 0)
{
{
return dump(
true, static_cast<unsigned int>(indent));
dump(ss,
true, static_cast<unsigned int>(indent));
}
}
else
else
{
{
return dump(
false, 0);
dump(ss,
false, 0);
}
}
return ss.str();
}
}
/// return the type of the object (explicit)
/// return the type of the object (explicit)
...
@@ -1964,19 +1968,21 @@ class basic_json
...
@@ -1964,19 +1968,21 @@ class basic_json
friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
{
{
// read width member and use it as indentation parameter if nonzero
// read width member and use it as indentation parameter if nonzero
const int indentation = (o.width() == 0) ? -1 : o.width();
const bool prettyPrint = (o.width() > 0);
const auto indentation = (prettyPrint ? o.width() : 0);
o << j.dump(indentation);
// reset width to 0 for subsequent calls to this stream
o.width(0);
// do the actual serialization
j.dump(o, prettyPrint, indentation);
return o;
return o;
}
}
/// serialize to stream
/// serialize to stream
friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
{
{
// read width member and use it as indentation parameter if nonzero
o << j;
const int indentation = (o.width() == 0) ? -1 : o.width();
o << j.dump(indentation);
return o;
return o;
}
}
...
@@ -2067,15 +2073,11 @@ class basic_json
...
@@ -2067,15 +2073,11 @@ class basic_json
characters by a sequence of "\u" followed by a four-digit hex
characters by a sequence of "\u" followed by a four-digit hex
representation.
representation.
@param o the stream to write the escaped string to
@param s the string to escape
@param s the string to escape
@return escaped string
*/
*/
static
string_t escape_string(
const string_t& s) noexcept
static
void escape_string(std::ostream& o,
const string_t& s) noexcept
{
{
// create a result string of at least the size than s
string_t result;
result.reserve(s.size());
for (const auto c : s)
for (const auto c : s)
{
{
switch (c)
switch (c)
...
@@ -2083,49 +2085,49 @@ class basic_json
...
@@ -2083,49 +2085,49 @@ class basic_json
// quotation mark (0x22)
// quotation mark (0x22)
case '"':
case '"':
{
{
result +=
"\\\"";
o <<
"\\\"";
break;
break;
}
}
// reverse solidus (0x5c)
// reverse solidus (0x5c)
case '\\':
case '\\':
{
{
result +=
"\\\\";
o <<
"\\\\";
break;
break;
}
}
// backspace (0x08)
// backspace (0x08)
case '\b':
case '\b':
{
{
result +=
"\\b";
o <<
"\\b";
break;
break;
}
}
// formfeed (0x0c)
// formfeed (0x0c)
case '\f':
case '\f':
{
{
result +=
"\\f";
o <<
"\\f";
break;
break;
}
}
// newline (0x0a)
// newline (0x0a)
case '\n':
case '\n':
{
{
result +=
"\\n";
o <<
"\\n";
break;
break;
}
}
// carriage return (0x0d)
// carriage return (0x0d)
case '\r':
case '\r':
{
{
result +=
"\\r";
o <<
"\\r";
break;
break;
}
}
// horizontal tab (0x09)
// horizontal tab (0x09)
case '\t':
case '\t':
{
{
result +=
"\\t";
o <<
"\\t";
break;
break;
}
}
...
@@ -2135,24 +2137,19 @@ class basic_json
...
@@ -2135,24 +2137,19 @@ class basic_json
{
{
// control characters (everything between 0x00 and 0x1f)
// control characters (everything between 0x00 and 0x1f)
// -> create four-digit hex representation
// -> create four-digit hex representation
std::basic_stringstream<typename string_t::value_type> ss;
o << "\\u" << std::hex << std::setw(4) << std::setfill('0') << int(c);
ss << "\\u" << std::hex << std::setw(4) << std::setfill('0') << int(c);
result += ss.str();
}
}
else
else
{
{
// all other characters are added as-is
// all other characters are added as-is
result.append(1, c)
;
o << c
;
}
}
break;
break;
}
}
}
}
}
}
return result;
}
}
/*!
/*!
@brief internal implementation of the serialization function
@brief internal implementation of the serialization function
...
@@ -2166,108 +2163,115 @@ class basic_json
...
@@ -2166,108 +2163,115 @@ class basic_json
std::to_string()
std::to_string()
- floating-point numbers are converted to a string using "%g" format
- floating-point numbers are converted to a string using "%g" format
@param o stream to write to
@param prettyPrint whether the output shall be pretty-printed
@param prettyPrint whether the output shall be pretty-printed
@param indentStep the indent level
@param indentStep the indent level
@param currentIndent the current indent level (only used internally)
@param currentIndent the current indent level (only used internally)
*/
*/
inline
string_t dump(
const bool prettyPrint, const unsigned int indentStep,
inline
void dump(std::ostream& o,
const bool prettyPrint, const unsigned int indentStep,
const unsigned int currentIndent = 0) const noexcept
const unsigned int currentIndent = 0) const noexcept
{
{
// variable to hold indentation for recursive calls
// variable to hold indentation for recursive calls
auto new_indent = currentIndent;
auto new_indent = currentIndent;
// helper function to return whitespace as indentation
const auto indent = [prettyPrint, &new_indent]()
{
return prettyPrint ? string_t(new_indent, ' ') : string_t();
};
switch (m_type)
switch (m_type)
{
{
case (value_t::object):
case (value_t::object):
{
{
if (m_value.object->empty())
if (m_value.object->empty())
{
{
return "{}";
o << "{}";
return;
}
}
string_t result =
"{";
o <<
"{";
// increase indentation
// increase indentation
if (prettyPrint)
if (prettyPrint)
{
{
new_indent += indentStep;
new_indent += indentStep;
result +=
"\n";
o <<
"\n";
}
}
for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
{
{
if (i != m_value.object->cbegin())
if (i != m_value.object->cbegin())
{
{
result += prettyPrint ? ",\n" : ","
;
o << (prettyPrint ? ",\n" : ",")
;
}
}
result += indent() + "\"" + escape_string(i->first) + "\":" + (prettyPrint ? " " : "")
o << string_t(new_indent, ' ') << "\"";
+ i->second.dump(prettyPrint, indentStep, new_indent);
escape_string(o, i->first);
o << "\":" << (prettyPrint ? " " : "");
i->second.dump(o, prettyPrint, indentStep, new_indent);
}
}
// decrease indentation
// decrease indentation
if (prettyPrint)
if (prettyPrint)
{
{
new_indent -= indentStep;
new_indent -= indentStep;
result +=
"\n";
o <<
"\n";
}
}
return result + indent() + "}";
o << string_t(new_indent, ' ') + "}";
return;
}
}
case (value_t::array):
case (value_t::array):
{
{
if (m_value.array->empty())
if (m_value.array->empty())
{
{
return "[]";
o << "[]";
return;
}
}
string_t result =
"[";
o <<
"[";
// increase indentation
// increase indentation
if (prettyPrint)
if (prettyPrint)
{
{
new_indent += indentStep;
new_indent += indentStep;
result +=
"\n";
o <<
"\n";
}
}
for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
{
{
if (i != m_value.array->cbegin())
if (i != m_value.array->cbegin())
{
{
result += prettyPrint ? ",\n" : ","
;
o << (prettyPrint ? ",\n" : ",")
;
}
}
result += indent() + i->dump(prettyPrint, indentStep, new_indent);
o << string_t(new_indent, ' ');
i->dump(o, prettyPrint, indentStep, new_indent);
}
}
// decrease indentation
// decrease indentation
if (prettyPrint)
if (prettyPrint)
{
{
new_indent -= indentStep;
new_indent -= indentStep;
result +=
"\n";
o <<
"\n";
}
}
return result + indent() + "]";
o << string_t(new_indent, ' ') << "]";
return;
}
}
case (value_t::string):
case (value_t::string):
{
{
return string_t("\"") + escape_string(*m_value.string) + "\"";
o << string_t("\"");
escape_string(o, *m_value.string);
o << "\"";
return;
}
}
case (value_t::boolean):
case (value_t::boolean):
{
{
return m_value.boolean ? "true" : "false";
o << (m_value.boolean ? "true" : "false");
return;
}
}
case (value_t::number_integer):
case (value_t::number_integer):
{
{
return std::to_string(m_value.number_integer);
o << m_value.number_integer;
return;
}
}
case (value_t::number_float):
case (value_t::number_float):
...
@@ -2277,16 +2281,20 @@ class basic_json
...
@@ -2277,16 +2281,20 @@ class basic_json
const auto sz = static_cast<unsigned int>(std::snprintf(nullptr, 0, "%.15g", m_value.number_float));
const auto sz = static_cast<unsigned int>(std::snprintf(nullptr, 0, "%.15g", m_value.number_float));
std::vector<typename string_t::value_type> buf(sz + 1);
std::vector<typename string_t::value_type> buf(sz + 1);
std::snprintf(&buf[0], buf.size(), "%.15g", m_value.number_float);
std::snprintf(&buf[0], buf.size(), "%.15g", m_value.number_float);
return string_t(buf.data());
o << buf.data();
return;
}
}
case (value_t::discarded):
case (value_t::discarded):
{
{
return "<discarded>";
o << "<discarded>";
return;
}
}
default:
default:
{
{
return "null";
o << "null";
return;
}
}
}
}
}
}
...
...
test/unit.cpp
View file @
9dbb4402
...
@@ -7162,45 +7162,52 @@ TEST_CASE("convenience functions")
...
@@ -7162,45 +7162,52 @@ TEST_CASE("convenience functions")
SECTION
(
"string escape"
)
SECTION
(
"string escape"
)
{
{
CHECK
(
json
::
escape_string
(
"
\"
"
)
==
"
\\\"
"
);
auto
escape_string
=
[](
const
std
::
string
&
s
)
CHECK
(
json
::
escape_string
(
"
\\
"
)
==
"
\\\\
"
);
{
CHECK
(
json
::
escape_string
(
"
\b
"
)
==
"
\\
b"
);
std
::
stringstream
ss
;
CHECK
(
json
::
escape_string
(
"
\f
"
)
==
"
\\
f"
);
json
::
escape_string
(
ss
,
s
);
CHECK
(
json
::
escape_string
(
"
\n
"
)
==
"
\\
n"
);
return
ss
.
str
();
CHECK
(
json
::
escape_string
(
"
\r
"
)
==
"
\\
r"
);
};
CHECK
(
json
::
escape_string
(
"
\t
"
)
==
"
\\
t"
);
CHECK
(
escape_string
(
"
\"
"
)
==
"
\\\"
"
);
CHECK
(
json
::
escape_string
(
"
\x01
"
)
==
"
\\
u0001"
);
CHECK
(
escape_string
(
"
\\
"
)
==
"
\\\\
"
);
CHECK
(
json
::
escape_string
(
"
\x02
"
)
==
"
\\
u0002"
);
CHECK
(
escape_string
(
"
\b
"
)
==
"
\\
b"
);
CHECK
(
json
::
escape_string
(
"
\x03
"
)
==
"
\\
u0003"
);
CHECK
(
escape_string
(
"
\f
"
)
==
"
\\
f"
);
CHECK
(
json
::
escape_string
(
"
\x04
"
)
==
"
\\
u0004"
);
CHECK
(
escape_string
(
"
\n
"
)
==
"
\\
n"
);
CHECK
(
json
::
escape_string
(
"
\x05
"
)
==
"
\\
u0005"
);
CHECK
(
escape_string
(
"
\r
"
)
==
"
\\
r"
);
CHECK
(
json
::
escape_string
(
"
\x06
"
)
==
"
\\
u0006"
);
CHECK
(
escape_string
(
"
\t
"
)
==
"
\\
t"
);
CHECK
(
json
::
escape_string
(
"
\x07
"
)
==
"
\\
u0007"
);
CHECK
(
json
::
escape_string
(
"
\x08
"
)
==
"
\\
b"
);
CHECK
(
escape_string
(
"
\x01
"
)
==
"
\\
u0001"
);
CHECK
(
json
::
escape_string
(
"
\x09
"
)
==
"
\\
t"
);
CHECK
(
escape_string
(
"
\x02
"
)
==
"
\\
u0002"
);
CHECK
(
json
::
escape_string
(
"
\x0a
"
)
==
"
\\
n"
);
CHECK
(
escape_string
(
"
\x03
"
)
==
"
\\
u0003"
);
CHECK
(
json
::
escape_string
(
"
\x0b
"
)
==
"
\\
u000b"
);
CHECK
(
escape_string
(
"
\x04
"
)
==
"
\\
u0004"
);
CHECK
(
json
::
escape_string
(
"
\x0c
"
)
==
"
\\
f"
);
CHECK
(
escape_string
(
"
\x05
"
)
==
"
\\
u0005"
);
CHECK
(
json
::
escape_string
(
"
\x0d
"
)
==
"
\\
r"
);
CHECK
(
escape_string
(
"
\x06
"
)
==
"
\\
u0006"
);
CHECK
(
json
::
escape_string
(
"
\x0e
"
)
==
"
\\
u000e"
);
CHECK
(
escape_string
(
"
\x07
"
)
==
"
\\
u0007"
);
CHECK
(
json
::
escape_string
(
"
\x0f
"
)
==
"
\\
u000f"
);
CHECK
(
escape_string
(
"
\x08
"
)
==
"
\\
b"
);
CHECK
(
json
::
escape_string
(
"
\x10
"
)
==
"
\\
u0010"
);
CHECK
(
escape_string
(
"
\x09
"
)
==
"
\\
t"
);
CHECK
(
json
::
escape_string
(
"
\x11
"
)
==
"
\\
u0011"
);
CHECK
(
escape_string
(
"
\x0a
"
)
==
"
\\
n"
);
CHECK
(
json
::
escape_string
(
"
\x12
"
)
==
"
\\
u0012"
);
CHECK
(
escape_string
(
"
\x0b
"
)
==
"
\\
u000b"
);
CHECK
(
json
::
escape_string
(
"
\x13
"
)
==
"
\\
u0013"
);
CHECK
(
escape_string
(
"
\x0c
"
)
==
"
\\
f"
);
CHECK
(
json
::
escape_string
(
"
\x14
"
)
==
"
\\
u0014"
);
CHECK
(
escape_string
(
"
\x0d
"
)
==
"
\\
r"
);
CHECK
(
json
::
escape_string
(
"
\x15
"
)
==
"
\\
u0015"
);
CHECK
(
escape_string
(
"
\x0e
"
)
==
"
\\
u000e"
);
CHECK
(
json
::
escape_string
(
"
\x16
"
)
==
"
\\
u0016"
);
CHECK
(
escape_string
(
"
\x0f
"
)
==
"
\\
u000f"
);
CHECK
(
json
::
escape_string
(
"
\x17
"
)
==
"
\\
u0017"
);
CHECK
(
escape_string
(
"
\x10
"
)
==
"
\\
u0010"
);
CHECK
(
json
::
escape_string
(
"
\x18
"
)
==
"
\\
u0018"
);
CHECK
(
escape_string
(
"
\x11
"
)
==
"
\\
u0011"
);
CHECK
(
json
::
escape_string
(
"
\x19
"
)
==
"
\\
u0019"
);
CHECK
(
escape_string
(
"
\x12
"
)
==
"
\\
u0012"
);
CHECK
(
json
::
escape_string
(
"
\x1a
"
)
==
"
\\
u001a"
);
CHECK
(
escape_string
(
"
\x13
"
)
==
"
\\
u0013"
);
CHECK
(
json
::
escape_string
(
"
\x1b
"
)
==
"
\\
u001b"
);
CHECK
(
escape_string
(
"
\x14
"
)
==
"
\\
u0014"
);
CHECK
(
json
::
escape_string
(
"
\x1c
"
)
==
"
\\
u001c"
);
CHECK
(
escape_string
(
"
\x15
"
)
==
"
\\
u0015"
);
CHECK
(
json
::
escape_string
(
"
\x1d
"
)
==
"
\\
u001d"
);
CHECK
(
escape_string
(
"
\x16
"
)
==
"
\\
u0016"
);
CHECK
(
json
::
escape_string
(
"
\x1e
"
)
==
"
\\
u001e"
);
CHECK
(
escape_string
(
"
\x17
"
)
==
"
\\
u0017"
);
CHECK
(
json
::
escape_string
(
"
\x1f
"
)
==
"
\\
u001f"
);
CHECK
(
escape_string
(
"
\x18
"
)
==
"
\\
u0018"
);
CHECK
(
escape_string
(
"
\x19
"
)
==
"
\\
u0019"
);
CHECK
(
escape_string
(
"
\x1a
"
)
==
"
\\
u001a"
);
CHECK
(
escape_string
(
"
\x1b
"
)
==
"
\\
u001b"
);
CHECK
(
escape_string
(
"
\x1c
"
)
==
"
\\
u001c"
);
CHECK
(
escape_string
(
"
\x1d
"
)
==
"
\\
u001d"
);
CHECK
(
escape_string
(
"
\x1e
"
)
==
"
\\
u001e"
);
CHECK
(
escape_string
(
"
\x1f
"
)
==
"
\\
u001f"
);
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment