-
+ F460B34ACF2FA80921B4A3EF40FE490F35D05F3CB8EEA67F6CEB51A81385F187C0E4A3F89D6D70D5A7FF41818020B9897601B32D306721C86F5E9DE0458733E4
bitcoin/src/json/json_spirit_writer_template.h
(0 . 0)(1 . 279)
9216 // /****************************\
9217 // * EXPERIMENTAL BRANCH. *
9218 // * FOR LABORATORY USE ONLY. *
9219 // ********************************
9220 // ************
9221 // **************
9222 // ****************
9223 // **** **** ****
9224 // *** *** ***
9225 // *** *** ***
9226 // *** * * **
9227 // ******** ********
9228 // ******* ******
9229 // *** **
9230 // * ******* **
9231 // ** * * * * *
9232 // ** * * ***
9233 // **** * * * * ****
9234 // **** *** * * ** ***
9235 // **** ********* ******
9236 // ******* ***** *******
9237 // ********* ****** **
9238 // ** ****** ******
9239 // ** ******* **
9240 // ** ******* ***
9241 // **** ******** ************
9242 // ************ ************
9243 // ******** *******
9244 // ****** ****
9245 // *** ***
9246 // ********************************
9247 #ifndef JSON_SPIRIT_WRITER_TEMPLATE
9248 #define JSON_SPIRIT_WRITER_TEMPLATE
9249
9250 // Copyright John W. Wilkinson 2007 - 2009.
9251 // Distributed under the MIT License, see accompanying file LICENSE.txt
9252
9253 // json spirit version 4.03
9254
9255 #include "json_spirit_value.h"
9256
9257 #include <cassert>
9258 #include <sstream>
9259 #include <iomanip>
9260
9261 namespace json_spirit
9262 {
9263 inline char to_hex_char( unsigned int c )
9264 {
9265 assert( c <= 0xF );
9266
9267 const char ch = static_cast< char >( c );
9268
9269 if( ch < 10 ) return '0' + ch;
9270
9271 return 'A' - 10 + ch;
9272 }
9273
9274 template< class String_type >
9275 String_type non_printable_to_string( unsigned int c )
9276 {
9277 typedef typename String_type::value_type Char_type;
9278
9279 String_type result( 6, '\\' );
9280
9281 result[1] = 'u';
9282
9283 result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4;
9284 result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4;
9285 result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4;
9286 result[ 2 ] = to_hex_char( c & 0x000F );
9287
9288 return result;
9289 }
9290
9291 template< typename Char_type, class String_type >
9292 bool add_esc_char( Char_type c, String_type& s )
9293 {
9294 switch( c )
9295 {
9296 case '"': s += to_str< String_type >( "\\\"" ); return true;
9297 case '\\': s += to_str< String_type >( "\\\\" ); return true;
9298 case '\b': s += to_str< String_type >( "\\b" ); return true;
9299 case '\f': s += to_str< String_type >( "\\f" ); return true;
9300 case '\n': s += to_str< String_type >( "\\n" ); return true;
9301 case '\r': s += to_str< String_type >( "\\r" ); return true;
9302 case '\t': s += to_str< String_type >( "\\t" ); return true;
9303 }
9304
9305 return false;
9306 }
9307
9308 template< class String_type >
9309 String_type add_esc_chars( const String_type& s )
9310 {
9311 typedef typename String_type::const_iterator Iter_type;
9312 typedef typename String_type::value_type Char_type;
9313
9314 String_type result;
9315
9316 const Iter_type end( s.end() );
9317
9318 for( Iter_type i = s.begin(); i != end; ++i )
9319 {
9320 const Char_type c( *i );
9321
9322 if( add_esc_char( c, result ) ) continue;
9323
9324 const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c );
9325
9326 if( iswprint( unsigned_c ) )
9327 {
9328 result += c;
9329 }
9330 else
9331 {
9332 result += non_printable_to_string< String_type >( unsigned_c );
9333 }
9334 }
9335
9336 return result;
9337 }
9338
9339 // this class generates the JSON text,
9340 // it keeps track of the indentation level etc.
9341 //
9342 template< class Value_type, class Ostream_type >
9343 class Generator
9344 {
9345 typedef typename Value_type::Config_type Config_type;
9346 typedef typename Config_type::String_type String_type;
9347 typedef typename Config_type::Object_type Object_type;
9348 typedef typename Config_type::Array_type Array_type;
9349 typedef typename String_type::value_type Char_type;
9350 typedef typename Object_type::value_type Obj_member_type;
9351
9352 public:
9353
9354 Generator( const Value_type& value, Ostream_type& os, bool pretty )
9355 : os_( os )
9356 , indentation_level_( 0 )
9357 , pretty_( pretty )
9358 {
9359 output( value );
9360 }
9361
9362 private:
9363
9364 void output( const Value_type& value )
9365 {
9366 switch( value.type() )
9367 {
9368 case obj_type: output( value.get_obj() ); break;
9369 case array_type: output( value.get_array() ); break;
9370 case str_type: output( value.get_str() ); break;
9371 case bool_type: output( value.get_bool() ); break;
9372 case int_type: output_int( value ); break;
9373
9374 /// Bitcoin: Added std::fixed and changed precision from 16 to 8
9375 case real_type: os_ << std::showpoint << std::fixed << std::setprecision(8)
9376 << value.get_real(); break;
9377
9378 case null_type: os_ << "null"; break;
9379 default: assert( false );
9380 }
9381 }
9382
9383 void output( const Object_type& obj )
9384 {
9385 output_array_or_obj( obj, '{', '}' );
9386 }
9387
9388 void output( const Array_type& arr )
9389 {
9390 output_array_or_obj( arr, '[', ']' );
9391 }
9392
9393 void output( const Obj_member_type& member )
9394 {
9395 output( Config_type::get_name( member ) ); space();
9396 os_ << ':'; space();
9397 output( Config_type::get_value( member ) );
9398 }
9399
9400 void output_int( const Value_type& value )
9401 {
9402 if( value.is_uint64() )
9403 {
9404 os_ << value.get_uint64();
9405 }
9406 else
9407 {
9408 os_ << value.get_int64();
9409 }
9410 }
9411
9412 void output( const String_type& s )
9413 {
9414 os_ << '"' << add_esc_chars( s ) << '"';
9415 }
9416
9417 void output( bool b )
9418 {
9419 os_ << to_str< String_type >( b ? "true" : "false" );
9420 }
9421
9422 template< class T >
9423 void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char )
9424 {
9425 os_ << start_char; new_line();
9426
9427 ++indentation_level_;
9428
9429 for( typename T::const_iterator i = t.begin(); i != t.end(); ++i )
9430 {
9431 indent(); output( *i );
9432
9433 typename T::const_iterator next = i;
9434
9435 if( ++next != t.end())
9436 {
9437 os_ << ',';
9438 }
9439
9440 new_line();
9441 }
9442
9443 --indentation_level_;
9444
9445 indent(); os_ << end_char;
9446 }
9447
9448 void indent()
9449 {
9450 if( !pretty_ ) return;
9451
9452 for( int i = 0; i < indentation_level_; ++i )
9453 {
9454 os_ << " ";
9455 }
9456 }
9457
9458 void space()
9459 {
9460 if( pretty_ ) os_ << ' ';
9461 }
9462
9463 void new_line()
9464 {
9465 if( pretty_ ) os_ << '\n';
9466 }
9467
9468 Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning
9469
9470 Ostream_type& os_;
9471 int indentation_level_;
9472 bool pretty_;
9473 };
9474
9475 template< class Value_type, class Ostream_type >
9476 void write_stream( const Value_type& value, Ostream_type& os, bool pretty )
9477 {
9478 Generator< Value_type, Ostream_type >( value, os, pretty );
9479 }
9480
9481 template< class Value_type >
9482 typename Value_type::String_type write_string( const Value_type& value, bool pretty )
9483 {
9484 typedef typename Value_type::String_type::value_type Char_type;
9485
9486 std::basic_ostringstream< Char_type > os;
9487
9488 write_stream( value, os, pretty );
9489
9490 return os.str();
9491 }
9492 }
9493
9494 #endif