Projects : bitcoin : bitcoin_dumpblock_no_losers
1 | #ifndef JSON_SPIRIT_READER_TEMPLATE |
2 | #define JSON_SPIRIT_READER_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 | #include "json_spirit_error_position.h" |
11 | |
12 | //#define BOOST_SPIRIT_THREADSAFE // uncomment for multithreaded use, requires linking to boost.thread |
13 | |
14 | #include <boost/bind.hpp> |
15 | #include <boost/function.hpp> |
16 | #include <boost/version.hpp> |
17 | |
18 | #if BOOST_VERSION >= 103800 |
19 | #include <boost/spirit/include/classic_core.hpp> |
20 | #include <boost/spirit/include/classic_confix.hpp> |
21 | #include <boost/spirit/include/classic_escape_char.hpp> |
22 | #include <boost/spirit/include/classic_multi_pass.hpp> |
23 | #include <boost/spirit/include/classic_position_iterator.hpp> |
24 | #define spirit_namespace boost::spirit::classic |
25 | #else |
26 | #include <boost/spirit/core.hpp> |
27 | #include <boost/spirit/utility/confix.hpp> |
28 | #include <boost/spirit/utility/escape_char.hpp> |
29 | #include <boost/spirit/iterator/multi_pass.hpp> |
30 | #include <boost/spirit/iterator/position_iterator.hpp> |
31 | #define spirit_namespace boost::spirit |
32 | #endif |
33 | |
34 | namespace json_spirit |
35 | { |
36 | const spirit_namespace::int_parser < boost::int64_t > int64_p = spirit_namespace::int_parser < boost::int64_t >(); |
37 | const spirit_namespace::uint_parser< boost::uint64_t > uint64_p = spirit_namespace::uint_parser< boost::uint64_t >(); |
38 | |
39 | template< class Iter_type > |
40 | bool is_eq( Iter_type first, Iter_type last, const char* c_str ) |
41 | { |
42 | for( Iter_type i = first; i != last; ++i, ++c_str ) |
43 | { |
44 | if( *c_str == 0 ) return false; |
45 | |
46 | if( *i != *c_str ) return false; |
47 | } |
48 | |
49 | return true; |
50 | } |
51 | |
52 | template< class Char_type > |
53 | Char_type hex_to_num( const Char_type c ) |
54 | { |
55 | if( ( c >= '0' ) && ( c <= '9' ) ) return c - '0'; |
56 | if( ( c >= 'a' ) && ( c <= 'f' ) ) return c - 'a' + 10; |
57 | if( ( c >= 'A' ) && ( c <= 'F' ) ) return c - 'A' + 10; |
58 | return 0; |
59 | } |
60 | |
61 | template< class Char_type, class Iter_type > |
62 | Char_type hex_str_to_char( Iter_type& begin ) |
63 | { |
64 | const Char_type c1( *( ++begin ) ); |
65 | const Char_type c2( *( ++begin ) ); |
66 | |
67 | return ( hex_to_num( c1 ) << 4 ) + hex_to_num( c2 ); |
68 | } |
69 | |
70 | template< class Char_type, class Iter_type > |
71 | Char_type unicode_str_to_char( Iter_type& begin ) |
72 | { |
73 | const Char_type c1( *( ++begin ) ); |
74 | const Char_type c2( *( ++begin ) ); |
75 | const Char_type c3( *( ++begin ) ); |
76 | const Char_type c4( *( ++begin ) ); |
77 | |
78 | return ( hex_to_num( c1 ) << 12 ) + |
79 | ( hex_to_num( c2 ) << 8 ) + |
80 | ( hex_to_num( c3 ) << 4 ) + |
81 | hex_to_num( c4 ); |
82 | } |
83 | |
84 | template< class String_type > |
85 | void append_esc_char_and_incr_iter( String_type& s, |
86 | typename String_type::const_iterator& begin, |
87 | typename String_type::const_iterator end ) |
88 | { |
89 | typedef typename String_type::value_type Char_type; |
90 | |
91 | const Char_type c2( *begin ); |
92 | |
93 | switch( c2 ) |
94 | { |
95 | case 't': s += '\t'; break; |
96 | case 'b': s += '\b'; break; |
97 | case 'f': s += '\f'; break; |
98 | case 'n': s += '\n'; break; |
99 | case 'r': s += '\r'; break; |
100 | case '\\': s += '\\'; break; |
101 | case '/': s += '/'; break; |
102 | case '"': s += '"'; break; |
103 | case 'x': |
104 | { |
105 | if( end - begin >= 3 ) // expecting "xHH..." |
106 | { |
107 | s += hex_str_to_char< Char_type >( begin ); |
108 | } |
109 | break; |
110 | } |
111 | case 'u': |
112 | { |
113 | if( end - begin >= 5 ) // expecting "uHHHH..." |
114 | { |
115 | s += unicode_str_to_char< Char_type >( begin ); |
116 | } |
117 | break; |
118 | } |
119 | } |
120 | } |
121 | |
122 | template< class String_type > |
123 | String_type substitute_esc_chars( typename String_type::const_iterator begin, |
124 | typename String_type::const_iterator end ) |
125 | { |
126 | typedef typename String_type::const_iterator Iter_type; |
127 | |
128 | if( end - begin < 2 ) return String_type( begin, end ); |
129 | |
130 | String_type result; |
131 | |
132 | result.reserve( end - begin ); |
133 | |
134 | const Iter_type end_minus_1( end - 1 ); |
135 | |
136 | Iter_type substr_start = begin; |
137 | Iter_type i = begin; |
138 | |
139 | for( ; i < end_minus_1; ++i ) |
140 | { |
141 | if( *i == '\\' ) |
142 | { |
143 | result.append( substr_start, i ); |
144 | |
145 | ++i; // skip the '\' |
146 | |
147 | append_esc_char_and_incr_iter( result, i, end ); |
148 | |
149 | substr_start = i + 1; |
150 | } |
151 | } |
152 | |
153 | result.append( substr_start, end ); |
154 | |
155 | return result; |
156 | } |
157 | |
158 | template< class String_type > |
159 | String_type get_str_( typename String_type::const_iterator begin, |
160 | typename String_type::const_iterator end ) |
161 | { |
162 | assert( end - begin >= 2 ); |
163 | |
164 | typedef typename String_type::const_iterator Iter_type; |
165 | |
166 | Iter_type str_without_quotes( ++begin ); |
167 | Iter_type end_without_quotes( --end ); |
168 | |
169 | return substitute_esc_chars< String_type >( str_without_quotes, end_without_quotes ); |
170 | } |
171 | |
172 | inline std::string get_str( std::string::const_iterator begin, std::string::const_iterator end ) |
173 | { |
174 | return get_str_< std::string >( begin, end ); |
175 | } |
176 | |
177 | inline std::wstring get_str( std::wstring::const_iterator begin, std::wstring::const_iterator end ) |
178 | { |
179 | return get_str_< std::wstring >( begin, end ); |
180 | } |
181 | |
182 | template< class String_type, class Iter_type > |
183 | String_type get_str( Iter_type begin, Iter_type end ) |
184 | { |
185 | const String_type tmp( begin, end ); // convert multipass iterators to string iterators |
186 | |
187 | return get_str( tmp.begin(), tmp.end() ); |
188 | } |
189 | |
190 | // this class's methods get called by the spirit parse resulting |
191 | // in the creation of a JSON object or array |
192 | // |
193 | // NB Iter_type could be a std::string iterator, wstring iterator, a position iterator or a multipass iterator |
194 | // |
195 | template< class Value_type, class Iter_type > |
196 | class Semantic_actions |
197 | { |
198 | public: |
199 | |
200 | typedef typename Value_type::Config_type Config_type; |
201 | typedef typename Config_type::String_type String_type; |
202 | typedef typename Config_type::Object_type Object_type; |
203 | typedef typename Config_type::Array_type Array_type; |
204 | typedef typename String_type::value_type Char_type; |
205 | |
206 | Semantic_actions( Value_type& value ) |
207 | : value_( value ) |
208 | , current_p_( 0 ) |
209 | { |
210 | } |
211 | |
212 | void begin_obj( Char_type c ) |
213 | { |
214 | assert( c == '{' ); |
215 | |
216 | begin_compound< Object_type >(); |
217 | } |
218 | |
219 | void end_obj( Char_type c ) |
220 | { |
221 | assert( c == '}' ); |
222 | |
223 | end_compound(); |
224 | } |
225 | |
226 | void begin_array( Char_type c ) |
227 | { |
228 | assert( c == '[' ); |
229 | |
230 | begin_compound< Array_type >(); |
231 | } |
232 | |
233 | void end_array( Char_type c ) |
234 | { |
235 | assert( c == ']' ); |
236 | |
237 | end_compound(); |
238 | } |
239 | |
240 | void new_name( Iter_type begin, Iter_type end ) |
241 | { |
242 | assert( current_p_->type() == obj_type ); |
243 | |
244 | name_ = get_str< String_type >( begin, end ); |
245 | } |
246 | |
247 | void new_str( Iter_type begin, Iter_type end ) |
248 | { |
249 | add_to_current( get_str< String_type >( begin, end ) ); |
250 | } |
251 | |
252 | void new_true( Iter_type begin, Iter_type end ) |
253 | { |
254 | assert( is_eq( begin, end, "true" ) ); |
255 | |
256 | add_to_current( true ); |
257 | } |
258 | |
259 | void new_false( Iter_type begin, Iter_type end ) |
260 | { |
261 | assert( is_eq( begin, end, "false" ) ); |
262 | |
263 | add_to_current( false ); |
264 | } |
265 | |
266 | void new_null( Iter_type begin, Iter_type end ) |
267 | { |
268 | assert( is_eq( begin, end, "null" ) ); |
269 | |
270 | add_to_current( Value_type() ); |
271 | } |
272 | |
273 | void new_int( boost::int64_t i ) |
274 | { |
275 | add_to_current( i ); |
276 | } |
277 | |
278 | void new_uint64( boost::uint64_t ui ) |
279 | { |
280 | add_to_current( ui ); |
281 | } |
282 | |
283 | void new_real( double d ) |
284 | { |
285 | add_to_current( d ); |
286 | } |
287 | |
288 | private: |
289 | |
290 | Semantic_actions& operator=( const Semantic_actions& ); |
291 | // to prevent "assignment operator could not be generated" warning |
292 | |
293 | Value_type* add_first( const Value_type& value ) |
294 | { |
295 | assert( current_p_ == 0 ); |
296 | |
297 | value_ = value; |
298 | current_p_ = &value_; |
299 | return current_p_; |
300 | } |
301 | |
302 | template< class Array_or_obj > |
303 | void begin_compound() |
304 | { |
305 | if( current_p_ == 0 ) |
306 | { |
307 | add_first( Array_or_obj() ); |
308 | } |
309 | else |
310 | { |
311 | stack_.push_back( current_p_ ); |
312 | |
313 | Array_or_obj new_array_or_obj; // avoid copy by building new array or object in place |
314 | |
315 | current_p_ = add_to_current( new_array_or_obj ); |
316 | } |
317 | } |
318 | |
319 | void end_compound() |
320 | { |
321 | if( current_p_ != &value_ ) |
322 | { |
323 | current_p_ = stack_.back(); |
324 | |
325 | stack_.pop_back(); |
326 | } |
327 | } |
328 | |
329 | Value_type* add_to_current( const Value_type& value ) |
330 | { |
331 | if( current_p_ == 0 ) |
332 | { |
333 | return add_first( value ); |
334 | } |
335 | else if( current_p_->type() == array_type ) |
336 | { |
337 | current_p_->get_array().push_back( value ); |
338 | |
339 | return ¤t_p_->get_array().back(); |
340 | } |
341 | |
342 | assert( current_p_->type() == obj_type ); |
343 | |
344 | return &Config_type::add( current_p_->get_obj(), name_, value ); |
345 | } |
346 | |
347 | Value_type& value_; // this is the object or array that is being created |
348 | Value_type* current_p_; // the child object or array that is currently being constructed |
349 | |
350 | std::vector< Value_type* > stack_; // previous child objects and arrays |
351 | |
352 | String_type name_; // of current name/value pair |
353 | }; |
354 | |
355 | template< typename Iter_type > |
356 | void throw_error( spirit_namespace::position_iterator< Iter_type > i, const std::string& reason ) |
357 | { |
358 | throw Error_position( i.get_position().line, i.get_position().column, reason ); |
359 | } |
360 | |
361 | template< typename Iter_type > |
362 | void throw_error( Iter_type i, const std::string& reason ) |
363 | { |
364 | throw reason; |
365 | } |
366 | |
367 | // the spirit grammer |
368 | // |
369 | template< class Value_type, class Iter_type > |
370 | class Json_grammer : public spirit_namespace::grammar< Json_grammer< Value_type, Iter_type > > |
371 | { |
372 | public: |
373 | |
374 | typedef Semantic_actions< Value_type, Iter_type > Semantic_actions_t; |
375 | |
376 | Json_grammer( Semantic_actions_t& semantic_actions ) |
377 | : actions_( semantic_actions ) |
378 | { |
379 | } |
380 | |
381 | static void throw_not_value( Iter_type begin, Iter_type end ) |
382 | { |
383 | throw_error( begin, "not a value" ); |
384 | } |
385 | |
386 | static void throw_not_array( Iter_type begin, Iter_type end ) |
387 | { |
388 | throw_error( begin, "not an array" ); |
389 | } |
390 | |
391 | static void throw_not_object( Iter_type begin, Iter_type end ) |
392 | { |
393 | throw_error( begin, "not an object" ); |
394 | } |
395 | |
396 | static void throw_not_pair( Iter_type begin, Iter_type end ) |
397 | { |
398 | throw_error( begin, "not a pair" ); |
399 | } |
400 | |
401 | static void throw_not_colon( Iter_type begin, Iter_type end ) |
402 | { |
403 | throw_error( begin, "no colon in pair" ); |
404 | } |
405 | |
406 | static void throw_not_string( Iter_type begin, Iter_type end ) |
407 | { |
408 | throw_error( begin, "not a string" ); |
409 | } |
410 | |
411 | template< typename ScannerT > |
412 | class definition |
413 | { |
414 | public: |
415 | |
416 | definition( const Json_grammer& self ) |
417 | { |
418 | using namespace spirit_namespace; |
419 | |
420 | typedef typename Value_type::String_type::value_type Char_type; |
421 | |
422 | // first we convert the semantic action class methods to functors with the |
423 | // parameter signature expected by spirit |
424 | |
425 | typedef boost::function< void( Char_type ) > Char_action; |
426 | typedef boost::function< void( Iter_type, Iter_type ) > Str_action; |
427 | typedef boost::function< void( double ) > Real_action; |
428 | typedef boost::function< void( boost::int64_t ) > Int_action; |
429 | typedef boost::function< void( boost::uint64_t ) > Uint64_action; |
430 | |
431 | Char_action begin_obj ( boost::bind( &Semantic_actions_t::begin_obj, &self.actions_, _1 ) ); |
432 | Char_action end_obj ( boost::bind( &Semantic_actions_t::end_obj, &self.actions_, _1 ) ); |
433 | Char_action begin_array( boost::bind( &Semantic_actions_t::begin_array, &self.actions_, _1 ) ); |
434 | Char_action end_array ( boost::bind( &Semantic_actions_t::end_array, &self.actions_, _1 ) ); |
435 | Str_action new_name ( boost::bind( &Semantic_actions_t::new_name, &self.actions_, _1, _2 ) ); |
436 | Str_action new_str ( boost::bind( &Semantic_actions_t::new_str, &self.actions_, _1, _2 ) ); |
437 | Str_action new_true ( boost::bind( &Semantic_actions_t::new_true, &self.actions_, _1, _2 ) ); |
438 | Str_action new_false ( boost::bind( &Semantic_actions_t::new_false, &self.actions_, _1, _2 ) ); |
439 | Str_action new_null ( boost::bind( &Semantic_actions_t::new_null, &self.actions_, _1, _2 ) ); |
440 | Real_action new_real ( boost::bind( &Semantic_actions_t::new_real, &self.actions_, _1 ) ); |
441 | Int_action new_int ( boost::bind( &Semantic_actions_t::new_int, &self.actions_, _1 ) ); |
442 | Uint64_action new_uint64 ( boost::bind( &Semantic_actions_t::new_uint64, &self.actions_, _1 ) ); |
443 | |
444 | // actual grammer |
445 | |
446 | json_ |
447 | = value_ | eps_p[ &throw_not_value ] |
448 | ; |
449 | |
450 | value_ |
451 | = string_[ new_str ] |
452 | | number_ |
453 | | object_ |
454 | | array_ |
455 | | str_p( "true" ) [ new_true ] |
456 | | str_p( "false" )[ new_false ] |
457 | | str_p( "null" ) [ new_null ] |
458 | ; |
459 | |
460 | object_ |
461 | = ch_p('{')[ begin_obj ] |
462 | >> !members_ |
463 | >> ( ch_p('}')[ end_obj ] | eps_p[ &throw_not_object ] ) |
464 | ; |
465 | |
466 | members_ |
467 | = pair_ >> *( ',' >> pair_ ) |
468 | ; |
469 | |
470 | pair_ |
471 | = string_[ new_name ] |
472 | >> ( ':' | eps_p[ &throw_not_colon ] ) |
473 | >> ( value_ | eps_p[ &throw_not_value ] ) |
474 | ; |
475 | |
476 | array_ |
477 | = ch_p('[')[ begin_array ] |
478 | >> !elements_ |
479 | >> ( ch_p(']')[ end_array ] | eps_p[ &throw_not_array ] ) |
480 | ; |
481 | |
482 | elements_ |
483 | = value_ >> *( ',' >> value_ ) |
484 | ; |
485 | |
486 | string_ |
487 | = lexeme_d // this causes white space inside a string to be retained |
488 | [ |
489 | confix_p |
490 | ( |
491 | '"', |
492 | *lex_escape_ch_p, |
493 | '"' |
494 | ) |
495 | ] |
496 | ; |
497 | |
498 | number_ |
499 | = strict_real_p[ new_real ] |
500 | | int64_p [ new_int ] |
501 | | uint64_p [ new_uint64 ] |
502 | ; |
503 | } |
504 | |
505 | spirit_namespace::rule< ScannerT > json_, object_, members_, pair_, array_, elements_, value_, string_, number_; |
506 | |
507 | const spirit_namespace::rule< ScannerT >& start() const { return json_; } |
508 | }; |
509 | |
510 | private: |
511 | |
512 | Json_grammer& operator=( const Json_grammer& ); // to prevent "assignment operator could not be generated" warning |
513 | |
514 | Semantic_actions_t& actions_; |
515 | }; |
516 | |
517 | template< class Iter_type, class Value_type > |
518 | Iter_type read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value ) |
519 | { |
520 | Semantic_actions< Value_type, Iter_type > semantic_actions( value ); |
521 | |
522 | const spirit_namespace::parse_info< Iter_type > info = |
523 | spirit_namespace::parse( begin, end, |
524 | Json_grammer< Value_type, Iter_type >( semantic_actions ), |
525 | spirit_namespace::space_p ); |
526 | |
527 | if( !info.hit ) |
528 | { |
529 | assert( false ); // in theory exception should already have been thrown |
530 | throw_error( info.stop, "error" ); |
531 | } |
532 | |
533 | return info.stop; |
534 | } |
535 | |
536 | template< class Iter_type, class Value_type > |
537 | void add_posn_iter_and_read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value ) |
538 | { |
539 | typedef spirit_namespace::position_iterator< Iter_type > Posn_iter_t; |
540 | |
541 | const Posn_iter_t posn_begin( begin, end ); |
542 | const Posn_iter_t posn_end( end, end ); |
543 | |
544 | read_range_or_throw( posn_begin, posn_end, value ); |
545 | } |
546 | |
547 | template< class Iter_type, class Value_type > |
548 | bool read_range( Iter_type& begin, Iter_type end, Value_type& value ) |
549 | { |
550 | try |
551 | { |
552 | begin = read_range_or_throw( begin, end, value ); |
553 | |
554 | return true; |
555 | } |
556 | catch( ... ) |
557 | { |
558 | return false; |
559 | } |
560 | } |
561 | |
562 | template< class String_type, class Value_type > |
563 | void read_string_or_throw( const String_type& s, Value_type& value ) |
564 | { |
565 | add_posn_iter_and_read_range_or_throw( s.begin(), s.end(), value ); |
566 | } |
567 | |
568 | template< class String_type, class Value_type > |
569 | bool read_string( const String_type& s, Value_type& value ) |
570 | { |
571 | typename String_type::const_iterator begin = s.begin(); |
572 | |
573 | return read_range( begin, s.end(), value ); |
574 | } |
575 | |
576 | template< class Istream_type > |
577 | struct Multi_pass_iters |
578 | { |
579 | typedef typename Istream_type::char_type Char_type; |
580 | typedef std::istream_iterator< Char_type, Char_type > istream_iter; |
581 | typedef spirit_namespace::multi_pass< istream_iter > Mp_iter; |
582 | |
583 | Multi_pass_iters( Istream_type& is ) |
584 | { |
585 | is.unsetf( std::ios::skipws ); |
586 | |
587 | begin_ = spirit_namespace::make_multi_pass( istream_iter( is ) ); |
588 | end_ = spirit_namespace::make_multi_pass( istream_iter() ); |
589 | } |
590 | |
591 | Mp_iter begin_; |
592 | Mp_iter end_; |
593 | }; |
594 | |
595 | template< class Istream_type, class Value_type > |
596 | bool read_stream( Istream_type& is, Value_type& value ) |
597 | { |
598 | Multi_pass_iters< Istream_type > mp_iters( is ); |
599 | |
600 | return read_range( mp_iters.begin_, mp_iters.end_, value ); |
601 | } |
602 | |
603 | template< class Istream_type, class Value_type > |
604 | void read_stream_or_throw( Istream_type& is, Value_type& value ) |
605 | { |
606 | const Multi_pass_iters< Istream_type > mp_iters( is ); |
607 | |
608 | add_posn_iter_and_read_range_or_throw( mp_iters.begin_, mp_iters.end_, value ); |
609 | } |
610 | } |
611 | |
612 | #endif |