uint.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2011 Bryce Lelbach
  4. Copyright (c) 2011 Jan Frederick Eick
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. ==============================================================================*/
  8. #if !defined(SPIRIT_UINT_APR_17_2006_0901AM)
  9. #define SPIRIT_UINT_APR_17_2006_0901AM
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/spirit/home/qi/skip_over.hpp>
  14. #include <boost/spirit/home/qi/detail/enable_lit.hpp>
  15. #include <boost/spirit/home/qi/numeric/numeric_utils.hpp>
  16. #include <boost/spirit/home/qi/meta_compiler.hpp>
  17. #include <boost/spirit/home/qi/parser.hpp>
  18. #include <boost/spirit/home/support/common_terminals.hpp>
  19. #include <boost/spirit/home/support/info.hpp>
  20. #include <boost/spirit/home/support/detail/is_spirit_tag.hpp>
  21. #include <boost/mpl/assert.hpp>
  22. #include <boost/type_traits/is_same.hpp>
  23. namespace boost { namespace spirit
  24. {
  25. namespace tag
  26. {
  27. template <typename T, unsigned Radix, unsigned MinDigits
  28. , int MaxDigits>
  29. struct uint_parser
  30. {
  31. BOOST_SPIRIT_IS_TAG()
  32. };
  33. }
  34. namespace qi
  35. {
  36. ///////////////////////////////////////////////////////////////////////
  37. // This one is the class that the user can instantiate directly in
  38. // order to create a customized int parser
  39. template <typename T = int, unsigned Radix = 10, unsigned MinDigits = 1
  40. , int MaxDigits = -1>
  41. struct uint_parser
  42. : spirit::terminal<tag::uint_parser<T, Radix, MinDigits, MaxDigits> >
  43. {};
  44. }
  45. ///////////////////////////////////////////////////////////////////////////
  46. // Enablers
  47. ///////////////////////////////////////////////////////////////////////////
  48. template <> // enables ushort_
  49. struct use_terminal<qi::domain, tag::ushort_> : mpl::true_ {};
  50. template <typename A0> // enables lit(n)
  51. struct use_terminal<qi::domain
  52. , terminal_ex<tag::lit, fusion::vector1<A0> >
  53. , typename enable_if<is_same<A0, unsigned short> >::type>
  54. : mpl::true_ {};
  55. template <typename A0> // enables ushort_(n)
  56. struct use_terminal<qi::domain
  57. , terminal_ex<tag::ushort_, fusion::vector1<A0> > >
  58. : is_arithmetic<A0> {};
  59. template <> // enables *lazy* ushort_(n)
  60. struct use_lazy_terminal<qi::domain, tag::ushort_, 1> : mpl::true_ {};
  61. ///////////////////////////////////////////////////////////////////////////
  62. template <> // enables uint_
  63. struct use_terminal<qi::domain, tag::uint_> : mpl::true_ {};
  64. template <typename A0> // enables lit(n)
  65. struct use_terminal<qi::domain
  66. , terminal_ex<tag::lit, fusion::vector1<A0> >
  67. , typename enable_if<is_same<A0, unsigned> >::type>
  68. : mpl::true_ {};
  69. template <typename A0> // enables uint_(n)
  70. struct use_terminal<qi::domain
  71. , terminal_ex<tag::uint_, fusion::vector1<A0> > >
  72. : is_arithmetic<A0> {};
  73. template <> // enables *lazy* uint_(n)
  74. struct use_lazy_terminal<qi::domain, tag::uint_, 1> : mpl::true_ {};
  75. ///////////////////////////////////////////////////////////////////////////
  76. template <> // enables ulong_
  77. struct use_terminal<qi::domain, tag::ulong_> : mpl::true_ {};
  78. template <typename A0> // enables lit(n)
  79. struct use_terminal<qi::domain
  80. , terminal_ex<tag::lit, fusion::vector1<A0> >
  81. , typename enable_if<is_same<A0, unsigned long> >::type>
  82. : mpl::true_ {};
  83. template <typename A0> // enables ulong_(n)
  84. struct use_terminal<qi::domain
  85. , terminal_ex<tag::ulong_, fusion::vector1<A0> > >
  86. : is_arithmetic<A0> {};
  87. template <> // enables *lazy* ulong_(n)
  88. struct use_lazy_terminal<qi::domain, tag::ulong_, 1> : mpl::true_ {};
  89. ///////////////////////////////////////////////////////////////////////////
  90. #ifdef BOOST_HAS_LONG_LONG
  91. template <> // enables ulong_long
  92. struct use_terminal<qi::domain, tag::ulong_long> : mpl::true_ {};
  93. template <typename A0> // enables lit(n)
  94. struct use_terminal<qi::domain
  95. , terminal_ex<tag::lit, fusion::vector1<A0> >
  96. , typename enable_if<is_same<A0, boost::ulong_long_type> >::type>
  97. : mpl::true_ {};
  98. template <typename A0> // enables ulong_long(n)
  99. struct use_terminal<qi::domain
  100. , terminal_ex<tag::ulong_long, fusion::vector1<A0> > >
  101. : is_arithmetic<A0> {};
  102. template <> // enables *lazy* ulong_long(n)
  103. struct use_lazy_terminal<qi::domain, tag::ulong_long, 1> : mpl::true_ {};
  104. #endif
  105. ///////////////////////////////////////////////////////////////////////////
  106. template <> // enables bin
  107. struct use_terminal<qi::domain, tag::bin> : mpl::true_ {};
  108. template <typename A0> // enables bin(n)
  109. struct use_terminal<qi::domain
  110. , terminal_ex<tag::bin, fusion::vector1<A0> > >
  111. : is_arithmetic<A0> {};
  112. template <> // enables *lazy* bin(n)
  113. struct use_lazy_terminal<qi::domain, tag::bin, 1> : mpl::true_ {};
  114. ///////////////////////////////////////////////////////////////////////////
  115. template <> // enables oct
  116. struct use_terminal<qi::domain, tag::oct> : mpl::true_ {};
  117. template <typename A0> // enables oct(n)
  118. struct use_terminal<qi::domain
  119. , terminal_ex<tag::oct, fusion::vector1<A0> > >
  120. : is_arithmetic<A0> {};
  121. template <> // enables *lazy* oct(n)
  122. struct use_lazy_terminal<qi::domain, tag::oct, 1> : mpl::true_ {};
  123. ///////////////////////////////////////////////////////////////////////////
  124. template <> // enables hex
  125. struct use_terminal<qi::domain, tag::hex> : mpl::true_ {};
  126. template <typename A0> // enables hex(n)
  127. struct use_terminal<qi::domain
  128. , terminal_ex<tag::hex, fusion::vector1<A0> > >
  129. : is_arithmetic<A0> {};
  130. template <> // enables *lazy* hex(n)
  131. struct use_lazy_terminal<qi::domain, tag::hex, 1> : mpl::true_ {};
  132. ///////////////////////////////////////////////////////////////////////////
  133. // enables any custom uint_parser
  134. template <typename T, unsigned Radix, unsigned MinDigits
  135. , int MaxDigits>
  136. struct use_terminal<qi::domain
  137. , tag::uint_parser<T, Radix, MinDigits, MaxDigits> >
  138. : mpl::true_ {};
  139. // enables any custom uint_parser(n)
  140. template <typename T, unsigned Radix, unsigned MinDigits
  141. , int MaxDigits, typename A0>
  142. struct use_terminal<qi::domain
  143. , terminal_ex<tag::uint_parser<T, Radix, MinDigits, MaxDigits>
  144. , fusion::vector1<A0> >
  145. > : mpl::true_ {};
  146. // enables *lazy* custom uint_parser(n)
  147. template <typename T, unsigned Radix, unsigned MinDigits
  148. , int MaxDigits>
  149. struct use_lazy_terminal<qi::domain
  150. , tag::uint_parser<T, Radix, MinDigits, MaxDigits>, 1
  151. > : mpl::true_ {};
  152. }}
  153. namespace boost { namespace spirit { namespace qi
  154. {
  155. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  156. using spirit::bin;
  157. using spirit::oct;
  158. using spirit::hex;
  159. using spirit::ushort_;
  160. using spirit::uint_;
  161. using spirit::ulong_;
  162. #ifdef BOOST_HAS_LONG_LONG
  163. using spirit::ulong_long;
  164. #endif
  165. using spirit::lit; // lit(1) is equivalent to 1
  166. #endif
  167. using spirit::bin_type;
  168. using spirit::oct_type;
  169. using spirit::hex_type;
  170. using spirit::ushort_type;
  171. using spirit::uint_type;
  172. using spirit::ulong_type;
  173. #ifdef BOOST_HAS_LONG_LONG
  174. using spirit::ulong_long_type;
  175. #endif
  176. using spirit::lit_type;
  177. ///////////////////////////////////////////////////////////////////////////
  178. // This is the actual uint parser
  179. ///////////////////////////////////////////////////////////////////////////
  180. template <typename T, unsigned Radix = 10, unsigned MinDigits = 1
  181. , int MaxDigits = -1>
  182. struct any_uint_parser
  183. : primitive_parser<any_uint_parser<T, Radix, MinDigits, MaxDigits> >
  184. {
  185. // check template parameter 'Radix' for validity
  186. BOOST_SPIRIT_ASSERT_MSG(
  187. Radix >= 2 && Radix <= 36,
  188. not_supported_radix, ());
  189. template <typename Context, typename Iterator>
  190. struct attribute
  191. {
  192. typedef T type;
  193. };
  194. template <typename Iterator, typename Context
  195. , typename Skipper, typename Attribute>
  196. bool parse(Iterator& first, Iterator const& last
  197. , Context& /*context*/, Skipper const& skipper
  198. , Attribute& attr_) const
  199. {
  200. typedef extract_uint<T, Radix, MinDigits, MaxDigits> extract;
  201. qi::skip_over(first, last, skipper);
  202. return extract::call(first, last, attr_);
  203. }
  204. template <typename Context>
  205. info what(Context& /*context*/) const
  206. {
  207. return info("unsigned-integer");
  208. }
  209. };
  210. //]
  211. template <typename T, unsigned Radix = 10, unsigned MinDigits = 1
  212. , int MaxDigits = -1, bool no_attribute = true>
  213. struct literal_uint_parser
  214. : primitive_parser<literal_uint_parser<T, Radix, MinDigits, MaxDigits
  215. , no_attribute> >
  216. {
  217. // check template parameter 'Radix' for validity
  218. BOOST_SPIRIT_ASSERT_MSG(
  219. Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
  220. not_supported_radix, ());
  221. template <typename Value>
  222. literal_uint_parser(Value const& n) : n_(n) {}
  223. template <typename Context, typename Iterator>
  224. struct attribute
  225. : mpl::if_c<no_attribute, unused_type, T>
  226. {};
  227. template <typename Iterator, typename Context
  228. , typename Skipper, typename Attribute>
  229. bool parse(Iterator& first, Iterator const& last
  230. , Context& /*context*/, Skipper const& skipper
  231. , Attribute& attr_param) const
  232. {
  233. typedef extract_uint<T, Radix, MinDigits, MaxDigits> extract;
  234. qi::skip_over(first, last, skipper);
  235. Iterator save = first;
  236. T attr_;
  237. if (extract::call(first, last, attr_) && (attr_ == n_))
  238. {
  239. traits::assign_to(attr_, attr_param);
  240. return true;
  241. }
  242. first = save;
  243. return false;
  244. }
  245. template <typename Context>
  246. info what(Context& /*context*/) const
  247. {
  248. return info("unsigned-integer");
  249. }
  250. T n_;
  251. };
  252. ///////////////////////////////////////////////////////////////////////////
  253. // Parser generators: make_xxx function (objects)
  254. ///////////////////////////////////////////////////////////////////////////
  255. template <typename T, unsigned Radix = 10, unsigned MinDigits = 1
  256. , int MaxDigits = -1>
  257. struct make_uint
  258. {
  259. typedef any_uint_parser<T, Radix, MinDigits, MaxDigits> result_type;
  260. result_type operator()(unused_type, unused_type) const
  261. {
  262. return result_type();
  263. }
  264. };
  265. template <typename T, unsigned Radix = 10, unsigned MinDigits = 1
  266. , int MaxDigits = -1>
  267. struct make_direct_uint
  268. {
  269. typedef literal_uint_parser<T, Radix, MinDigits, MaxDigits, false>
  270. result_type;
  271. template <typename Terminal>
  272. result_type operator()(Terminal const& term, unused_type) const
  273. {
  274. return result_type(fusion::at_c<0>(term.args));
  275. }
  276. };
  277. template <typename T, unsigned Radix = 10, unsigned MinDigits = 1
  278. , int MaxDigits = -1>
  279. struct make_literal_uint
  280. {
  281. typedef literal_uint_parser<T, Radix, MinDigits, MaxDigits> result_type;
  282. template <typename Terminal>
  283. result_type operator()(Terminal const& term, unused_type) const
  284. {
  285. return result_type(fusion::at_c<0>(term.args));
  286. }
  287. };
  288. ///////////////////////////////////////////////////////////////////////////
  289. template <typename Modifiers, typename A0>
  290. struct make_primitive<
  291. terminal_ex<tag::lit, fusion::vector1<A0> >
  292. , Modifiers, typename enable_if<is_same<A0, unsigned short> >::type>
  293. : make_literal_uint<unsigned short> {};
  294. template <typename Modifiers, typename A0>
  295. struct make_primitive<
  296. terminal_ex<tag::lit, fusion::vector1<A0> >
  297. , Modifiers, typename enable_if<is_same<A0, unsigned> >::type>
  298. : make_literal_uint<unsigned> {};
  299. template <typename Modifiers, typename A0>
  300. struct make_primitive<
  301. terminal_ex<tag::lit, fusion::vector1<A0> >
  302. , Modifiers, typename enable_if<is_same<A0, unsigned long> >::type>
  303. : make_literal_uint<unsigned long> {};
  304. #ifdef BOOST_HAS_LONG_LONG
  305. template <typename Modifiers, typename A0>
  306. struct make_primitive<
  307. terminal_ex<tag::lit, fusion::vector1<A0> >
  308. , Modifiers, typename enable_if<is_same<A0, boost::ulong_long_type> >::type>
  309. : make_literal_uint<boost::ulong_long_type> {};
  310. #endif
  311. ///////////////////////////////////////////////////////////////////////////
  312. template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits
  313. , typename Modifiers>
  314. struct make_primitive<
  315. tag::uint_parser<T, Radix, MinDigits, MaxDigits>
  316. , Modifiers>
  317. : make_uint<T, Radix, MinDigits, MaxDigits> {};
  318. template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits
  319. , typename A0, typename Modifiers>
  320. struct make_primitive<
  321. terminal_ex<tag::uint_parser<T, Radix, MinDigits, MaxDigits>
  322. , fusion::vector1<A0> >, Modifiers>
  323. : make_direct_uint<T, Radix, MinDigits, MaxDigits> {};
  324. ///////////////////////////////////////////////////////////////////////////
  325. template <typename Modifiers>
  326. struct make_primitive<tag::bin, Modifiers>
  327. : make_uint<unsigned, 2> {};
  328. template <typename Modifiers, typename A0>
  329. struct make_primitive<
  330. terminal_ex<tag::bin
  331. , fusion::vector1<A0> > , Modifiers>
  332. : make_direct_uint<unsigned, 2> {};
  333. ///////////////////////////////////////////////////////////////////////////
  334. template <typename Modifiers>
  335. struct make_primitive<tag::oct, Modifiers>
  336. : make_uint<unsigned, 8> {};
  337. template <typename Modifiers, typename A0>
  338. struct make_primitive<
  339. terminal_ex<tag::oct
  340. , fusion::vector1<A0> > , Modifiers>
  341. : make_direct_uint<unsigned, 8> {};
  342. ///////////////////////////////////////////////////////////////////////////
  343. template <typename Modifiers>
  344. struct make_primitive<tag::hex, Modifiers>
  345. : make_uint<unsigned, 16> {};
  346. template <typename Modifiers, typename A0>
  347. struct make_primitive<
  348. terminal_ex<tag::hex
  349. , fusion::vector1<A0> > , Modifiers>
  350. : make_direct_uint<unsigned, 16> {};
  351. ///////////////////////////////////////////////////////////////////////////
  352. template <typename Modifiers>
  353. struct make_primitive<tag::ushort_, Modifiers>
  354. : make_uint<unsigned short> {};
  355. template <typename Modifiers, typename A0>
  356. struct make_primitive<
  357. terminal_ex<tag::ushort_
  358. , fusion::vector1<A0> > , Modifiers>
  359. : make_direct_uint<unsigned short> {};
  360. ///////////////////////////////////////////////////////////////////////////
  361. template <typename Modifiers>
  362. struct make_primitive<tag::uint_, Modifiers>
  363. : make_uint<unsigned> {};
  364. template <typename Modifiers, typename A0>
  365. struct make_primitive<
  366. terminal_ex<tag::uint_
  367. , fusion::vector1<A0> > , Modifiers>
  368. : make_direct_uint<unsigned> {};
  369. ///////////////////////////////////////////////////////////////////////////
  370. template <typename Modifiers>
  371. struct make_primitive<tag::ulong_, Modifiers>
  372. : make_uint<unsigned long> {};
  373. template <typename Modifiers, typename A0>
  374. struct make_primitive<
  375. terminal_ex<tag::ulong_
  376. , fusion::vector1<A0> > , Modifiers>
  377. : make_direct_uint<unsigned long> {};
  378. ///////////////////////////////////////////////////////////////////////////
  379. #ifdef BOOST_HAS_LONG_LONG
  380. template <typename Modifiers>
  381. struct make_primitive<tag::ulong_long, Modifiers>
  382. : make_uint<boost::ulong_long_type> {};
  383. template <typename Modifiers, typename A0>
  384. struct make_primitive<
  385. terminal_ex<tag::ulong_long
  386. , fusion::vector1<A0> > , Modifiers>
  387. : make_direct_uint<boost::ulong_long_type> {};
  388. #endif
  389. }}}
  390. #endif