Projects : bitcoin : bitcoin_dumpblock_no_losers

bitcoin/src/json/json_spirit_writer_template.h

Dir - Raw

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
15namespace 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