Back to home page

Bitcoin sources

 
 

    


File indexing completed on 2020-06-25 15:43:26

0001 #ifndef JSON_SPIRIT_WRITER_TEMPLATE
0002 #define JSON_SPIRIT_WRITER_TEMPLATE
0003 
0004 //          Copyright John W. Wilkinson 2007 - 2009.
0005 // Distributed under the MIT License, see accompanying file LICENSE.txt
0006 
0007 // json spirit version 4.03
0008 
0009 #include "json_spirit_value.h"
0010 
0011 #include <cassert>
0012 #include <sstream>
0013 #include <iomanip>
0014 
0015 namespace json_spirit
0016 {
0017     inline char to_hex_char( unsigned int c )
0018     {
0019         assert( c <= 0xF );
0020 
0021         const char ch = static_cast< char >( c );
0022 
0023         if( ch < 10 ) return '0' + ch;
0024 
0025         return 'A' - 10 + ch;
0026     }
0027 
0028     template< class String_type >
0029     String_type non_printable_to_string( unsigned int c )
0030     {
0031         typedef typename String_type::value_type Char_type;
0032 
0033         String_type result( 6, '\\' );
0034 
0035         result[1] = 'u';
0036 
0037         result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4;
0038         result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4;
0039         result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4;
0040         result[ 2 ] = to_hex_char( c & 0x000F );
0041 
0042         return result;
0043     }
0044 
0045     template< typename Char_type, class String_type >
0046     bool add_esc_char( Char_type c, String_type& s )
0047     {
0048         switch( c )
0049         {
0050             case '"':  s += to_str< String_type >( "\\\"" ); return true;
0051             case '\\': s += to_str< String_type >( "\\\\" ); return true;
0052             case '\b': s += to_str< String_type >( "\\b"  ); return true;
0053             case '\f': s += to_str< String_type >( "\\f"  ); return true;
0054             case '\n': s += to_str< String_type >( "\\n"  ); return true;
0055             case '\r': s += to_str< String_type >( "\\r"  ); return true;
0056             case '\t': s += to_str< String_type >( "\\t"  ); return true;
0057         }
0058 
0059         return false;
0060     }
0061 
0062     template< class String_type >
0063     String_type add_esc_chars( const String_type& s )
0064     {
0065         typedef typename String_type::const_iterator Iter_type;
0066         typedef typename String_type::value_type     Char_type;
0067 
0068         String_type result;
0069 
0070         const Iter_type end( s.end() );
0071 
0072         for( Iter_type i = s.begin(); i != end; ++i )
0073         {
0074             const Char_type c( *i );
0075 
0076             if( add_esc_char( c, result ) ) continue;
0077 
0078             const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c );
0079 
0080             if( iswprint( unsigned_c ) )
0081             {
0082                 result += c;
0083             }
0084             else
0085             {
0086                 result += non_printable_to_string< String_type >( unsigned_c );
0087             }
0088         }
0089 
0090         return result;
0091     }
0092 
0093     // this class generates the JSON text,
0094     // it keeps track of the indentation level etc.
0095     //
0096     template< class Value_type, class Ostream_type >
0097     class Generator
0098     {
0099         typedef typename Value_type::Config_type Config_type;
0100         typedef typename Config_type::String_type String_type;
0101         typedef typename Config_type::Object_type Object_type;
0102         typedef typename Config_type::Array_type Array_type;
0103         typedef typename String_type::value_type Char_type;
0104         typedef typename Object_type::value_type Obj_member_type;
0105 
0106     public:
0107 
0108         Generator( const Value_type& value, Ostream_type& os, bool pretty )
0109         :   os_( os )
0110         ,   indentation_level_( 0 )
0111         ,   pretty_( pretty )
0112         {
0113             output( value );
0114         }
0115 
0116     private:
0117 
0118         void output( const Value_type& value )
0119         {
0120             switch( value.type() )
0121             {
0122                 case obj_type:   output( value.get_obj() );   break;
0123                 case array_type: output( value.get_array() ); break;
0124                 case str_type:   output( value.get_str() );   break;
0125                 case bool_type:  output( value.get_bool() );  break;
0126                 case int_type:   output_int( value );         break;
0127 
0128                 /// Bitcoin: Added std::fixed and changed precision from 16 to 8
0129                 case real_type:  os_ << std::showpoint << std::fixed << std::setprecision(8)
0130                                      << value.get_real();     break;
0131 
0132                 case null_type:  os_ << "null";               break;
0133                 default: assert( false );
0134             }
0135         }
0136 
0137         void output( const Object_type& obj )
0138         {
0139             output_array_or_obj( obj, '{', '}' );
0140         }
0141 
0142         void output( const Array_type& arr )
0143         {
0144             output_array_or_obj( arr, '[', ']' );
0145         }
0146 
0147         void output( const Obj_member_type& member )
0148         {
0149             output( Config_type::get_name( member ) ); space(); 
0150             os_ << ':'; space(); 
0151             output( Config_type::get_value( member ) );
0152         }
0153 
0154         void output_int( const Value_type& value )
0155         {
0156             if( value.is_uint64() )
0157             {
0158                 os_ << value.get_uint64();
0159             }
0160             else
0161             {
0162                os_ << value.get_int64();
0163             }
0164         }
0165 
0166         void output( const String_type& s )
0167         {
0168             os_ << '"' << add_esc_chars( s ) << '"';
0169         }
0170 
0171         void output( bool b )
0172         {
0173             os_ << to_str< String_type >( b ? "true" : "false" );
0174         }
0175 
0176         template< class T >
0177         void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char )
0178         {
0179             os_ << start_char; new_line();
0180 
0181             ++indentation_level_;
0182             
0183             for( typename T::const_iterator i = t.begin(); i != t.end(); ++i )
0184             {
0185                 indent(); output( *i );
0186 
0187                 typename T::const_iterator next = i;
0188 
0189                 if( ++next != t.end())
0190                 {
0191                     os_ << ',';
0192                 }
0193 
0194                 new_line();
0195             }
0196 
0197             --indentation_level_;
0198 
0199             indent(); os_ << end_char;
0200         }
0201         
0202         void indent()
0203         {
0204             if( !pretty_ ) return;
0205 
0206             for( int i = 0; i < indentation_level_; ++i )
0207             { 
0208                 os_ << "    ";
0209             }
0210         }
0211 
0212         void space()
0213         {
0214             if( pretty_ ) os_ << ' ';
0215         }
0216 
0217         void new_line()
0218         {
0219             if( pretty_ ) os_ << '\n';
0220         }
0221 
0222         Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning
0223 
0224         Ostream_type& os_;
0225         int indentation_level_;
0226         bool pretty_;
0227     };
0228 
0229     template< class Value_type, class Ostream_type >
0230     void write_stream( const Value_type& value, Ostream_type& os, bool pretty )
0231     {
0232         Generator< Value_type, Ostream_type >( value, os, pretty );
0233     }
0234 
0235     template< class Value_type >
0236     typename Value_type::String_type write_string( const Value_type& value, bool pretty )
0237     {
0238         typedef typename Value_type::String_type::value_type Char_type;
0239 
0240         std::basic_ostringstream< Char_type > os;
0241 
0242         write_stream( value, os, pretty );
0243 
0244         return os.str();
0245     }
0246 }
0247 
0248 #endif