-
+ 075843B80107FE24C8100BA93C9ED3CE8EFF7D711064599A89AB8BF9F771A9A7B9A874960EAC98C36FA2E4D76A5D76BB630F03D651DDF4FF0391876066927E21
bitcoin/src/json/json_spirit_writer_template.h
(0 . 0)(1 . 248)
8317 #ifndef JSON_SPIRIT_WRITER_TEMPLATE
8318 #define JSON_SPIRIT_WRITER_TEMPLATE
8319
8320 // Copyright John W. Wilkinson 2007 - 2009.
8321 // Distributed under the MIT License, see accompanying file LICENSE.txt
8322
8323 // json spirit version 4.03
8324
8325 #include "json_spirit_value.h"
8326
8327 #include <cassert>
8328 #include <sstream>
8329 #include <iomanip>
8330
8331 namespace json_spirit
8332 {
8333 inline char to_hex_char( unsigned int c )
8334 {
8335 assert( c <= 0xF );
8336
8337 const char ch = static_cast< char >( c );
8338
8339 if( ch < 10 ) return '0' + ch;
8340
8341 return 'A' - 10 + ch;
8342 }
8343
8344 template< class String_type >
8345 String_type non_printable_to_string( unsigned int c )
8346 {
8347 typedef typename String_type::value_type Char_type;
8348
8349 String_type result( 6, '\\' );
8350
8351 result[1] = 'u';
8352
8353 result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4;
8354 result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4;
8355 result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4;
8356 result[ 2 ] = to_hex_char( c & 0x000F );
8357
8358 return result;
8359 }
8360
8361 template< typename Char_type, class String_type >
8362 bool add_esc_char( Char_type c, String_type& s )
8363 {
8364 switch( c )
8365 {
8366 case '"': s += to_str< String_type >( "\\\"" ); return true;
8367 case '\\': s += to_str< String_type >( "\\\\" ); return true;
8368 case '\b': s += to_str< String_type >( "\\b" ); return true;
8369 case '\f': s += to_str< String_type >( "\\f" ); return true;
8370 case '\n': s += to_str< String_type >( "\\n" ); return true;
8371 case '\r': s += to_str< String_type >( "\\r" ); return true;
8372 case '\t': s += to_str< String_type >( "\\t" ); return true;
8373 }
8374
8375 return false;
8376 }
8377
8378 template< class String_type >
8379 String_type add_esc_chars( const String_type& s )
8380 {
8381 typedef typename String_type::const_iterator Iter_type;
8382 typedef typename String_type::value_type Char_type;
8383
8384 String_type result;
8385
8386 const Iter_type end( s.end() );
8387
8388 for( Iter_type i = s.begin(); i != end; ++i )
8389 {
8390 const Char_type c( *i );
8391
8392 if( add_esc_char( c, result ) ) continue;
8393
8394 const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c );
8395
8396 if( iswprint( unsigned_c ) )
8397 {
8398 result += c;
8399 }
8400 else
8401 {
8402 result += non_printable_to_string< String_type >( unsigned_c );
8403 }
8404 }
8405
8406 return result;
8407 }
8408
8409 // this class generates the JSON text,
8410 // it keeps track of the indentation level etc.
8411 //
8412 template< class Value_type, class Ostream_type >
8413 class Generator
8414 {
8415 typedef typename Value_type::Config_type Config_type;
8416 typedef typename Config_type::String_type String_type;
8417 typedef typename Config_type::Object_type Object_type;
8418 typedef typename Config_type::Array_type Array_type;
8419 typedef typename String_type::value_type Char_type;
8420 typedef typename Object_type::value_type Obj_member_type;
8421
8422 public:
8423
8424 Generator( const Value_type& value, Ostream_type& os, bool pretty )
8425 : os_( os )
8426 , indentation_level_( 0 )
8427 , pretty_( pretty )
8428 {
8429 output( value );
8430 }
8431
8432 private:
8433
8434 void output( const Value_type& value )
8435 {
8436 switch( value.type() )
8437 {
8438 case obj_type: output( value.get_obj() ); break;
8439 case array_type: output( value.get_array() ); break;
8440 case str_type: output( value.get_str() ); break;
8441 case bool_type: output( value.get_bool() ); break;
8442 case int_type: output_int( value ); break;
8443
8444 /// Bitcoin: Added std::fixed and changed precision from 16 to 8
8445 case real_type: os_ << std::showpoint << std::fixed << std::setprecision(8)
8446 << value.get_real(); break;
8447
8448 case null_type: os_ << "null"; break;
8449 default: assert( false );
8450 }
8451 }
8452
8453 void output( const Object_type& obj )
8454 {
8455 output_array_or_obj( obj, '{', '}' );
8456 }
8457
8458 void output( const Array_type& arr )
8459 {
8460 output_array_or_obj( arr, '[', ']' );
8461 }
8462
8463 void output( const Obj_member_type& member )
8464 {
8465 output( Config_type::get_name( member ) ); space();
8466 os_ << ':'; space();
8467 output( Config_type::get_value( member ) );
8468 }
8469
8470 void output_int( const Value_type& value )
8471 {
8472 if( value.is_uint64() )
8473 {
8474 os_ << value.get_uint64();
8475 }
8476 else
8477 {
8478 os_ << value.get_int64();
8479 }
8480 }
8481
8482 void output( const String_type& s )
8483 {
8484 os_ << '"' << add_esc_chars( s ) << '"';
8485 }
8486
8487 void output( bool b )
8488 {
8489 os_ << to_str< String_type >( b ? "true" : "false" );
8490 }
8491
8492 template< class T >
8493 void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char )
8494 {
8495 os_ << start_char; new_line();
8496
8497 ++indentation_level_;
8498
8499 for( typename T::const_iterator i = t.begin(); i != t.end(); ++i )
8500 {
8501 indent(); output( *i );
8502
8503 typename T::const_iterator next = i;
8504
8505 if( ++next != t.end())
8506 {
8507 os_ << ',';
8508 }
8509
8510 new_line();
8511 }
8512
8513 --indentation_level_;
8514
8515 indent(); os_ << end_char;
8516 }
8517
8518 void indent()
8519 {
8520 if( !pretty_ ) return;
8521
8522 for( int i = 0; i < indentation_level_; ++i )
8523 {
8524 os_ << " ";
8525 }
8526 }
8527
8528 void space()
8529 {
8530 if( pretty_ ) os_ << ' ';
8531 }
8532
8533 void new_line()
8534 {
8535 if( pretty_ ) os_ << '\n';
8536 }
8537
8538 Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning
8539
8540 Ostream_type& os_;
8541 int indentation_level_;
8542 bool pretty_;
8543 };
8544
8545 template< class Value_type, class Ostream_type >
8546 void write_stream( const Value_type& value, Ostream_type& os, bool pretty )
8547 {
8548 Generator< Value_type, Ostream_type >( value, os, pretty );
8549 }
8550
8551 template< class Value_type >
8552 typename Value_type::String_type write_string( const Value_type& value, bool pretty )
8553 {
8554 typedef typename Value_type::String_type::value_type Char_type;
8555
8556 std::basic_ostringstream< Char_type > os;
8557
8558 write_stream( value, os, pretty );
8559
8560 return os.str();
8561 }
8562 }
8563
8564 #endif