Pyrogenesis trunk
json_spirit_writer_template.h
Go to the documentation of this file.
1#ifndef JSON_SPIRIT_WRITER_TEMPLATE
2#define JSON_SPIRIT_WRITER_TEMPLATE
3
4// Copyright John W. Wilkinson 2007 - 2014
5// Distributed under the MIT License, see accompanying file LICENSE.txt
6
7// json spirit version 4.08
8
9#if defined(_MSC_VER) && (_MSC_VER >= 1020)
10# pragma once
11#endif
12
13#include "json_spirit_value.h"
15
16#include <cassert>
17#include <sstream>
18#include <iomanip>
19#include <boost/io/ios_state.hpp>
20
21namespace json_spirit
22{
23 inline char to_hex_char( unsigned int c )
24 {
25 assert( c <= 0xF );
26
27 const char ch = static_cast< char >( c );
28
29 if( ch < 10 ) return '0' + ch;
30
31 return 'A' - 10 + ch;
32 }
33
34 template< class String_type >
35 String_type non_printable_to_string( unsigned int c )
36 {
37 typedef typename String_type::value_type Char_type;
38
39 String_type result( 6, '\\' );
40
41 result[1] = 'u';
42
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 );
47
48 return result;
49 }
50
51 template< typename Char_type, class String_type >
52 bool add_esc_char( Char_type c, String_type& s )
53 {
54 switch( c )
55 {
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;
63 }
64
65 return false;
66 }
67
68 template< class String_type >
69 String_type add_esc_chars( const String_type& s, bool raw_utf8, bool esc_nonascii )
70 {
71 typedef typename String_type::const_iterator Iter_type;
72 typedef typename String_type::value_type Char_type;
73
74 String_type result;
75
76 const Iter_type end( s.end() );
77
78 for( Iter_type i = s.begin(); i != end; ++i )
79 {
80 const Char_type c( *i );
81
82 if( add_esc_char( c, result ) ) continue;
83
84 if( raw_utf8 )
85 {
86 result += c;
87 }
88 else
89 {
90 const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c );
91
92 if( !esc_nonascii && iswprint( unsigned_c ) )
93 {
94 result += c;
95 }
96 else
97 {
98 result += non_printable_to_string< String_type >( unsigned_c );
99 }
100 }
101 }
102
103 return result;
104 }
105
106 // this class generates the JSON text,
107 // it keeps track of the indentation level etc.
108 //
109 template< class Value_type, class Ostream_type >
111 {
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;
118
119 public:
120
121 Generator( const Value_type& value, Ostream_type& os, int options, unsigned int precision_of_doubles )
122 : os_( os )
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 )
128 , ios_saver_( os )
129 {
130 if( precision_of_doubles > 0 )
131 {
132 precision_of_doubles_ = precision_of_doubles;
133 }
134 else
135 {
136 precision_of_doubles_ = ( options & remove_trailing_zeros ) != 0 ? 16 : 17;
137 }
138
139 output( value );
140 }
141
142 private:
143
144 void output( const Value_type& value )
145 {
146 switch( value.type() )
147 {
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 );
156 }
157 }
158
159 void output( const Object_type& obj )
160 {
161 output_array_or_obj( obj, '{', '}' );
162 }
163
164 void output( const Obj_member_type& member )
165 {
166 output( Config_type::get_name( member ) ); space();
167 os_ << ':'; space();
168 output( Config_type::get_value( member ) );
169 }
170
171 void output_int( const Value_type& value )
172 {
173 if( value.is_uint64() )
174 {
175 os_ << value.get_uint64();
176 }
177 else
178 {
179 os_ << value.get_int64();
180 }
181 }
182
183 void output( const String_type& s )
184 {
185 os_ << '"' << add_esc_chars( s, raw_utf8_, esc_nonascii_ ) << '"';
186 }
187
188 void output( bool b )
189 {
190 os_ << to_str< String_type >( b ? "true" : "false" );
191 }
192
193 void output( double d )
194 {
195 os_ << std::setprecision( precision_of_doubles_ ) << d;
196 }
197
198 static bool contains_composite_elements( const Array_type& arr )
199 {
200 for( typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i )
201 {
202 const Value_type& val = *i;
203
204 if( val.type() == obj_type ||
205 val.type() == array_type )
206 {
207 return true;
208 }
209 }
210
211 return false;
212 }
213
214 template< class Iter >
215 void output_composite_item( Iter i, Iter last )
216 {
217 output( *i );
218
219 if( ++i != last )
220 {
221 os_ << ',';
222 }
223 }
224
225 void output( const Array_type& arr )
226 {
228 {
229 os_ << '['; space();
230
231 for( typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i )
232 {
233 output_composite_item( i, arr.end() );
234
235 space();
236 }
237
238 os_ << ']';
239 }
240 else
241 {
242 output_array_or_obj( arr, '[', ']' );
243 }
244 }
245
246 template< class T >
247 void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char )
248 {
249 os_ << start_char; new_line();
250
252
253 for( typename T::const_iterator i = t.begin(); i != t.end(); ++i )
254 {
255 indent();
256
257 output_composite_item( i, t.end() );
258
259 new_line();
260 }
261
263
264 indent(); os_ << end_char;
265 }
266
267 void indent()
268 {
269 if( !pretty_ ) return;
270
271 for( int i = 0; i < indentation_level_; ++i )
272 {
273 os_ << " ";
274 }
275 }
276
277 void space()
278 {
279 if( pretty_ ) os_ << ' ';
280 }
281
282 void new_line()
283 {
284 if( pretty_ ) os_ << '\n';
285 }
286
287 Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning
288
289 Ostream_type& os_;
296 boost::io::basic_ios_all_saver< Char_type > ios_saver_; // so that ostream state is reset after control is returned to the caller
297 };
298
299 // writes JSON Value to a stream, e.g.
300 //
301 // write_stream( value, os, pretty_print );
302 //
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 )
305 {
306 os << std::dec;
307 Generator< Value_type, Ostream_type >( value, os, options, precision_of_doubles );
308 }
309
310 // writes JSON Value to a stream, e.g.
311 //
312 // const string json_str = write( value, pretty_print );
313 //
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 )
316 {
317 typedef typename Value_type::String_type::value_type Char_type;
318
319 std::basic_ostringstream< Char_type > os;
320
321 write_stream( value, os, options, precision_of_doubles );
322
323 return os.str();
324 }
325}
326
327#endif
Definition: json_spirit_writer_template.h:111
static bool contains_composite_elements(const Array_type &arr)
Definition: json_spirit_writer_template.h:198
boost::io::basic_ios_all_saver< Char_type > ios_saver_
Definition: json_spirit_writer_template.h:296
int precision_of_doubles_
Definition: json_spirit_writer_template.h:295
void output(double d)
Definition: json_spirit_writer_template.h:193
void output(const Object_type &obj)
Definition: json_spirit_writer_template.h:159
void output(const Value_type &value)
Definition: json_spirit_writer_template.h:144
Config_type::String_type String_type
Definition: json_spirit_writer_template.h:113
void output_array_or_obj(const T &t, Char_type start_char, Char_type end_char)
Definition: json_spirit_writer_template.h:247
Ostream_type & os_
Definition: json_spirit_writer_template.h:289
void output(const String_type &s)
Definition: json_spirit_writer_template.h:183
Value_type::Config_type Config_type
Definition: json_spirit_writer_template.h:112
Config_type::Object_type Object_type
Definition: json_spirit_writer_template.h:114
void indent()
Definition: json_spirit_writer_template.h:267
bool pretty_
Definition: json_spirit_writer_template.h:291
bool raw_utf8_
Definition: json_spirit_writer_template.h:292
void new_line()
Definition: json_spirit_writer_template.h:282
void output(const Array_type &arr)
Definition: json_spirit_writer_template.h:225
void space()
Definition: json_spirit_writer_template.h:277
bool single_line_arrays_
Definition: json_spirit_writer_template.h:294
String_type::value_type Char_type
Definition: json_spirit_writer_template.h:116
Generator(const Value_type &value, Ostream_type &os, int options, unsigned int precision_of_doubles)
Definition: json_spirit_writer_template.h:121
void output(bool b)
Definition: json_spirit_writer_template.h:188
Object_type::value_type Obj_member_type
Definition: json_spirit_writer_template.h:117
int indentation_level_
Definition: json_spirit_writer_template.h:290
void output_int(const Value_type &value)
Definition: json_spirit_writer_template.h:171
void output_composite_item(Iter i, Iter last)
Definition: json_spirit_writer_template.h:215
bool esc_nonascii_
Definition: json_spirit_writer_template.h:293
Config_type::Array_type Array_type
Definition: json_spirit_writer_template.h:115
Generator & operator=(const Generator &)
void output(const Obj_member_type &member)
Definition: json_spirit_writer_template.h:164
int get_value(const Value &value, Type_to_type< int >)
Definition: json_spirit_value.h:532
Definition: json_spirit_error_position.h:16
bool add_esc_char(Char_type c, String_type &s)
Definition: json_spirit_writer_template.h:52
void write_stream(const Value_type &value, Ostream_type &os, int options=none, unsigned int precision_of_doubles=0)
Definition: json_spirit_writer_template.h:304
String_type add_esc_chars(const String_type &s, bool raw_utf8, bool esc_nonascii)
Definition: json_spirit_writer_template.h:69
Value_type::String_type write_string(const Value_type &value, int options=none, unsigned int precision_of_doubles=0)
Definition: json_spirit_writer_template.h:315
@ none
Definition: json_spirit_writer_options.h:15
@ single_line_arrays
Definition: json_spirit_writer_options.h:26
@ raw_utf8
Definition: json_spirit_writer_options.h:19
@ remove_trailing_zeros
Definition: json_spirit_writer_options.h:24
@ pretty_print
Definition: json_spirit_writer_options.h:17
@ always_escape_nonascii
Definition: json_spirit_writer_options.h:29
char to_hex_char(unsigned int c)
Definition: json_spirit_writer_template.h:23
String_type non_printable_to_string(unsigned int c)
Definition: json_spirit_writer_template.h:35
Value_type
Definition: json_spirit_value.h:33
@ null_type
Definition: json_spirit_value.h:33
@ obj_type
Definition: json_spirit_value.h:33
@ array_type
Definition: json_spirit_value.h:33
@ int_type
Definition: json_spirit_value.h:33
@ str_type
Definition: json_spirit_value.h:33
@ bool_type
Definition: json_spirit_value.h:33
@ real_type
Definition: json_spirit_value.h:33
#define T(string_literal)
Definition: secure_crt.cpp:77