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 
21 namespace 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 >
110  class Generator
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_;
291  bool pretty_;
292  bool raw_utf8_;
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
String_type non_printable_to_string(unsigned int c)
Definition: json_spirit_writer_template.h:35
Definition: json_spirit_writer_options.h:24
int indentation_level_
Definition: json_spirit_writer_template.h:290
void output(const String_type &s)
Definition: json_spirit_writer_template.h:183
Definition: json_spirit_writer_options.h:17
String_type::value_type Char_type
Definition: json_spirit_writer_template.h:116
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
Generator & operator=(const Generator &)
Definition: json_spirit_writer_options.h:19
bool single_line_arrays_
Definition: json_spirit_writer_template.h:294
Definition: json_spirit_error_position.h:15
bool esc_nonascii_
Definition: json_spirit_writer_template.h:293
Definition: json_spirit_writer_template.h:110
void space()
Definition: json_spirit_writer_template.h:277
boost::io::basic_ios_all_saver< Char_type > ios_saver_
Definition: json_spirit_writer_template.h:296
Object_type::value_type Obj_member_type
Definition: json_spirit_writer_template.h:117
void output_int(const Value_type &value)
Definition: json_spirit_writer_template.h:171
Definition: json_spirit_writer_options.h:26
int precision_of_doubles_
Definition: json_spirit_writer_template.h:295
void indent()
Definition: json_spirit_writer_template.h:267
Definition: json_spirit_value.h:33
bool add_esc_char(Char_type c, String_type &s)
Definition: json_spirit_writer_template.h:52
Generator(const Value_type &value, Ostream_type &os, int options, unsigned int precision_of_doubles)
Definition: json_spirit_writer_template.h:121
char to_hex_char(unsigned int c)
Definition: json_spirit_writer_template.h:23
Value_type
Definition: json_spirit_value.h:33
Config_type::Array_type Array_type
Definition: json_spirit_writer_template.h:115
void output(const Array_type &arr)
Definition: json_spirit_writer_template.h:225
void output_composite_item(Iter i, Iter last)
Definition: json_spirit_writer_template.h:215
Config_type::String_type String_type
Definition: json_spirit_writer_template.h:113
int get_value(const Value &value, Type_to_type< int >)
Definition: json_spirit_value.h:532
Ostream_type & os_
Definition: json_spirit_writer_template.h:289
Definition: json_spirit_value.h:33
Definition: json_spirit_value.h:33
void output(const Value_type &value)
Definition: json_spirit_writer_template.h:144
#define T(string_literal)
Definition: secure_crt.cpp:77
Definition: json_spirit_value.h:33
void output_array_or_obj(const T &t, Char_type start_char, Char_type end_char)
Definition: json_spirit_writer_template.h:247
void output(const Obj_member_type &member)
Definition: json_spirit_writer_template.h:164
String_type add_esc_chars(const String_type &s, bool raw_utf8, bool esc_nonascii)
Definition: json_spirit_writer_template.h:69
Definition: json_spirit_writer_options.h:15
Definition: json_spirit_value.h:33
void new_line()
Definition: json_spirit_writer_template.h:282
Definition: json_spirit_value.h:33
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
Value_type::Config_type Config_type
Definition: json_spirit_writer_template.h:112
bool raw_utf8_
Definition: json_spirit_writer_template.h:292
Config_type::Object_type Object_type
Definition: json_spirit_writer_template.h:114
static bool contains_composite_elements(const Array_type &arr)
Definition: json_spirit_writer_template.h:198
Definition: json_spirit_value.h:33
void output(const Object_type &obj)
Definition: json_spirit_writer_template.h:159
void output(double d)
Definition: json_spirit_writer_template.h:193
Definition: json_spirit_writer_options.h:29
void output(bool b)
Definition: json_spirit_writer_template.h:188
bool pretty_
Definition: json_spirit_writer_template.h:291