1 #ifndef JSON_SPIRIT_WRITER_TEMPLATE
2 #define JSON_SPIRIT_WRITER_TEMPLATE
4 // Copyright John W. Wilkinson 2007 - 2014
5 // Distributed under the MIT License, see accompanying file LICENSE.txt
7 // json spirit version 4.08
9 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
13 #include "json_spirit_value.h"
14 #include "json_spirit_writer_options.h"
19 #include <boost/io/ios_state.hpp>
23 inline char to_hex_char( unsigned int c
)
27 const char ch
= static_cast< char >( c
);
29 if( ch
< 10 ) return '0' + ch
;
34 template< class String_type
>
35 String_type
non_printable_to_string( unsigned int c
)
37 typedef typename
String_type::value_type Char_type
;
39 String_type
result( 6, '\\' );
43 result
[ 5 ] = to_hex_char( c
& 0x000F ); c
>>= 4;
44 result
[ 4 ] = to_hex_char( c
& 0x000F ); c
>>= 4;
45 result
[ 3 ] = to_hex_char( c
& 0x000F ); c
>>= 4;
46 result
[ 2 ] = to_hex_char( c
& 0x000F );
51 template< typename Char_type
, class String_type
>
52 bool add_esc_char( Char_type c
, String_type
& s
)
56 case '"': s
+= to_str
< String_type
>( "\\\"" ); return true;
57 case '\\': s
+= to_str
< String_type
>( "\\\\" ); return true;
58 case '\b': s
+= to_str
< String_type
>( "\\b" ); return true;
59 case '\f': s
+= to_str
< String_type
>( "\\f" ); return true;
60 case '\n': s
+= to_str
< String_type
>( "\\n" ); return true;
61 case '\r': s
+= to_str
< String_type
>( "\\r" ); return true;
62 case '\t': s
+= to_str
< String_type
>( "\\t" ); return true;
68 template< class String_type
>
69 String_type
add_esc_chars( const String_type
& s
, bool raw_utf8
, bool esc_nonascii
)
71 typedef typename
String_type::const_iterator Iter_type
;
72 typedef typename
String_type::value_type Char_type
;
76 const Iter_type
end( s
.end() );
78 for( Iter_type i
= s
.begin(); i
!= end
; ++i
)
80 const Char_type
c( *i
);
82 if( add_esc_char( c
, result
) ) continue;
90 const wint_t unsigned_c( ( c
>= 0 ) ? c
: 256 + c
);
92 if( !esc_nonascii
&& iswprint( unsigned_c
) )
98 result
+= non_printable_to_string
< String_type
>( unsigned_c
);
106 // this class generates the JSON text,
107 // it keeps track of the indentation level etc.
109 template< class Value_type
, class Ostream_type
>
112 typedef typename
Value_type::Config_type Config_type
;
113 typedef typename
Config_type::String_type String_type
;
114 typedef typename
Config_type::Object_type Object_type
;
115 typedef typename
Config_type::Array_type Array_type
;
116 typedef typename
String_type::value_type Char_type
;
117 typedef typename
Object_type::value_type Obj_member_type
;
121 Generator( const Value_type
& value
, Ostream_type
& os
, int options
, unsigned int precision_of_doubles
)
123 , indentation_level_( 0 )
124 , pretty_( ( options
& pretty_print
) != 0 || ( options
& single_line_arrays
) != 0 )
125 , raw_utf8_( ( options
& raw_utf8
) != 0 )
126 , esc_nonascii_( ( options
& always_escape_nonascii
) != 0 )
127 , single_line_arrays_( ( options
& single_line_arrays
) != 0 )
130 if( precision_of_doubles
> 0 )
132 precision_of_doubles_
= precision_of_doubles
;
136 precision_of_doubles_
= ( options
& remove_trailing_zeros
) != 0 ? 16 : 17;
144 void output( const Value_type
& value
)
146 switch( value
.type() )
148 case obj_type
: output( value
.get_obj() ); break;
149 case array_type
: output( value
.get_array() ); break;
150 case str_type
: output( value
.get_str() ); break;
151 case bool_type
: output( value
.get_bool() ); break;
152 case real_type
: output( value
.get_real() ); break;
153 case int_type
: output_int( value
); break;
154 case null_type
: os_
<< "null"; break;
155 default: assert( false );
159 void output( const Object_type
& obj
)
161 output_array_or_obj( obj
, '{', '}' );
164 void output( const Obj_member_type
& member
)
166 output( Config_type::get_name( member
) ); space();
168 output( Config_type::get_value( member
) );
171 void output_int( const Value_type
& value
)
173 if( value
.is_uint64() )
175 os_
<< value
.get_uint64();
179 os_
<< value
.get_int64();
183 void output( const String_type
& s
)
185 os_
<< '"' << add_esc_chars( s
, raw_utf8_
, esc_nonascii_
) << '"';
188 void output( bool b
)
190 os_
<< to_str
< String_type
>( b
? "true" : "false" );
193 void output( double d
)
195 os_
<< std::setprecision( precision_of_doubles_
) << d
;
198 static bool contains_composite_elements( const Array_type
& arr
)
200 for( typename
Array_type::const_iterator i
= arr
.begin(); i
!= arr
.end(); ++i
)
202 const Value_type
& val
= *i
;
204 if( val
.type() == obj_type
||
205 val
.type() == array_type
)
214 template< class Iter
>
215 void output_composite_item( Iter i
, Iter last
)
225 void output( const Array_type
& arr
)
227 if( single_line_arrays_
&& !contains_composite_elements( arr
) )
231 for( typename
Array_type::const_iterator i
= arr
.begin(); i
!= arr
.end(); ++i
)
233 output_composite_item( i
, arr
.end() );
242 output_array_or_obj( arr
, '[', ']' );
247 void output_array_or_obj( const T
& t
, Char_type start_char
, Char_type end_char
)
249 os_
<< start_char
; new_line();
251 ++indentation_level_
;
253 for( typename
T::const_iterator i
= t
.begin(); i
!= t
.end(); ++i
)
257 output_composite_item( i
, t
.end() );
262 --indentation_level_
;
264 indent(); os_
<< end_char
;
269 if( !pretty_
) return;
271 for( int i
= 0; i
< indentation_level_
; ++i
)
279 if( pretty_
) os_
<< ' ';
284 if( pretty_
) os_
<< '\n';
287 Generator
& operator=( const Generator
& ); // to prevent "assignment operator could not be generated" warning
290 int indentation_level_
;
294 bool single_line_arrays_
;
295 int precision_of_doubles_
;
296 boost::io::basic_ios_all_saver
< Char_type
> ios_saver_
; // so that ostream state is reset after control is returned to the caller
299 // writes JSON Value to a stream, e.g.
301 // write_stream( value, os, pretty_print );
303 template< class Value_type
, class Ostream_type
>
304 void write_stream( const Value_type
& value
, Ostream_type
& os
, int options
= none
, unsigned int precision_of_doubles
= 0 )
307 Generator
< Value_type
, Ostream_type
>( value
, os
, options
, precision_of_doubles
);
310 // writes JSON Value to a stream, e.g.
312 // const string json_str = write( value, pretty_print );
314 template< class Value_type
>
315 typename
Value_type::String_type
write_string( const Value_type
& value
, int options
= none
, unsigned int precision_of_doubles
= 0 )
317 typedef typename
Value_type::String_type::value_type Char_type
;
319 std::basic_ostringstream
< Char_type
> os
;
321 write_stream( value
, os
, options
, precision_of_doubles
);