binary.hpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Hartmut Kaiser
  3. Copyright (c) 2001-2011 Joel de Guzman
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. #if !defined(BOOST_SPIRIT_X3_BINARY_MAY_08_2007_0808AM)
  8. #define BOOST_SPIRIT_X3_BINARY_MAY_08_2007_0808AM
  9. #include <boost/spirit/home/x3/core/parser.hpp>
  10. #include <boost/spirit/home/x3/core/skip_over.hpp>
  11. #include <boost/spirit/home/x3/support/traits/move_to.hpp>
  12. #include <cstdint>
  13. #include <boost/endian/conversion.hpp>
  14. #include <boost/endian/arithmetic.hpp>
  15. #include <boost/fusion/include/at.hpp>
  16. #include <boost/mpl/or.hpp>
  17. #include <boost/type_traits/is_integral.hpp>
  18. #include <boost/type_traits/is_enum.hpp>
  19. #include <boost/type_traits/is_floating_point.hpp>
  20. #include <boost/config.hpp>
  21. namespace boost { namespace spirit { namespace x3
  22. {
  23. template <typename V, typename T
  24. , boost::endian::order endian, std::size_t bits>
  25. struct binary_lit_parser
  26. : parser<binary_lit_parser<V, T, endian, bits> >
  27. {
  28. static bool const has_attribute = false;
  29. typedef unused_type attribute_type;
  30. binary_lit_parser(V n_)
  31. : n(n_) {}
  32. template <typename Iterator, typename Context, typename Attribute>
  33. bool parse(Iterator& first, Iterator const& last
  34. , Context const& context, unused_type, Attribute& attr_param) const
  35. {
  36. x3::skip_over(first, last, context);
  37. auto bytes = reinterpret_cast<const unsigned char*>(&n);
  38. Iterator it = first;
  39. for (unsigned int i = 0; i < sizeof(n); ++i)
  40. {
  41. if (it == last || *bytes++ != static_cast<unsigned char>(*it++))
  42. return false;
  43. }
  44. first = it;
  45. x3::traits::move_to(n, attr_param);
  46. return true;
  47. }
  48. boost::endian::endian_arithmetic<endian, T, bits> n;
  49. };
  50. ///////////////////////////////////////////////////////////////////////////
  51. template <typename T, boost::endian::order endian, std::size_t bits>
  52. struct any_binary_parser : parser<any_binary_parser<T, endian, bits > >
  53. {
  54. typedef T attribute_type;
  55. static bool const has_attribute =
  56. !is_same<unused_type, attribute_type>::value;
  57. template <typename Iterator, typename Context, typename Attribute>
  58. bool parse(Iterator& first, Iterator const& last
  59. , Context const& context, unused_type, Attribute& attr_param) const
  60. {
  61. x3::skip_over(first, last, context);
  62. attribute_type attr_;
  63. auto bytes = reinterpret_cast<unsigned char*>(&attr_);
  64. Iterator it = first;
  65. for (unsigned int i = 0; i < sizeof(attr_); ++i)
  66. {
  67. if (it == last)
  68. return false;
  69. *bytes++ = *it++;
  70. }
  71. first = it;
  72. x3::traits::move_to(
  73. endian::conditional_reverse<endian, endian::order::native>(attr_)
  74. , attr_param );
  75. return true;
  76. }
  77. template <typename V>
  78. binary_lit_parser< V, T, endian, bits> operator()(V n) const
  79. {
  80. return {n};
  81. }
  82. };
  83. #define BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(name, endiantype, attrtype, bits) \
  84. typedef any_binary_parser< attrtype, boost::endian::order::endiantype, bits > name##type; \
  85. name##type const name = name##type();
  86. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(byte_, native, uint_least8_t, 8)
  87. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(word, native, uint_least16_t, 16)
  88. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_word, big, uint_least16_t, 16)
  89. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_word, little, uint_least16_t, 16)
  90. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(dword, native, uint_least32_t, 32)
  91. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_dword, big, uint_least32_t, 32)
  92. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_dword, little, uint_least32_t, 32)
  93. #ifdef BOOST_HAS_LONG_LONG
  94. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(qword, native, uint_least64_t, 64)
  95. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_qword, big, uint_least64_t, 64)
  96. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_qword, little, uint_least64_t, 64)
  97. #endif
  98. // Use a pseudo configuration macro to make clear that endian libray support
  99. // for floating point types is required. Must be removed as soon as the endian library
  100. // properly supports floating point types.
  101. #ifdef BOOST_ENDIAN_HAS_FLOATING_POINT
  102. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(bin_float, native, float, 32)
  103. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_bin_float, big, float, 32)
  104. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_bin_float, little, float, 32)
  105. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(bin_double, native, double, 64)
  106. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_bin_double, big, double, 64)
  107. BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_bin_double, little, double, 64)
  108. #endif
  109. #undef BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE
  110. ///////////////////////////////////////////////////////////////////////////
  111. template <typename T, std::size_t bits>
  112. struct get_info<any_binary_parser<T, endian::order::little, bits>>
  113. {
  114. typedef std::string result_type;
  115. std::string operator()(any_binary_parser<T, endian::order::little, bits> const& p) const
  116. {
  117. return "little-endian binary";
  118. }
  119. };
  120. template <typename T, std::size_t bits>
  121. struct get_info<any_binary_parser<T, endian::order::big, bits>>
  122. {
  123. typedef std::string result_type;
  124. std::string operator()(any_binary_parser<T, endian::order::big, bits> const& p) const
  125. {
  126. return "big-endian binary";
  127. }
  128. };
  129. template <typename V, typename T, std::size_t bits>
  130. struct get_info<binary_lit_parser<V, T, endian::order::little, bits>>
  131. {
  132. typedef std::string result_type;
  133. std::string operator()(binary_lit_parser<V, T, endian::order::little, bits> const& p) const
  134. {
  135. return "little-endian binary";
  136. }
  137. };
  138. template <typename V, typename T, std::size_t bits>
  139. struct get_info<binary_lit_parser<V, T, endian::order::big, bits>>
  140. {
  141. typedef std::string result_type;
  142. std::string operator()(binary_lit_parser<V, T, endian::order::big, bits> const& p) const
  143. {
  144. return "big-endian binary";
  145. }
  146. };
  147. }}}
  148. #endif