raw
genesis                 1 #ifndef JSON_SPIRIT_WRITER_TEMPLATE
genesis 2 #define JSON_SPIRIT_WRITER_TEMPLATE
genesis 3
genesis 4 // Copyright John W. Wilkinson 2007 - 2009.
genesis 5 // Distributed under the MIT License, see accompanying file LICENSE.txt
genesis 6
genesis 7 // json spirit version 4.03
genesis 8
genesis 9 #include "json_spirit_value.h"
genesis 10
genesis 11 #include <cassert>
genesis 12 #include <sstream>
genesis 13 #include <iomanip>
genesis 14
genesis 15 namespace json_spirit
genesis 16 {
genesis 17 inline char to_hex_char( unsigned int c )
genesis 18 {
genesis 19 assert( c <= 0xF );
genesis 20
genesis 21 const char ch = static_cast< char >( c );
genesis 22
genesis 23 if( ch < 10 ) return '0' + ch;
genesis 24
genesis 25 return 'A' - 10 + ch;
genesis 26 }
genesis 27
genesis 28 template< class String_type >
genesis 29 String_type non_printable_to_string( unsigned int c )
genesis 30 {
genesis 31 typedef typename String_type::value_type Char_type;
genesis 32
genesis 33 String_type result( 6, '\\' );
genesis 34
genesis 35 result[1] = 'u';
genesis 36
genesis 37 result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4;
genesis 38 result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4;
genesis 39 result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4;
genesis 40 result[ 2 ] = to_hex_char( c & 0x000F );
genesis 41
genesis 42 return result;
genesis 43 }
genesis 44
genesis 45 template< typename Char_type, class String_type >
genesis 46 bool add_esc_char( Char_type c, String_type& s )
genesis 47 {
genesis 48 switch( c )
genesis 49 {
genesis 50 case '"': s += to_str< String_type >( "\\\"" ); return true;
genesis 51 case '\\': s += to_str< String_type >( "\\\\" ); return true;
genesis 52 case '\b': s += to_str< String_type >( "\\b" ); return true;
genesis 53 case '\f': s += to_str< String_type >( "\\f" ); return true;
genesis 54 case '\n': s += to_str< String_type >( "\\n" ); return true;
genesis 55 case '\r': s += to_str< String_type >( "\\r" ); return true;
genesis 56 case '\t': s += to_str< String_type >( "\\t" ); return true;
genesis 57 }
genesis 58
genesis 59 return false;
genesis 60 }
genesis 61
genesis 62 template< class String_type >
genesis 63 String_type add_esc_chars( const String_type& s )
genesis 64 {
genesis 65 typedef typename String_type::const_iterator Iter_type;
genesis 66 typedef typename String_type::value_type Char_type;
genesis 67
genesis 68 String_type result;
genesis 69
genesis 70 const Iter_type end( s.end() );
genesis 71
genesis 72 for( Iter_type i = s.begin(); i != end; ++i )
genesis 73 {
genesis 74 const Char_type c( *i );
genesis 75
genesis 76 if( add_esc_char( c, result ) ) continue;
genesis 77
genesis 78 const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c );
genesis 79
genesis 80 if( iswprint( unsigned_c ) )
genesis 81 {
genesis 82 result += c;
genesis 83 }
genesis 84 else
genesis 85 {
genesis 86 result += non_printable_to_string< String_type >( unsigned_c );
genesis 87 }
genesis 88 }
genesis 89
genesis 90 return result;
genesis 91 }
genesis 92
genesis 93 // this class generates the JSON text,
genesis 94 // it keeps track of the indentation level etc.
genesis 95 //
genesis 96 template< class Value_type, class Ostream_type >
genesis 97 class Generator
genesis 98 {
genesis 99 typedef typename Value_type::Config_type Config_type;
genesis 100 typedef typename Config_type::String_type String_type;
genesis 101 typedef typename Config_type::Object_type Object_type;
genesis 102 typedef typename Config_type::Array_type Array_type;
genesis 103 typedef typename String_type::value_type Char_type;
genesis 104 typedef typename Object_type::value_type Obj_member_type;
genesis 105
genesis 106 public:
genesis 107
genesis 108 Generator( const Value_type& value, Ostream_type& os, bool pretty )
genesis 109 : os_( os )
genesis 110 , indentation_level_( 0 )
genesis 111 , pretty_( pretty )
genesis 112 {
genesis 113 output( value );
genesis 114 }
genesis 115
genesis 116 private:
genesis 117
genesis 118 void output( const Value_type& value )
genesis 119 {
genesis 120 switch( value.type() )
genesis 121 {
genesis 122 case obj_type: output( value.get_obj() ); break;
genesis 123 case array_type: output( value.get_array() ); break;
genesis 124 case str_type: output( value.get_str() ); break;
genesis 125 case bool_type: output( value.get_bool() ); break;
genesis 126 case int_type: output_int( value ); break;
genesis 127
genesis 128 /// Bitcoin: Added std::fixed and changed precision from 16 to 8
genesis 129 case real_type: os_ << std::showpoint << std::fixed << std::setprecision(8)
genesis 130 << value.get_real(); break;
genesis 131
genesis 132 case null_type: os_ << "null"; break;
genesis 133 default: assert( false );
genesis 134 }
genesis 135 }
genesis 136
genesis 137 void output( const Object_type& obj )
genesis 138 {
genesis 139 output_array_or_obj( obj, '{', '}' );
genesis 140 }
genesis 141
genesis 142 void output( const Array_type& arr )
genesis 143 {
genesis 144 output_array_or_obj( arr, '[', ']' );
genesis 145 }
genesis 146
genesis 147 void output( const Obj_member_type& member )
genesis 148 {
genesis 149 output( Config_type::get_name( member ) ); space();
genesis 150 os_ << ':'; space();
genesis 151 output( Config_type::get_value( member ) );
genesis 152 }
genesis 153
genesis 154 void output_int( const Value_type& value )
genesis 155 {
genesis 156 if( value.is_uint64() )
genesis 157 {
genesis 158 os_ << value.get_uint64();
genesis 159 }
genesis 160 else
genesis 161 {
genesis 162 os_ << value.get_int64();
genesis 163 }
genesis 164 }
genesis 165
genesis 166 void output( const String_type& s )
genesis 167 {
genesis 168 os_ << '"' << add_esc_chars( s ) << '"';
genesis 169 }
genesis 170
genesis 171 void output( bool b )
genesis 172 {
genesis 173 os_ << to_str< String_type >( b ? "true" : "false" );
genesis 174 }
genesis 175
genesis 176 template< class T >
genesis 177 void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char )
genesis 178 {
genesis 179 os_ << start_char; new_line();
genesis 180
genesis 181 ++indentation_level_;
genesis 182
genesis 183 for( typename T::const_iterator i = t.begin(); i != t.end(); ++i )
genesis 184 {
genesis 185 indent(); output( *i );
genesis 186
genesis 187 typename T::const_iterator next = i;
genesis 188
genesis 189 if( ++next != t.end())
genesis 190 {
genesis 191 os_ << ',';
genesis 192 }
genesis 193
genesis 194 new_line();
genesis 195 }
genesis 196
genesis 197 --indentation_level_;
genesis 198
genesis 199 indent(); os_ << end_char;
genesis 200 }
genesis 201
genesis 202 void indent()
genesis 203 {
genesis 204 if( !pretty_ ) return;
genesis 205
genesis 206 for( int i = 0; i < indentation_level_; ++i )
genesis 207 {
genesis 208 os_ << " ";
genesis 209 }
genesis 210 }
genesis 211
genesis 212 void space()
genesis 213 {
genesis 214 if( pretty_ ) os_ << ' ';
genesis 215 }
genesis 216
genesis 217 void new_line()
genesis 218 {
genesis 219 if( pretty_ ) os_ << '\n';
genesis 220 }
genesis 221
genesis 222 Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning
genesis 223
genesis 224 Ostream_type& os_;
genesis 225 int indentation_level_;
genesis 226 bool pretty_;
genesis 227 };
genesis 228
genesis 229 template< class Value_type, class Ostream_type >
genesis 230 void write_stream( const Value_type& value, Ostream_type& os, bool pretty )
genesis 231 {
genesis 232 Generator< Value_type, Ostream_type >( value, os, pretty );
genesis 233 }
genesis 234
genesis 235 template< class Value_type >
genesis 236 typename Value_type::String_type write_string( const Value_type& value, bool pretty )
genesis 237 {
genesis 238 typedef typename Value_type::String_type::value_type Char_type;
genesis 239
genesis 240 std::basic_ostringstream< Char_type > os;
genesis 241
genesis 242 write_stream( value, os, pretty );
genesis 243
genesis 244 return os.str();
genesis 245 }
genesis 246 }
genesis 247
genesis 248 #endif