json_spirit_reader_template.h 19 KB

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