json_spirit_reader_template.h 19 KB

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