Skip to content

Commit 385857a

Browse files
committed
Improve performance of stringifying a JSON value
1 parent 8514c38 commit 385857a

File tree

2 files changed

+90
-75
lines changed

2 files changed

+90
-75
lines changed

include/tao/json/internal/escape.hh

Lines changed: 0 additions & 66 deletions
This file was deleted.

include/tao/json/internal/to_stream.hh

Lines changed: 90 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
#include "../external/double.hh"
1010
#include "../value.hh"
1111

12-
#include "escape.hh"
13-
1412
namespace tao
1513
{
1614
namespace json
@@ -19,7 +17,80 @@ namespace tao
1917
{
2018
inline void to_stream( std::ostream & o, const std::string & s )
2119
{
22-
o << escape( s ); // TODO: Check whether direct-to-stream is faster.
20+
static const char * h = "0123456789abcdef";
21+
22+
o << '"';
23+
const char * p = s.data();
24+
const char * l = p;
25+
const char * const e = s.data() + s.size();
26+
while ( p != e ) {
27+
switch ( const unsigned char c = *p ) {
28+
case '\b':
29+
if ( l != p ) {
30+
o.write( l, p - l );
31+
}
32+
l = ++p;
33+
o << "\\b";
34+
break;
35+
case '\f':
36+
if ( l != p ) {
37+
o.write( l, p - l );
38+
}
39+
l = ++p;
40+
o << "\\f";
41+
break;
42+
case '\n':
43+
if ( l != p ) {
44+
o.write( l, p - l );
45+
}
46+
l = ++p;
47+
o << "\\n";
48+
break;
49+
case '\r':
50+
if ( l != p ) {
51+
o.write( l, p - l );
52+
}
53+
l = ++p;
54+
o << "\\r";
55+
break;
56+
case '\t':
57+
if ( l != p ) {
58+
o.write( l, p - l );
59+
}
60+
l = ++p;
61+
o << "\\t";
62+
break;
63+
case '\\':
64+
if ( l != p ) {
65+
o.write( l, p - l );
66+
}
67+
l = ++p;
68+
o << "\\\\";
69+
break;
70+
case '\"':
71+
if ( l != p ) {
72+
o.write( l, p - l );
73+
}
74+
l = ++p;
75+
o << "\\\"";
76+
break;
77+
default:
78+
if ( ( c < 32 ) || ( c == 127 ) ) {
79+
if ( l != p ) {
80+
o.write( l, p - l );
81+
}
82+
l = ++p;
83+
o << "\\u00" << h[ ( c & 0xf0 ) >> 4 ] << h[ c & 0x0f ];
84+
}
85+
else {
86+
++p;
87+
}
88+
}
89+
}
90+
if ( l != p ) {
91+
o.write( l, p - l );
92+
}
93+
o << '"';
2394
}
2495

2596
template< template< typename ... > class Traits >
@@ -111,10 +182,15 @@ namespace tao
111182
{
112183
switch ( v.type() ) {
113184
case type::NULL_:
114-
o << "null";
185+
o.write( "null", 4 );
115186
return;
116187
case type::BOOL:
117-
o << ( v.unsafe_get_bool() ? "true" : "false" );
188+
if ( v.unsafe_get_bool() ) {
189+
o.write( "true", 4 );
190+
}
191+
else {
192+
o.write( "false", 5 );
193+
}
118194
return;
119195
case type::SIGNED:
120196
o << v.unsafe_get_signed();
@@ -140,7 +216,7 @@ namespace tao
140216
internal::to_stream( o, * p );
141217
}
142218
else {
143-
o << "null";
219+
o.write( "null", 4 );
144220
}
145221
return;
146222
}
@@ -152,10 +228,15 @@ namespace tao
152228
{
153229
switch ( v.type() ) {
154230
case type::NULL_:
155-
o << "null";
231+
o.write( "null", 4 );
156232
return;
157233
case type::BOOL:
158-
o << ( v.unsafe_get_bool() ? "true" : "false" );
234+
if ( v.unsafe_get_bool() ) {
235+
o.write( "true", 4 );
236+
}
237+
else {
238+
o.write( "false", 5 );
239+
}
159240
return;
160241
case type::SIGNED:
161242
o << v.unsafe_get_signed();
@@ -181,7 +262,7 @@ namespace tao
181262
internal::to_stream( o, * p, indent, current );
182263
}
183264
else {
184-
o << "null";
265+
o.write( "null", 4 );
185266
}
186267
return;
187268
}

0 commit comments

Comments
 (0)