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