1 #ifndef JSON_SPIRIT_READER_TEMPLATE
2 #define JSON_SPIRIT_READER_TEMPLATE
4 // Copyright John W. Wilkinson 2007 - 2011
5 // Distributed under the MIT License, see accompanying file LICENSE.txt
7 // json spirit version 4.05
9 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
13 #include "json_spirit_value.h"
14 #include "json_spirit_error_position.h"
16 #include "common/utf8.h"
18 #define BOOST_SPIRIT_THREADSAFE // uncomment for multithreaded use, requires linking to boost.thread
20 #include <boost/bind.hpp>
21 #include <boost/function.hpp>
22 #include <boost/version.hpp>
24 #if BOOST_VERSION >= 103800
25 #include <boost/spirit/include/classic_core.hpp>
26 #include <boost/spirit/include/classic_confix.hpp>
27 #include <boost/spirit/include/classic_escape_char.hpp>
28 #include <boost/spirit/include/classic_multi_pass.hpp>
29 #include <boost/spirit/include/classic_position_iterator.hpp>
30 #define spirit_namespace boost::spirit::classic
32 #include <boost/spirit/core.hpp>
33 #include <boost/spirit/utility/confix.hpp>
34 #include <boost/spirit/utility/escape_char.hpp>
35 #include <boost/spirit/iterator/multi_pass.hpp>
36 #include <boost/spirit/iterator/position_iterator.hpp>
37 #define spirit_namespace boost::spirit
42 const spirit_namespace::int_parser
< boost::int64_t > int64_p
= spirit_namespace::int_parser
< boost::int64_t >();
43 const spirit_namespace::uint_parser
< boost::uint64_t > uint64_p
= spirit_namespace::uint_parser
< boost::uint64_t >();
45 template< class Iter_type
>
46 bool is_eq( Iter_type first
, Iter_type last
, const char* c_str
)
48 for( Iter_type i
= first
; i
!= last
; ++i
, ++c_str
)
50 if( *c_str
== 0 ) return false;
52 if( *i
!= *c_str
) return false;
58 template< class Char_type
>
59 Char_type
hex_to_num( const Char_type c
)
61 if( ( c
>= '0' ) && ( c
<= '9' ) ) return c
- '0';
62 if( ( c
>= 'a' ) && ( c
<= 'f' ) ) return c
- 'a' + 10;
63 if( ( c
>= 'A' ) && ( c
<= 'F' ) ) return c
- 'A' + 10;
67 template< class Char_type
, class Iter_type
>
68 Char_type
hex_str_to_char( Iter_type
& begin
)
70 const Char_type
c1( *( ++begin
) );
71 const Char_type
c2( *( ++begin
) );
73 return ( hex_to_num( c1
) << 4 ) + hex_to_num( c2
);
76 template< class String_type
, class Iter_type
>
77 String_type
unicode_str_to_utf8( Iter_type
& begin
);
80 std::string
unicode_str_to_utf8( std::string::const_iterator
& begin
)
82 typedef std::string::value_type Char_type
;
84 const Char_type
c1( *( ++begin
) );
85 const Char_type
c2( *( ++begin
) );
86 const Char_type
c3( *( ++begin
) );
87 const Char_type
c4( *( ++begin
) );
89 unsigned long uc
= ( hex_to_num( c1
) << 12 ) +
90 ( hex_to_num( c2
) << 8 ) +
91 ( hex_to_num( c3
) << 4 ) +
94 unsigned char buf
[7]; // MAX_UTF8_SZ is 6 (see src/common/utf8.c)
95 int r
= encode_utf8(uc
, buf
);
97 return std::string(reinterpret_cast<char *>(buf
), r
);
99 return std::string("_");
102 template< class String_type
>
103 void append_esc_char_and_incr_iter( String_type
& s
,
104 typename
String_type::const_iterator
& begin
,
105 typename
String_type::const_iterator end
)
107 typedef typename
String_type::value_type Char_type
;
109 const Char_type
c2( *begin
);
113 case 't': s
+= '\t'; break;
114 case 'b': s
+= '\b'; break;
115 case 'f': s
+= '\f'; break;
116 case 'n': s
+= '\n'; break;
117 case 'r': s
+= '\r'; break;
118 case '\\': s
+= '\\'; break;
119 case '/': s
+= '/'; break;
120 case '"': s
+= '"'; break;
123 if( end
- begin
>= 3 ) // expecting "xHH..."
125 s
+= hex_str_to_char
< Char_type
>( begin
);
131 if( end
- begin
>= 5 ) // expecting "uHHHH..."
133 s
+= unicode_str_to_utf8
< String_type
>( begin
);
140 template< class String_type
>
141 String_type
substitute_esc_chars( typename
String_type::const_iterator begin
,
142 typename
String_type::const_iterator end
)
144 typedef typename
String_type::const_iterator Iter_type
;
146 if( end
- begin
< 2 ) return String_type( begin
, end
);
150 result
.reserve( end
- begin
);
152 const Iter_type
end_minus_1( end
- 1 );
154 Iter_type substr_start
= begin
;
157 for( ; i
< end_minus_1
; ++i
)
161 result
.append( substr_start
, i
);
165 append_esc_char_and_incr_iter( result
, i
, end
);
167 substr_start
= i
+ 1;
171 result
.append( substr_start
, end
);
176 template< class String_type
>
177 String_type
get_str_( typename
String_type::const_iterator begin
,
178 typename
String_type::const_iterator end
)
180 assert( end
- begin
>= 2 );
182 typedef typename
String_type::const_iterator Iter_type
;
184 Iter_type
str_without_quotes( ++begin
);
185 Iter_type
end_without_quotes( --end
);
187 return substitute_esc_chars
< String_type
>( str_without_quotes
, end_without_quotes
);
190 inline std::string
get_str( std::string::const_iterator begin
, std::string::const_iterator end
)
192 return get_str_
< std::string
>( begin
, end
);
195 // Need this guard else it tries to instantiate unicode_str_to_utf8 with a
196 // std::wstring, which isn't presently implemented
197 #if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING )
198 inline std::wstring
get_str( std::wstring::const_iterator begin
, std::wstring::const_iterator end
)
200 return get_str_
< std::wstring
>( begin
, end
);
204 template< class String_type
, class Iter_type
>
205 String_type
get_str( Iter_type begin
, Iter_type end
)
207 const String_type
tmp( begin
, end
); // convert multipass iterators to string iterators
209 return get_str( tmp
.begin(), tmp
.end() );
212 // this class's methods get called by the spirit parse resulting
213 // in the creation of a JSON object or array
215 // NB Iter_type could be a std::string iterator, wstring iterator, a position iterator or a multipass iterator
217 template< class Value_type
, class Iter_type
>
218 class Semantic_actions
222 typedef typename
Value_type::Config_type Config_type
;
223 typedef typename
Config_type::String_type String_type
;
224 typedef typename
Config_type::Object_type Object_type
;
225 typedef typename
Config_type::Array_type Array_type
;
226 typedef typename
String_type::value_type Char_type
;
228 Semantic_actions( Value_type
& value
)
234 void begin_obj( Char_type c
)
238 begin_compound
< Object_type
>();
241 void end_obj( Char_type c
)
248 void begin_array( Char_type c
)
252 begin_compound
< Array_type
>();
255 void end_array( Char_type c
)
262 void new_name( Iter_type begin
, Iter_type end
)
264 assert( current_p_
->type() == obj_type
);
266 name_
= get_str
< String_type
>( begin
, end
);
269 void new_str( Iter_type begin
, Iter_type end
)
271 add_to_current( get_str
< String_type
>( begin
, end
) );
274 void new_true( Iter_type begin
, Iter_type end
)
276 assert( is_eq( begin
, end
, "true" ) );
278 add_to_current( true );
281 void new_false( Iter_type begin
, Iter_type end
)
283 assert( is_eq( begin
, end
, "false" ) );
285 add_to_current( false );
288 void new_null( Iter_type begin
, Iter_type end
)
290 assert( is_eq( begin
, end
, "null" ) );
292 add_to_current( Value_type() );
295 void new_int( boost::int64_t i
)
300 void new_uint64( boost::uint64_t ui
)
302 add_to_current( ui
);
305 void new_real( double d
)
312 Semantic_actions
& operator=( const Semantic_actions
& );
313 // to prevent "assignment operator could not be generated" warning
315 Value_type
* add_first( const Value_type
& value
)
317 assert( current_p_
== 0 );
320 current_p_
= &value_
;
324 template< class Array_or_obj
>
325 void begin_compound()
327 if( current_p_
== 0 )
329 add_first( Array_or_obj() );
333 stack_
.push_back( current_p_
);
335 Array_or_obj new_array_or_obj
; // avoid copy by building new array or object in place
337 current_p_
= add_to_current( new_array_or_obj
);
343 if( current_p_
!= &value_
)
345 current_p_
= stack_
.back();
351 Value_type
* add_to_current( const Value_type
& value
)
353 if( current_p_
== 0 )
355 return add_first( value
);
357 else if( current_p_
->type() == array_type
)
359 current_p_
->get_array().push_back( value
);
361 return ¤t_p_
->get_array().back();
364 assert( current_p_
->type() == obj_type
);
366 return &Config_type::add( current_p_
->get_obj(), name_
, value
);
369 Value_type
& value_
; // this is the object or array that is being created
370 Value_type
* current_p_
; // the child object or array that is currently being constructed
372 std::vector
< Value_type
* > stack_
; // previous child objects and arrays
374 String_type name_
; // of current name/value pair
377 template< typename Iter_type
>
378 void throw_error( spirit_namespace::position_iterator
< Iter_type
> i
, const std::string
& reason
)
380 throw Error_position( i
.get_position().line
, i
.get_position().column
, reason
);
383 template< typename Iter_type
>
384 void throw_error( Iter_type i
, const std::string
& reason
)
389 // the spirit grammer
391 template< class Value_type
, class Iter_type
>
392 class Json_grammer
: public spirit_namespace::grammar
< Json_grammer
< Value_type
, Iter_type
> >
396 typedef Semantic_actions
< Value_type
, Iter_type
> Semantic_actions_t
;
398 Json_grammer( Semantic_actions_t
& semantic_actions
)
399 : actions_( semantic_actions
)
403 static void throw_not_value( Iter_type begin
, Iter_type end
)
405 throw_error( begin
, "not a value" );
408 static void throw_not_array( Iter_type begin
, Iter_type end
)
410 throw_error( begin
, "not an array" );
413 static void throw_not_object( Iter_type begin
, Iter_type end
)
415 throw_error( begin
, "not an object" );
418 static void throw_not_pair( Iter_type begin
, Iter_type end
)
420 throw_error( begin
, "not a pair" );
423 static void throw_not_colon( Iter_type begin
, Iter_type end
)
425 throw_error( begin
, "no colon in pair" );
428 static void throw_not_string( Iter_type begin
, Iter_type end
)
430 throw_error( begin
, "not a string" );
433 template< typename ScannerT
>
438 definition( const Json_grammer
& self
)
440 using namespace spirit_namespace
;
442 typedef typename
Value_type::String_type::value_type Char_type
;
444 // first we convert the semantic action class methods to functors with the
445 // parameter signature expected by spirit
447 typedef boost::function
< void( Char_type
) > Char_action
;
448 typedef boost::function
< void( Iter_type
, Iter_type
) > Str_action
;
449 typedef boost::function
< void( double ) > Real_action
;
450 typedef boost::function
< void( boost::int64_t ) > Int_action
;
451 typedef boost::function
< void( boost::uint64_t ) > Uint64_action
;
453 Char_action
begin_obj ( boost::bind( &Semantic_actions_t::begin_obj
, &self
.actions_
, _1
) );
454 Char_action
end_obj ( boost::bind( &Semantic_actions_t::end_obj
, &self
.actions_
, _1
) );
455 Char_action
begin_array( boost::bind( &Semantic_actions_t::begin_array
, &self
.actions_
, _1
) );
456 Char_action
end_array ( boost::bind( &Semantic_actions_t::end_array
, &self
.actions_
, _1
) );
457 Str_action
new_name ( boost::bind( &Semantic_actions_t::new_name
, &self
.actions_
, _1
, _2
) );
458 Str_action
new_str ( boost::bind( &Semantic_actions_t::new_str
, &self
.actions_
, _1
, _2
) );
459 Str_action
new_true ( boost::bind( &Semantic_actions_t::new_true
, &self
.actions_
, _1
, _2
) );
460 Str_action
new_false ( boost::bind( &Semantic_actions_t::new_false
, &self
.actions_
, _1
, _2
) );
461 Str_action
new_null ( boost::bind( &Semantic_actions_t::new_null
, &self
.actions_
, _1
, _2
) );
462 Real_action
new_real ( boost::bind( &Semantic_actions_t::new_real
, &self
.actions_
, _1
) );
463 Int_action
new_int ( boost::bind( &Semantic_actions_t::new_int
, &self
.actions_
, _1
) );
464 Uint64_action
new_uint64 ( boost::bind( &Semantic_actions_t::new_uint64
, &self
.actions_
, _1
) );
469 = value_
| eps_p
[ &throw_not_value
]
477 | str_p( "true" ) [ new_true
]
478 | str_p( "false" )[ new_false
]
479 | str_p( "null" ) [ new_null
]
483 = ch_p('{')[ begin_obj
]
485 >> ( ch_p('}')[ end_obj
] | eps_p
[ &throw_not_object
] )
489 = pair_
>> *( ',' >> pair_
| ch_p(',') )
493 = string_
[ new_name
]
494 >> ( ':' | eps_p
[ &throw_not_colon
] )
495 >> ( value_
| eps_p
[ &throw_not_value
] )
499 = ch_p('[')[ begin_array
]
501 >> ( ch_p(']')[ end_array
] | eps_p
[ &throw_not_array
] )
505 = value_
>> *( ',' >> value_
| ch_p(',') )
509 = lexeme_d
// this causes white space inside a string to be retained
521 = strict_real_p
[ new_real
]
522 | int64_p
[ new_int
]
523 | uint64_p
[ new_uint64
]
527 spirit_namespace::rule
< ScannerT
> json_
, object_
, members_
, pair_
, array_
, elements_
, value_
, string_
, number_
;
529 const spirit_namespace::rule
< ScannerT
>& start() const { return json_
; }
534 Json_grammer
& operator=( const Json_grammer
& ); // to prevent "assignment operator could not be generated" warning
536 Semantic_actions_t
& actions_
;
539 template< class Iter_type
, class Value_type
>
540 void add_posn_iter_and_read_range_or_throw( Iter_type begin
, Iter_type end
, Value_type
& value
)
542 typedef spirit_namespace::position_iterator
< Iter_type
> Posn_iter_t
;
544 const Posn_iter_t
posn_begin( begin
, end
);
545 const Posn_iter_t
posn_end( end
, end
);
547 read_range_or_throw( posn_begin
, posn_end
, value
);
550 template< class Istream_type
>
551 struct Multi_pass_iters
553 typedef typename
Istream_type::char_type Char_type
;
554 typedef std::istream_iterator
< Char_type
, Char_type
> istream_iter
;
555 typedef spirit_namespace::multi_pass
< istream_iter
> Mp_iter
;
557 Multi_pass_iters( Istream_type
& is
)
559 is
.unsetf( std::ios::skipws
);
561 begin_
= spirit_namespace::make_multi_pass( istream_iter( is
) );
562 end_
= spirit_namespace::make_multi_pass( istream_iter() );
569 // reads a JSON Value from a pair of input iterators throwing an exception on invalid input, e.g.
571 // string::const_iterator start = str.begin();
572 // const string::const_iterator next = read_range_or_throw( str.begin(), str.end(), value );
574 // The iterator 'next' will point to the character past the
577 template< class Iter_type
, class Value_type
>
578 Iter_type
read_range_or_throw( Iter_type begin
, Iter_type end
, Value_type
& value
)
580 Semantic_actions
< Value_type
, Iter_type
> semantic_actions( value
);
582 const spirit_namespace::parse_info
< Iter_type
> info
=
583 spirit_namespace::parse( begin
, end
,
584 Json_grammer
< Value_type
, Iter_type
>( semantic_actions
),
585 spirit_namespace::space_p
);
589 assert( false ); // in theory exception should already have been thrown
590 throw_error( info
.stop
, "error" );
596 // reads a JSON Value from a pair of input iterators, e.g.
598 // string::const_iterator start = str.begin();
599 // const bool success = read_string( start, str.end(), value );
601 // The iterator 'start' will point to the character past the
604 template< class Iter_type
, class Value_type
>
605 bool read_range( Iter_type
& begin
, Iter_type end
, Value_type
& value
)
609 begin
= read_range_or_throw( begin
, end
, value
);
619 // reads a JSON Value from a string, e.g.
621 // const bool success = read_string( str, value );
623 template< class String_type
, class Value_type
>
624 bool read_string( const String_type
& s
, Value_type
& value
)
626 typename
String_type::const_iterator begin
= s
.begin();
628 return read_range( begin
, s
.end(), value
);
631 // reads a JSON Value from a string throwing an exception on invalid input, e.g.
633 // read_string_or_throw( is, value );
635 template< class String_type
, class Value_type
>
636 void read_string_or_throw( const String_type
& s
, Value_type
& value
)
638 add_posn_iter_and_read_range_or_throw( s
.begin(), s
.end(), value
);
641 // reads a JSON Value from a stream, e.g.
643 // const bool success = read_stream( is, value );
645 template< class Istream_type
, class Value_type
>
646 bool read_stream( Istream_type
& is
, Value_type
& value
)
648 Multi_pass_iters
< Istream_type
> mp_iters( is
);
650 return read_range( mp_iters
.begin_
, mp_iters
.end_
, value
);
653 // reads a JSON Value from a stream throwing an exception on invalid input, e.g.
655 // read_stream_or_throw( is, value );
657 template< class Istream_type
, class Value_type
>
658 void read_stream_or_throw( Istream_type
& is
, Value_type
& value
)
660 const Multi_pass_iters
< Istream_type
> mp_iters( is
);
662 add_posn_iter_and_read_range_or_throw( mp_iters
.begin_
, mp_iters
.end_
, value
);