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 >
is_eq(Iter_type first,Iter_type last,const char * c_str)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 >
hex_to_num(const Char_type c)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 >
hex_str_to_char(Iter_type & begin)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 >
unicode_str_to_char(Iter_type & begin)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 >
append_esc_char_and_incr_iter(String_type & s,typename String_type::const_iterator & begin,typename String_type::const_iterator end)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 >
substitute_esc_chars(typename String_type::const_iterator begin,typename String_type::const_iterator end)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 >
get_str_(typename String_type::const_iterator begin,typename String_type::const_iterator end)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 
get_str(std::string::const_iterator begin,std::string::const_iterator end)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 
get_str(std::wstring::const_iterator begin,std::wstring::const_iterator end)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 >
get_str(Iter_type begin,Iter_type end)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 
Semantic_actions(Value_type & value)206         Semantic_actions( Value_type& value )
207         :   value_( value )
208         ,   current_p_( 0 )
209         {
210         }
211 
begin_obj(Char_type c)212         void begin_obj( Char_type c )
213         {
214             assert( c == '{' );
215 
216             begin_compound< Object_type >();
217         }
218 
end_obj(Char_type c)219         void end_obj( Char_type c )
220         {
221             assert( c == '}' );
222 
223             end_compound();
224         }
225 
begin_array(Char_type c)226         void begin_array( Char_type c )
227         {
228             assert( c == '[' );
229 
230             begin_compound< Array_type >();
231         }
232 
end_array(Char_type c)233         void end_array( Char_type c )
234         {
235             assert( c == ']' );
236 
237             end_compound();
238         }
239 
new_name(Iter_type begin,Iter_type end)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 
new_str(Iter_type begin,Iter_type end)247         void new_str( Iter_type begin, Iter_type end )
248         {
249             add_to_current( get_str< String_type >( begin, end ) );
250         }
251 
new_true(Iter_type begin,Iter_type end)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 
new_false(Iter_type begin,Iter_type end)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 
new_null(Iter_type begin,Iter_type end)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 
new_int(boost::int64_t i)273         void new_int( boost::int64_t i )
274         {
275             add_to_current( i );
276         }
277 
new_uint64(boost::uint64_t ui)278         void new_uint64( boost::uint64_t ui )
279         {
280             add_to_current( ui );
281         }
282 
new_real(double d)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 
add_first(const Value_type & value)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 >
begin_compound()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 
end_compound()319         void end_compound()
320         {
321             if( current_p_ != &value_ )
322             {
323                 current_p_ = stack_.back();
324 
325                 stack_.pop_back();
326             }
327         }
328 
add_to_current(const Value_type & value)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 &current_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 >
throw_error(spirit_namespace::position_iterator<Iter_type> i,const std::string & reason)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 >
throw_error(Iter_type i,const std::string & reason)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 
Json_grammer(Semantic_actions_t & semantic_actions)376         Json_grammer( Semantic_actions_t& semantic_actions )
377         :   actions_( semantic_actions )
378         {
379         }
380 
throw_not_value(Iter_type begin,Iter_type end)381         static void throw_not_value( Iter_type begin, Iter_type end )
382         {
383     	    throw_error( begin, "not a value" );
384         }
385 
throw_not_array(Iter_type begin,Iter_type end)386         static void throw_not_array( Iter_type begin, Iter_type end )
387         {
388     	    throw_error( begin, "not an array" );
389         }
390 
throw_not_object(Iter_type begin,Iter_type end)391         static void throw_not_object( Iter_type begin, Iter_type end )
392         {
393     	    throw_error( begin, "not an object" );
394         }
395 
throw_not_pair(Iter_type begin,Iter_type end)396         static void throw_not_pair( Iter_type begin, Iter_type end )
397         {
398     	    throw_error( begin, "not a pair" );
399         }
400 
throw_not_colon(Iter_type begin,Iter_type end)401         static void throw_not_colon( Iter_type begin, Iter_type end )
402         {
403     	    throw_error( begin, "no colon in pair" );
404         }
405 
throw_not_string(Iter_type begin,Iter_type end)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 
definition(const Json_grammer & self)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 
start()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 >
read_range_or_throw(Iter_type begin,Iter_type end,Value_type & value)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 >
add_posn_iter_and_read_range_or_throw(Iter_type begin,Iter_type end,Value_type & value)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 >
read_range(Iter_type & begin,Iter_type end,Value_type & value)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 >
read_string_or_throw(const String_type & s,Value_type & value)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 >
read_string(const String_type & s,Value_type & value)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 
Multi_pass_itersMulti_pass_iters583         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 >
read_stream(Istream_type & is,Value_type & value)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 >
read_stream_or_throw(Istream_type & is,Value_type & value)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
613