9
3

uint.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #if !defined(BOOST_SPIRIT_KARMA_UINT_FEB_23_2007_0840PM)
  6. #define BOOST_SPIRIT_KARMA_UINT_FEB_23_2007_0840PM
  7. #if defined(_MSC_VER)
  8. #pragma once
  9. #endif
  10. #include <boost/limits.hpp>
  11. #include <boost/config.hpp>
  12. #include <boost/mpl/bool.hpp>
  13. #include <boost/utility/enable_if.hpp>
  14. #include <boost/spirit/home/support/common_terminals.hpp>
  15. #include <boost/spirit/home/support/string_traits.hpp>
  16. #include <boost/spirit/home/support/numeric_traits.hpp>
  17. #include <boost/spirit/home/support/info.hpp>
  18. #include <boost/spirit/home/support/char_class.hpp>
  19. #include <boost/spirit/home/support/container.hpp>
  20. #include <boost/spirit/home/support/detail/get_encoding.hpp>
  21. #include <boost/spirit/home/support/detail/is_spirit_tag.hpp>
  22. #include <boost/spirit/home/karma/meta_compiler.hpp>
  23. #include <boost/spirit/home/karma/delimit_out.hpp>
  24. #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
  25. #include <boost/spirit/home/karma/detail/get_casetag.hpp>
  26. #include <boost/spirit/home/karma/detail/extract_from.hpp>
  27. #include <boost/spirit/home/karma/detail/enable_lit.hpp>
  28. #include <boost/spirit/home/karma/domain.hpp>
  29. #include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
  30. #include <boost/fusion/include/at.hpp>
  31. #include <boost/fusion/include/value_at.hpp>
  32. #include <boost/fusion/include/vector.hpp>
  33. namespace boost { namespace spirit
  34. {
  35. namespace tag
  36. {
  37. template <typename T, unsigned Radix>
  38. struct uint_generator
  39. {
  40. BOOST_SPIRIT_IS_TAG()
  41. };
  42. }
  43. namespace karma
  44. {
  45. ///////////////////////////////////////////////////////////////////////
  46. // This one is the class that the user can instantiate directly in
  47. // order to create a customized int generator
  48. template <typename T = unsigned int, unsigned Radix = 10>
  49. struct uint_generator
  50. : spirit::terminal<tag::uint_generator<T, Radix> >
  51. {};
  52. }
  53. ///////////////////////////////////////////////////////////////////////////
  54. // Enablers
  55. ///////////////////////////////////////////////////////////////////////////
  56. template <>
  57. struct use_terminal<karma::domain, tag::ushort_> // enables ushort_
  58. : mpl::true_ {};
  59. template <>
  60. struct use_terminal<karma::domain, tag::uint_> // enables uint_
  61. : mpl::true_ {};
  62. template <>
  63. struct use_terminal<karma::domain, tag::ulong_> // enables ulong_
  64. : mpl::true_ {};
  65. template <>
  66. struct use_terminal<karma::domain, tag::bin> // enables bin
  67. : mpl::true_ {};
  68. template <>
  69. struct use_terminal<karma::domain, tag::oct> // enables oct
  70. : mpl::true_ {};
  71. template <>
  72. struct use_terminal<karma::domain, tag::hex> // enables hex
  73. : mpl::true_ {};
  74. #ifdef BOOST_HAS_LONG_LONG
  75. template <>
  76. struct use_terminal<karma::domain, tag::ulong_long> // enables ulong_long
  77. : mpl::true_ {};
  78. #endif
  79. ///////////////////////////////////////////////////////////////////////////
  80. #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
  81. template <> // enables lit(unsigned short(0))
  82. struct use_terminal<karma::domain, unsigned short>
  83. : mpl::true_ {};
  84. #endif
  85. template <> // enables lit(0U)
  86. struct use_terminal<karma::domain, unsigned int>
  87. : mpl::true_ {};
  88. template <> // enables lit(0UL)
  89. struct use_terminal<karma::domain, unsigned long>
  90. : mpl::true_ {};
  91. #ifdef BOOST_HAS_LONG_LONG
  92. template <> // enables lit(0ULL)
  93. struct use_terminal<karma::domain, boost::ulong_long_type>
  94. : mpl::true_ {};
  95. #endif
  96. ///////////////////////////////////////////////////////////////////////////
  97. template <typename A0>
  98. struct use_terminal<karma::domain // enables ushort_(...)
  99. , terminal_ex<tag::ushort_, fusion::vector1<A0> >
  100. > : mpl::true_ {};
  101. template <typename A0>
  102. struct use_terminal<karma::domain // enables uint_(...)
  103. , terminal_ex<tag::uint_, fusion::vector1<A0> >
  104. > : mpl::true_ {};
  105. template <typename A0>
  106. struct use_terminal<karma::domain // enables ulong_(...)
  107. , terminal_ex<tag::ulong_, fusion::vector1<A0> >
  108. > : mpl::true_ {};
  109. template <typename A0>
  110. struct use_terminal<karma::domain // enables bin(...)
  111. , terminal_ex<tag::bin, fusion::vector1<A0> >
  112. > : mpl::true_ {};
  113. template <typename A0>
  114. struct use_terminal<karma::domain // enables oct(...)
  115. , terminal_ex<tag::oct, fusion::vector1<A0> >
  116. > : mpl::true_ {};
  117. template <typename A0>
  118. struct use_terminal<karma::domain // enables hex(...)
  119. , terminal_ex<tag::hex, fusion::vector1<A0> >
  120. > : mpl::true_ {};
  121. #ifdef BOOST_HAS_LONG_LONG
  122. template <typename A0>
  123. struct use_terminal<karma::domain // enables ulong_long(...)
  124. , terminal_ex<tag::ulong_long, fusion::vector1<A0> >
  125. > : mpl::true_ {};
  126. #endif
  127. ///////////////////////////////////////////////////////////////////////////
  128. template <> // enables *lazy* ushort_(...)
  129. struct use_lazy_terminal<karma::domain, tag::ushort_, 1>
  130. : mpl::true_ {};
  131. template <> // enables *lazy* uint_(...)
  132. struct use_lazy_terminal<karma::domain, tag::uint_, 1>
  133. : mpl::true_ {};
  134. template <> // enables *lazy* ulong_(...)
  135. struct use_lazy_terminal<karma::domain, tag::ulong_, 1>
  136. : mpl::true_ {};
  137. template <> // enables *lazy* bin(...)
  138. struct use_lazy_terminal<karma::domain, tag::bin, 1>
  139. : mpl::true_ {};
  140. template <> // enables *lazy* oct(...)
  141. struct use_lazy_terminal<karma::domain, tag::oct, 1>
  142. : mpl::true_ {};
  143. template <> // enables *lazy* hex(...)
  144. struct use_lazy_terminal<karma::domain, tag::hex, 1>
  145. : mpl::true_ {};
  146. #ifdef BOOST_HAS_LONG_LONG
  147. template <> // enables *lazy* ulong_long(...)
  148. struct use_lazy_terminal<karma::domain, tag::ulong_long, 1>
  149. : mpl::true_ {};
  150. #endif
  151. ///////////////////////////////////////////////////////////////////////////
  152. // enables any custom uint_generator
  153. template <typename T, unsigned Radix>
  154. struct use_terminal<karma::domain, tag::uint_generator<T, Radix> >
  155. : mpl::true_ {};
  156. // enables any custom uint_generator(...)
  157. template <typename T, unsigned Radix, typename A0>
  158. struct use_terminal<karma::domain
  159. , terminal_ex<tag::uint_generator<T, Radix>, fusion::vector1<A0> >
  160. > : mpl::true_ {};
  161. // enables *lazy* custom uint_generator
  162. template <typename T, unsigned Radix>
  163. struct use_lazy_terminal<
  164. karma::domain
  165. , tag::uint_generator<T, Radix>
  166. , 1 // arity
  167. > : mpl::true_ {};
  168. // enables lit(uint)
  169. template <typename A0>
  170. struct use_terminal<karma::domain
  171. , terminal_ex<tag::lit, fusion::vector1<A0> >
  172. , typename enable_if<traits::is_uint<A0> >::type>
  173. : mpl::true_ {};
  174. }}
  175. ///////////////////////////////////////////////////////////////////////////////
  176. namespace boost { namespace spirit { namespace karma
  177. {
  178. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  179. using spirit::ushort_;
  180. using spirit::uint_;
  181. using spirit::ulong_;
  182. #ifdef BOOST_HAS_LONG_LONG
  183. using spirit::ulong_long;
  184. #endif
  185. using spirit::bin;
  186. using spirit::oct;
  187. using spirit::hex;
  188. using spirit::lit; // lit(1U) is equivalent to 1U
  189. #endif
  190. using spirit::ushort_type;
  191. using spirit::uint_type;
  192. using spirit::ulong_type;
  193. #ifdef BOOST_HAS_LONG_LONG
  194. using spirit::ulong_long_type;
  195. #endif
  196. using spirit::bin_type;
  197. using spirit::oct_type;
  198. using spirit::hex_type;
  199. using spirit::lit_type;
  200. ///////////////////////////////////////////////////////////////////////////
  201. // This specialization is used for unsigned int generators not having a
  202. // direct initializer: uint_, ulong_ etc. These generators must be used in
  203. // conjunction with an Attribute.
  204. ///////////////////////////////////////////////////////////////////////////
  205. template <typename T, typename CharEncoding, typename Tag, unsigned Radix>
  206. struct any_uint_generator
  207. : primitive_generator<any_uint_generator<T, CharEncoding, Tag, Radix> >
  208. {
  209. template <typename Context, typename Unused>
  210. struct attribute
  211. {
  212. typedef T type;
  213. };
  214. // check template Attribute 'Radix' for validity
  215. BOOST_SPIRIT_ASSERT_MSG(
  216. Radix >= 2 && Radix <= 36, not_supported_radix, ());
  217. BOOST_SPIRIT_ASSERT_MSG(
  218. // the following is a workaround for STLPort, where the simpler
  219. // `!std::numeric_limits<T>::is_signed` wouldn't compile
  220. mpl::not_<mpl::bool_<std::numeric_limits<T>::is_signed> >::value,
  221. signed_unsigned_mismatch, ());
  222. // int has a Attribute attached
  223. template <typename OutputIterator, typename Context, typename Delimiter
  224. , typename Attribute>
  225. static bool
  226. generate(OutputIterator& sink, Context& context, Delimiter const& d
  227. , Attribute const& attr)
  228. {
  229. if (!traits::has_optional_value(attr))
  230. return false; // fail if it's an uninitialized optional
  231. return uint_inserter<Radix, CharEncoding, Tag>::
  232. call(sink, traits::extract_from<T>(attr, context)) &&
  233. delimit_out(sink, d); // always do post-delimiting
  234. }
  235. // this int has no Attribute attached, it needs to have been
  236. // initialized from a direct literal
  237. template <typename OutputIterator, typename Context, typename Delimiter>
  238. static bool
  239. generate(OutputIterator&, Context&, Delimiter const&, unused_type)
  240. {
  241. // It is not possible (doesn't make sense) to use numeric generators
  242. // without providing any attribute, as the generator doesn't 'know'
  243. // what to output. The following assertion fires if this situation
  244. // is detected in your code.
  245. BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, uint_not_usable_without_attribute, ());
  246. return false;
  247. }
  248. template <typename Context>
  249. static info what(Context const& /*context*/)
  250. {
  251. return info("unsigned-integer");
  252. }
  253. };
  254. ///////////////////////////////////////////////////////////////////////////
  255. // This specialization is used for unsigned int generators having a direct
  256. // initializer: uint_(10), ulong_(20) etc.
  257. ///////////////////////////////////////////////////////////////////////////
  258. template <
  259. typename T, typename CharEncoding, typename Tag, unsigned Radix
  260. , bool no_attribute>
  261. struct literal_uint_generator
  262. : primitive_generator<literal_uint_generator<T, CharEncoding, Tag, Radix
  263. , no_attribute> >
  264. {
  265. template <typename Context, typename Unused = unused_type>
  266. struct attribute
  267. : mpl::if_c<no_attribute, unused_type, T>
  268. {};
  269. literal_uint_generator(typename add_const<T>::type n)
  270. : n_(n) {}
  271. // check template Attribute 'Radix' for validity
  272. BOOST_SPIRIT_ASSERT_MSG(
  273. Radix >= 2 && Radix <= 36, not_supported_radix, ());
  274. BOOST_SPIRIT_ASSERT_MSG(
  275. // the following is a workaround for STLPort, where the simpler
  276. // `!std::numeric_limits<T>::is_signed wouldn't` compile
  277. mpl::not_<mpl::bool_<std::numeric_limits<T>::is_signed> >::value,
  278. signed_unsigned_mismatch, ());
  279. // A uint(1U) which additionally has an associated attribute emits
  280. // its immediate literal only if it matches the attribute, otherwise
  281. // it fails.
  282. template <typename OutputIterator, typename Context, typename Delimiter
  283. , typename Attribute>
  284. bool generate(OutputIterator& sink, Context& context
  285. , Delimiter const& d, Attribute const& attr) const
  286. {
  287. typedef typename attribute<Context>::type attribute_type;
  288. if (!traits::has_optional_value(attr) ||
  289. n_ != traits::extract_from<attribute_type>(attr, context))
  290. {
  291. return false;
  292. }
  293. return uint_inserter<Radix, CharEncoding, Tag>::call(sink, n_) &&
  294. delimit_out(sink, d); // always do post-delimiting
  295. }
  296. // A uint(1U) without any associated attribute just emits its
  297. // immediate literal
  298. template <typename OutputIterator, typename Context, typename Delimiter>
  299. bool generate(OutputIterator& sink, Context&, Delimiter const& d
  300. , unused_type) const
  301. {
  302. return uint_inserter<Radix, CharEncoding, Tag>::call(sink, n_) &&
  303. delimit_out(sink, d); // always do post-delimiting
  304. }
  305. template <typename Context>
  306. static info what(Context const& /*context*/)
  307. {
  308. return info("unsigned-integer");
  309. }
  310. T n_;
  311. };
  312. ///////////////////////////////////////////////////////////////////////////
  313. // Generator generators: make_xxx function (objects)
  314. ///////////////////////////////////////////////////////////////////////////
  315. namespace detail
  316. {
  317. template <typename T, typename Modifiers, unsigned Radix = 10>
  318. struct make_uint
  319. {
  320. static bool const lower =
  321. has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
  322. static bool const upper =
  323. has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
  324. typedef any_uint_generator<
  325. T
  326. , typename spirit::detail::get_encoding_with_case<
  327. Modifiers, unused_type, lower || upper>::type
  328. , typename detail::get_casetag<Modifiers, lower || upper>::type
  329. , Radix
  330. > result_type;
  331. result_type operator()(unused_type, unused_type) const
  332. {
  333. return result_type();
  334. }
  335. };
  336. }
  337. ///////////////////////////////////////////////////////////////////////////
  338. template <typename Modifiers>
  339. struct make_primitive<tag::ushort_, Modifiers>
  340. : detail::make_uint<unsigned short, Modifiers> {};
  341. template <typename Modifiers>
  342. struct make_primitive<tag::uint_, Modifiers>
  343. : detail::make_uint<unsigned int, Modifiers> {};
  344. template <typename Modifiers>
  345. struct make_primitive<tag::ulong_, Modifiers>
  346. : detail::make_uint<unsigned long, Modifiers> {};
  347. template <typename Modifiers>
  348. struct make_primitive<tag::bin, Modifiers>
  349. : detail::make_uint<unsigned, Modifiers, 2> {};
  350. template <typename Modifiers>
  351. struct make_primitive<tag::oct, Modifiers>
  352. : detail::make_uint<unsigned, Modifiers, 8> {};
  353. template <typename Modifiers>
  354. struct make_primitive<tag::hex, Modifiers>
  355. : detail::make_uint<unsigned, Modifiers, 16> {};
  356. #ifdef BOOST_HAS_LONG_LONG
  357. template <typename Modifiers>
  358. struct make_primitive<tag::ulong_long, Modifiers>
  359. : detail::make_uint<boost::ulong_long_type, Modifiers> {};
  360. #endif
  361. template <typename T, unsigned Radix, typename Modifiers>
  362. struct make_primitive<tag::uint_generator<T, Radix>, Modifiers>
  363. : detail::make_uint<typename remove_const<T>::type, Modifiers, Radix> {};
  364. ///////////////////////////////////////////////////////////////////////////
  365. namespace detail
  366. {
  367. template <typename T, typename Modifiers, unsigned Radix = 10>
  368. struct make_uint_direct
  369. {
  370. static bool const lower =
  371. has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
  372. static bool const upper =
  373. has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
  374. typedef literal_uint_generator<
  375. T
  376. , typename spirit::detail::get_encoding_with_case<
  377. Modifiers, unused_type, lower || upper>::type
  378. , typename detail::get_casetag<Modifiers, lower || upper>::type
  379. , Radix, false
  380. > result_type;
  381. template <typename Terminal>
  382. result_type operator()(Terminal const& term, unused_type) const
  383. {
  384. return result_type(fusion::at_c<0>(term.args));
  385. }
  386. };
  387. }
  388. template <typename Modifiers, typename A0>
  389. struct make_primitive<
  390. terminal_ex<tag::ushort_, fusion::vector1<A0> >, Modifiers>
  391. : detail::make_uint_direct<unsigned short, Modifiers> {};
  392. template <typename Modifiers, typename A0>
  393. struct make_primitive<
  394. terminal_ex<tag::uint_, fusion::vector1<A0> >, Modifiers>
  395. : detail::make_uint_direct<unsigned int, Modifiers> {};
  396. template <typename Modifiers, typename A0>
  397. struct make_primitive<
  398. terminal_ex<tag::ulong_, fusion::vector1<A0> >, Modifiers>
  399. : detail::make_uint_direct<unsigned long, Modifiers> {};
  400. template <typename Modifiers, typename A0>
  401. struct make_primitive<
  402. terminal_ex<tag::bin, fusion::vector1<A0> >, Modifiers>
  403. : detail::make_uint_direct<unsigned, Modifiers, 2> {};
  404. template <typename Modifiers, typename A0>
  405. struct make_primitive<
  406. terminal_ex<tag::oct, fusion::vector1<A0> >, Modifiers>
  407. : detail::make_uint_direct<unsigned, Modifiers, 8> {};
  408. template <typename Modifiers, typename A0>
  409. struct make_primitive<
  410. terminal_ex<tag::hex, fusion::vector1<A0> >, Modifiers>
  411. : detail::make_uint_direct<unsigned, Modifiers, 16> {};
  412. #ifdef BOOST_HAS_LONG_LONG
  413. template <typename Modifiers, typename A0>
  414. struct make_primitive<
  415. terminal_ex<tag::ulong_long, fusion::vector1<A0> >, Modifiers>
  416. : detail::make_uint_direct<boost::ulong_long_type, Modifiers> {};
  417. #endif
  418. template <typename T, unsigned Radix, typename A0, typename Modifiers>
  419. struct make_primitive<
  420. terminal_ex<tag::uint_generator<T, Radix>, fusion::vector1<A0> >
  421. , Modifiers>
  422. : detail::make_uint_direct<typename remove_const<T>::type, Modifiers, Radix>
  423. {};
  424. ///////////////////////////////////////////////////////////////////////////
  425. namespace detail
  426. {
  427. template <typename T, typename Modifiers>
  428. struct basic_uint_literal
  429. {
  430. static bool const lower =
  431. has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
  432. static bool const upper =
  433. has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
  434. typedef literal_uint_generator<
  435. T
  436. , typename spirit::detail::get_encoding_with_case<
  437. Modifiers, unused_type, lower || upper>::type
  438. , typename detail::get_casetag<Modifiers, lower || upper>::type
  439. , 10, true
  440. > result_type;
  441. template <typename T_>
  442. result_type operator()(T_ i, unused_type) const
  443. {
  444. return result_type(i);
  445. }
  446. };
  447. }
  448. #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
  449. template <typename Modifiers>
  450. struct make_primitive<unsigned short, Modifiers>
  451. : detail::basic_uint_literal<unsigned short, Modifiers> {};
  452. #endif
  453. template <typename Modifiers>
  454. struct make_primitive<unsigned int, Modifiers>
  455. : detail::basic_uint_literal<unsigned int, Modifiers> {};
  456. template <typename Modifiers>
  457. struct make_primitive<unsigned long, Modifiers>
  458. : detail::basic_uint_literal<unsigned long, Modifiers> {};
  459. #ifdef BOOST_HAS_LONG_LONG
  460. template <typename Modifiers>
  461. struct make_primitive<boost::ulong_long_type, Modifiers>
  462. : detail::basic_uint_literal<boost::ulong_long_type, Modifiers> {};
  463. #endif
  464. // lit(uint)
  465. template <typename Modifiers, typename A0>
  466. struct make_primitive<
  467. terminal_ex<tag::lit, fusion::vector1<A0> >
  468. , Modifiers
  469. , typename enable_if<traits::is_uint<A0> >::type>
  470. {
  471. static bool const lower =
  472. has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
  473. static bool const upper =
  474. has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
  475. typedef literal_uint_generator<
  476. typename remove_const<A0>::type
  477. , typename spirit::detail::get_encoding_with_case<
  478. Modifiers, unused_type, lower || upper>::type
  479. , typename detail::get_casetag<Modifiers, lower || upper>::type
  480. , 10, true
  481. > result_type;
  482. template <typename Terminal>
  483. result_type operator()(Terminal const& term, unused_type) const
  484. {
  485. return result_type(fusion::at_c<0>(term.args));
  486. }
  487. };
  488. }}}
  489. #endif