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