1 #ifndef JSON_SPIRIT_WRITER_TEMPLATE
\r
2 #define JSON_SPIRIT_WRITER_TEMPLATE
\r
4 // Copyright John W. Wilkinson 2007 - 2009.
\r
5 // Distributed under the MIT License, see accompanying file LICENSE.txt
\r
7 // json spirit version 4.03
\r
9 #include "json_spirit_value.h"
\r
15 namespace json_spirit
\r
17 inline char to_hex_char( unsigned int c )
\r
21 const char ch = static_cast< char >( c );
\r
23 if( ch < 10 ) return '0' + ch;
\r
25 return 'A' - 10 + ch;
\r
28 template< class String_type >
\r
29 String_type non_printable_to_string( unsigned int c )
\r
31 typedef typename String_type::value_type Char_type;
\r
33 String_type result( 6, '\\' );
\r
37 result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4;
\r
38 result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4;
\r
39 result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4;
\r
40 result[ 2 ] = to_hex_char( c & 0x000F );
\r
45 template< typename Char_type, class String_type >
\r
46 bool add_esc_char( Char_type c, String_type& s )
\r
50 case '"': s += to_str< String_type >( "\\\"" ); return true;
\r
51 case '\\': s += to_str< String_type >( "\\\\" ); return true;
\r
52 case '\b': s += to_str< String_type >( "\\b" ); return true;
\r
53 case '\f': s += to_str< String_type >( "\\f" ); return true;
\r
54 case '\n': s += to_str< String_type >( "\\n" ); return true;
\r
55 case '\r': s += to_str< String_type >( "\\r" ); return true;
\r
56 case '\t': s += to_str< String_type >( "\\t" ); return true;
\r
62 template< class String_type >
\r
63 String_type add_esc_chars( const String_type& s )
\r
65 typedef typename String_type::const_iterator Iter_type;
\r
66 typedef typename String_type::value_type Char_type;
\r
70 const Iter_type end( s.end() );
\r
72 for( Iter_type i = s.begin(); i != end; ++i )
\r
74 const Char_type c( *i );
\r
76 if( add_esc_char( c, result ) ) continue;
\r
78 const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c );
\r
80 if( iswprint( unsigned_c ) )
\r
86 result += non_printable_to_string< String_type >( unsigned_c );
\r
93 // this class generates the JSON text,
\r
94 // it keeps track of the indentation level etc.
\r
96 template< class Value_type, class Ostream_type >
\r
99 typedef typename Value_type::Config_type Config_type;
\r
100 typedef typename Config_type::String_type String_type;
\r
101 typedef typename Config_type::Object_type Object_type;
\r
102 typedef typename Config_type::Array_type Array_type;
\r
103 typedef typename String_type::value_type Char_type;
\r
104 typedef typename Object_type::value_type Obj_member_type;
\r
108 Generator( const Value_type& value, Ostream_type& os, bool pretty )
\r
110 , indentation_level_( 0 )
\r
111 , pretty_( pretty )
\r
118 void output( const Value_type& value )
\r
120 switch( value.type() )
\r
122 case obj_type: output( value.get_obj() ); break;
\r
123 case array_type: output( value.get_array() ); break;
\r
124 case str_type: output( value.get_str() ); break;
\r
125 case bool_type: output( value.get_bool() ); break;
\r
126 case int_type: output_int( value ); break;
\r
127 case real_type: os_ << std::showpoint << std::setprecision( 16 )
\r
128 << value.get_real(); break;
\r
129 case null_type: os_ << "null"; break;
\r
130 default: assert( false );
\r
134 void output( const Object_type& obj )
\r
136 output_array_or_obj( obj, '{', '}' );
\r
139 void output( const Array_type& arr )
\r
141 output_array_or_obj( arr, '[', ']' );
\r
144 void output( const Obj_member_type& member )
\r
146 output( Config_type::get_name( member ) ); space();
\r
147 os_ << ':'; space();
\r
148 output( Config_type::get_value( member ) );
\r
151 void output_int( const Value_type& value )
\r
153 if( value.is_uint64() )
\r
155 os_ << value.get_uint64();
\r
159 os_ << value.get_int64();
\r
163 void output( const String_type& s )
\r
165 os_ << '"' << add_esc_chars( s ) << '"';
\r
168 void output( bool b )
\r
170 os_ << to_str< String_type >( b ? "true" : "false" );
\r
173 template< class T >
\r
174 void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char )
\r
176 os_ << start_char; new_line();
\r
178 ++indentation_level_;
\r
180 for( typename T::const_iterator i = t.begin(); i != t.end(); ++i )
\r
182 indent(); output( *i );
\r
184 typename T::const_iterator next = i;
\r
186 if( ++next != t.end())
\r
194 --indentation_level_;
\r
196 indent(); os_ << end_char;
\r
201 if( !pretty_ ) return;
\r
203 for( int i = 0; i < indentation_level_; ++i )
\r
211 if( pretty_ ) os_ << ' ';
\r
216 if( pretty_ ) os_ << '\n';
\r
219 Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning
\r
222 int indentation_level_;
\r
226 template< class Value_type, class Ostream_type >
\r
227 void write_stream( const Value_type& value, Ostream_type& os, bool pretty )
\r
229 Generator< Value_type, Ostream_type >( value, os, pretty );
\r
232 template< class Value_type >
\r
233 typename Value_type::String_type write_string( const Value_type& value, bool pretty )
\r
235 typedef typename Value_type::String_type::value_type Char_type;
\r
237 std::basic_ostringstream< Char_type > os;
\r
239 write_stream( value, os, pretty );
\r