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 - 2013
5 // Distributed under the MIT License, see accompanying file LICENSE.txt
6 
7 // json spirit version 4.06
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  template< class Ostream >
107  void append_double( Ostream& os, const double d, const int precision )
108  {
109  os << std::showpoint << std::setprecision( precision ) << d;
110  }
111 
112  template< class String_type >
113  void erase_and_extract_exponent( String_type& str, String_type& exp )
114  {
115  const typename String_type::size_type exp_start= str.find( 'e' );
116 
117  if( exp_start != String_type::npos )
118  {
119  exp = str.substr( exp_start );
120  str.erase( exp_start );
121  }
122  }
123 
124  template< class String_type >
125  typename String_type::size_type find_first_non_zero( const String_type& str )
126  {
127  typename String_type::size_type result = str.size() - 1;
128 
129  for( ; result != 0; --result )
130  {
131  if( str[ result ] != '0' )
132  {
133  break;
134  }
135  }
136 
137  return result;
138  }
139 
140  template< class String_type >
141  void remove_trailing( String_type& str )
142  {
143  String_type exp;
144 
145  erase_and_extract_exponent( str, exp );
146 
147  const typename String_type::size_type first_non_zero = find_first_non_zero( str );
148 
149  if( first_non_zero != 0 )
150  {
151  const int offset = str[first_non_zero] == '.' ? 2 : 1; // note zero digits following a decimal point is non standard
152  str.erase( first_non_zero + offset );
153  }
154 
155  str += exp;
156  }
157 
158  // this class generates the JSON text,
159  // it keeps track of the indentation level etc.
160  //
161  template< class Value_type, class Ostream_type >
162  class Generator
163  {
164  typedef typename Value_type::Config_type Config_type;
165  typedef typename Config_type::String_type String_type;
166  typedef typename Config_type::Object_type Object_type;
167  typedef typename Config_type::Array_type Array_type;
168  typedef typename String_type::value_type Char_type;
169  typedef typename Object_type::value_type Obj_member_type;
170 
171  public:
172 
173  Generator( const Value_type& value, Ostream_type& os, unsigned int options )
174  : os_( os )
175  , indentation_level_( 0 )
176  , pretty_( ( options & pretty_print ) != 0 || ( options & single_line_arrays ) != 0 )
177  , raw_utf8_( ( options & raw_utf8 ) != 0 )
178  , esc_nonascii_( ( options & always_escape_nonascii ) != 0 )
179  , remove_trailing_zeros_( ( options & remove_trailing_zeros ) != 0 )
180  , single_line_arrays_( ( options & single_line_arrays ) != 0 )
181  , ios_saver_( os )
182  {
183  output( value );
184  }
185 
186  private:
187 
188  void output( const Value_type& value )
189  {
190  switch( value.type() )
191  {
192  case obj_type: output( value.get_obj() ); break;
193  case array_type: output( value.get_array() ); break;
194  case str_type: output( value.get_str() ); break;
195  case bool_type: output( value.get_bool() ); break;
196  case real_type: output( value.get_real() ); break;
197  case int_type: output_int( value ); break;
198  case null_type: os_ << "null"; break;
199  default: assert( false );
200  }
201  }
202 
203  void output( const Object_type& obj )
204  {
205  output_array_or_obj( obj, '{', '}' );
206  }
207 
208  void output( const Obj_member_type& member )
209  {
210  output( Config_type::get_name( member ) ); space();
211  os_ << ':'; space();
212  output( Config_type::get_value( member ) );
213  }
214 
215  void output_int( const Value_type& value )
216  {
217  if( value.is_uint64() )
218  {
219  os_ << value.get_uint64();
220  }
221  else
222  {
223  os_ << value.get_int64();
224  }
225  }
226 
227  void output( const String_type& s )
228  {
229  os_ << '"' << add_esc_chars( s, raw_utf8_, esc_nonascii_ ) << '"';
230  }
231 
232  void output( bool b )
233  {
234  os_ << to_str< String_type >( b ? "true" : "false" );
235  }
236 
237  void output( double d )
238  {
240  {
241  std::basic_ostringstream< Char_type > os;
242 
243  append_double( os, d, 16 ); // note precision is 16 so that we get some trailing space that we can remove,
244  // otherwise, 0.1234 gets converted to "0.12399999..."
245 
246  String_type str = os.str();
247 
248  remove_trailing( str );
249 
250  os_ << str;
251  }
252  else
253  {
254  append_double( os_, d, 17 );
255  }
256  }
257 
258  static bool contains_composite_elements( const Array_type& arr )
259  {
260  for( typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i )
261  {
262  const Value_type& val = *i;
263 
264  if( val.type() == obj_type ||
265  val.type() == array_type )
266  {
267  return true;
268  }
269  }
270 
271  return false;
272  }
273 
274  template< class Iter >
275  void output_composite_item( Iter i, Iter last )
276  {
277  output( *i );
278 
279  if( ++i != last )
280  {
281  os_ << ',';
282  }
283  }
284 
285  void output( const Array_type& arr )
286  {
288  {
289  os_ << '['; space();
290 
291  for( typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i )
292  {
293  output_composite_item( i, arr.end() );
294 
295  space();
296  }
297 
298  os_ << ']';
299  }
300  else
301  {
302  output_array_or_obj( arr, '[', ']' );
303  }
304  }
305 
306  template< class T >
307  void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char )
308  {
309  os_ << start_char; new_line();
310 
312 
313  for( typename T::const_iterator i = t.begin(); i != t.end(); ++i )
314  {
315  indent();
316 
317  output_composite_item( i, t.end() );
318 
319  new_line();
320  }
321 
323 
324  indent(); os_ << end_char;
325  }
326 
327  void indent()
328  {
329  if( !pretty_ ) return;
330 
331  for( int i = 0; i < indentation_level_; ++i )
332  {
333  os_ << " ";
334  }
335  }
336 
337  void space()
338  {
339  if( pretty_ ) os_ << ' ';
340  }
341 
342  void new_line()
343  {
344  if( pretty_ ) os_ << '\n';
345  }
346 
347  Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning
348 
349  Ostream_type& os_;
351  bool pretty_;
352  bool raw_utf8_;
356  boost::io::basic_ios_all_saver< Char_type > ios_saver_; // so that ostream state is reset after control is returned to the caller
357  };
358 
359  // writes JSON Value to a stream, e.g.
360  //
361  // write_stream( value, os, pretty_print );
362  //
363  template< class Value_type, class Ostream_type >
364  void write_stream( const Value_type& value, Ostream_type& os, unsigned int options = 0 )
365  {
366  os << std::dec;
367  Generator< Value_type, Ostream_type >( value, os, options );
368  }
369 
370  // writes JSON Value to a stream, e.g.
371  //
372  // const string json_str = write( value, pretty_print );
373  //
374  template< class Value_type >
375  typename Value_type::String_type write_string( const Value_type& value, unsigned int options = 0 )
376  {
377  typedef typename Value_type::String_type::value_type Char_type;
378 
379  std::basic_ostringstream< Char_type > os;
380 
381  write_stream( value, os, options );
382 
383  return os.str();
384  }
385 }
386 
387 #endif
String_type non_printable_to_string(unsigned int c)
Definition: json_spirit_writer_template.h:35
Definition: json_spirit_writer_options.h:22
int indentation_level_
Definition: json_spirit_writer_template.h:350
void output(const String_type &s)
Definition: json_spirit_writer_template.h:227
Definition: json_spirit_writer_options.h:15
void erase_and_extract_exponent(String_type &str, String_type &exp)
Definition: json_spirit_writer_template.h:113
String_type::value_type Char_type
Definition: json_spirit_writer_template.h:168
Value_type::String_type write_string(const Value_type &value, unsigned int options=0)
Definition: json_spirit_writer_template.h:375
void append_double(Ostream &os, const double d, const int precision)
Definition: json_spirit_writer_template.h:107
Generator & operator=(const Generator &)
Definition: json_spirit_writer_options.h:17
bool single_line_arrays_
Definition: json_spirit_writer_template.h:355
Definition: json_spirit_error_position.h:15
bool esc_nonascii_
Definition: json_spirit_writer_template.h:353
Definition: json_spirit_writer_template.h:162
void space()
Definition: json_spirit_writer_template.h:337
boost::io::basic_ios_all_saver< Char_type > ios_saver_
Definition: json_spirit_writer_template.h:356
Object_type::value_type Obj_member_type
Definition: json_spirit_writer_template.h:169
void output_int(const Value_type &value)
Definition: json_spirit_writer_template.h:215
Definition: json_spirit_writer_options.h:24
void indent()
Definition: json_spirit_writer_template.h:327
Definition: json_spirit_value.h:32
bool add_esc_char(Char_type c, String_type &s)
Definition: json_spirit_writer_template.h:52
char to_hex_char(unsigned int c)
Definition: json_spirit_writer_template.h:23
Value_type
Definition: json_spirit_value.h:32
Config_type::Array_type Array_type
Definition: json_spirit_writer_template.h:167
void output(const Array_type &arr)
Definition: json_spirit_writer_template.h:285
void write_stream(const Value_type &value, Ostream_type &os, unsigned int options=0)
Definition: json_spirit_writer_template.h:364
void output_composite_item(Iter i, Iter last)
Definition: json_spirit_writer_template.h:275
Config_type::String_type String_type
Definition: json_spirit_writer_template.h:165
int get_value(const Value &value, Type_to_type< int >)
Definition: json_spirit_value.h:531
Ostream_type & os_
Definition: json_spirit_writer_template.h:349
void remove_trailing(String_type &str)
Definition: json_spirit_writer_template.h:141
Definition: json_spirit_value.h:32
Definition: json_spirit_value.h:32
void output(const Value_type &value)
Definition: json_spirit_writer_template.h:188
bool remove_trailing_zeros_
Definition: json_spirit_writer_template.h:354
#define T(string_literal)
Definition: secure_crt.cpp:76
Definition: json_spirit_value.h:32
String_type::size_type find_first_non_zero(const String_type &str)
Definition: json_spirit_writer_template.h:125
void output_array_or_obj(const T &t, Char_type start_char, Char_type end_char)
Definition: json_spirit_writer_template.h:307
Generator(const Value_type &value, Ostream_type &os, unsigned int options)
Definition: json_spirit_writer_template.h:173
void output(const Obj_member_type &member)
Definition: json_spirit_writer_template.h:208
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_value.h:32
void new_line()
Definition: json_spirit_writer_template.h:342
Definition: json_spirit_value.h:32
Value_type::Config_type Config_type
Definition: json_spirit_writer_template.h:164
bool raw_utf8_
Definition: json_spirit_writer_template.h:352
Config_type::Object_type Object_type
Definition: json_spirit_writer_template.h:166
static bool contains_composite_elements(const Array_type &arr)
Definition: json_spirit_writer_template.h:258
Definition: json_spirit_value.h:32
void output(const Object_type &obj)
Definition: json_spirit_writer_template.h:203
void output(double d)
Definition: json_spirit_writer_template.h:237
Definition: json_spirit_writer_options.h:27
void output(bool b)
Definition: json_spirit_writer_template.h:232
bool pretty_
Definition: json_spirit_writer_template.h:351