File indexing completed on 2025-01-31 10:02:34
0001
0002
0003
0004
0005
0006
0007
0008 #if !defined(BOOST_SPIRIT_X3_BINARY_MAY_08_2007_0808AM)
0009 #define BOOST_SPIRIT_X3_BINARY_MAY_08_2007_0808AM
0010
0011 #include <boost/spirit/home/x3/core/parser.hpp>
0012 #include <boost/spirit/home/x3/core/skip_over.hpp>
0013 #include <boost/spirit/home/x3/support/traits/move_to.hpp>
0014 #include <cstdint>
0015
0016 #include <boost/endian/conversion.hpp>
0017 #include <boost/endian/arithmetic.hpp>
0018 #include <boost/mpl/or.hpp>
0019 #include <boost/type_traits/is_integral.hpp>
0020 #include <boost/type_traits/is_enum.hpp>
0021 #include <boost/type_traits/is_floating_point.hpp>
0022 #include <boost/config.hpp>
0023 #include <climits>
0024
0025 namespace boost { namespace spirit { namespace x3
0026 {
0027 template <typename T, boost::endian::order endian, std::size_t bits>
0028 struct binary_lit_parser
0029 : parser<binary_lit_parser<T, endian, bits> >
0030 {
0031 static bool const has_attribute = false;
0032 typedef unused_type attribute_type;
0033
0034 constexpr binary_lit_parser(T n_)
0035 : n(n_) {}
0036
0037 template <typename Iterator, typename Context, typename Attribute>
0038 bool parse(Iterator& first, Iterator const& last
0039 , Context const& context, unused_type, Attribute& attr_param) const
0040 {
0041 x3::skip_over(first, last, context);
0042
0043 unsigned char const* bytes = n.data();
0044
0045 Iterator it = first;
0046 for (unsigned int i = 0; i < sizeof(n); ++i)
0047 {
0048 if (it == last || *bytes++ != static_cast<unsigned char>(*it++))
0049 return false;
0050 }
0051
0052 first = it;
0053 x3::traits::move_to(n, attr_param);
0054 return true;
0055 }
0056
0057 boost::endian::endian_arithmetic<endian, T, bits> n;
0058 };
0059
0060
0061 template <typename T, boost::endian::order endian, std::size_t bits>
0062 struct any_binary_parser : parser<any_binary_parser<T, endian, bits > >
0063 {
0064
0065 typedef T attribute_type;
0066 static bool const has_attribute =
0067 !is_same<unused_type, attribute_type>::value;
0068
0069 template <typename Iterator, typename Context, typename Attribute>
0070 bool parse(Iterator& first, Iterator const& last
0071 , Context const& context, unused_type, Attribute& attr_param) const
0072 {
0073 x3::skip_over(first, last, context);
0074
0075
0076 alignas(T) unsigned char buf[sizeof(T)];
0077 unsigned char * bytes = buf;
0078
0079 Iterator it = first;
0080 for (unsigned int i = 0; i < sizeof(T); ++i)
0081 {
0082 if (it == last)
0083 return false;
0084 *bytes++ = *it++;
0085 }
0086
0087 first = it;
0088
0089 static_assert(bits % CHAR_BIT == 0,
0090 "Boost.Endian supports only multiples of CHAR_BIT");
0091 x3::traits::move_to(
0092 endian::endian_load<T, bits / CHAR_BIT, endian>(buf),
0093 attr_param);
0094 return true;
0095 }
0096
0097 constexpr binary_lit_parser<T, endian, bits> operator()(T n) const
0098 {
0099 return {n};
0100 }
0101 };
0102
0103 #define BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(name, endiantype, attrtype, bits) \
0104 typedef any_binary_parser< attrtype, boost::endian::order::endiantype, bits > name##type; \
0105 constexpr name##type name = name##type();
0106
0107
0108 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(byte_, native, uint_least8_t, 8)
0109 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(word, native, uint_least16_t, 16)
0110 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_word, big, uint_least16_t, 16)
0111 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_word, little, uint_least16_t, 16)
0112 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(dword, native, uint_least32_t, 32)
0113 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_dword, big, uint_least32_t, 32)
0114 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_dword, little, uint_least32_t, 32)
0115 #ifdef BOOST_HAS_LONG_LONG
0116 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(qword, native, uint_least64_t, 64)
0117 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_qword, big, uint_least64_t, 64)
0118 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_qword, little, uint_least64_t, 64)
0119 #endif
0120 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(bin_float, native, float, sizeof(float) * CHAR_BIT)
0121 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_bin_float, big, float, sizeof(float) * CHAR_BIT)
0122 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_bin_float, little, float, sizeof(float) * CHAR_BIT)
0123 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(bin_double, native, double, sizeof(double) * CHAR_BIT)
0124 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_bin_double, big, double, sizeof(double) * CHAR_BIT)
0125 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_bin_double, little, double, sizeof(double) * CHAR_BIT)
0126
0127 #undef BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE
0128
0129
0130 template <typename T, std::size_t bits>
0131 struct get_info<any_binary_parser<T, endian::order::little, bits>>
0132 {
0133 typedef std::string result_type;
0134 std::string operator()(any_binary_parser<T, endian::order::little, bits> const&) const
0135 {
0136 return "little-endian binary";
0137 }
0138 };
0139
0140 template <typename T, std::size_t bits>
0141 struct get_info<any_binary_parser<T, endian::order::big, bits>>
0142 {
0143 typedef std::string result_type;
0144 std::string operator()(any_binary_parser<T, endian::order::big, bits> const&) const
0145 {
0146 return "big-endian binary";
0147 }
0148 };
0149
0150 template <typename T, std::size_t bits>
0151 struct get_info<binary_lit_parser<T, endian::order::little, bits>>
0152 {
0153 typedef std::string result_type;
0154 std::string operator()(binary_lit_parser<T, endian::order::little, bits> const&) const
0155 {
0156 return "little-endian binary";
0157 }
0158 };
0159
0160 template <typename T, std::size_t bits>
0161 struct get_info<binary_lit_parser<T, endian::order::big, bits>>
0162 {
0163 typedef std::string result_type;
0164 std::string operator()(binary_lit_parser<T, endian::order::big, bits> const&) const
0165 {
0166 return "big-endian binary";
0167 }
0168 };
0169
0170 }}}
0171
0172 #endif