]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2001-2011 Hartmut Kaiser | |
3 | Copyright (c) 2001-2011 Joel de Guzman | |
4 | ||
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(BOOST_SPIRIT_X3_BINARY_MAY_08_2007_0808AM) | |
9 | #define BOOST_SPIRIT_X3_BINARY_MAY_08_2007_0808AM | |
10 | ||
11 | #include <boost/spirit/home/x3/core/parser.hpp> | |
12 | #include <boost/spirit/home/x3/core/skip_over.hpp> | |
13 | #include <boost/spirit/home/x3/support/traits/move_to.hpp> | |
14 | #include <cstdint> | |
15 | ||
16 | #include <boost/endian/conversion.hpp> | |
17 | #include <boost/endian/arithmetic.hpp> | |
7c673cae FG |
18 | #include <boost/mpl/or.hpp> |
19 | #include <boost/type_traits/is_integral.hpp> | |
20 | #include <boost/type_traits/is_enum.hpp> | |
21 | #include <boost/type_traits/is_floating_point.hpp> | |
22 | #include <boost/config.hpp> | |
20effc67 | 23 | #include <climits> |
7c673cae FG |
24 | |
25 | namespace boost { namespace spirit { namespace x3 | |
26 | { | |
27 | template <typename V, typename T | |
28 | , boost::endian::order endian, std::size_t bits> | |
29 | struct binary_lit_parser | |
30 | : parser<binary_lit_parser<V, T, endian, bits> > | |
31 | { | |
32 | static bool const has_attribute = false; | |
33 | typedef unused_type attribute_type; | |
34 | ||
f67539c2 | 35 | constexpr binary_lit_parser(V n_) |
7c673cae FG |
36 | : n(n_) {} |
37 | ||
38 | template <typename Iterator, typename Context, typename Attribute> | |
39 | bool parse(Iterator& first, Iterator const& last | |
11fdf7f2 | 40 | , Context const& context, unused_type, Attribute& attr_param) const |
7c673cae FG |
41 | { |
42 | x3::skip_over(first, last, context); | |
43 | ||
f67539c2 | 44 | unsigned char const* bytes = n.data(); |
7c673cae FG |
45 | |
46 | Iterator it = first; | |
47 | for (unsigned int i = 0; i < sizeof(n); ++i) | |
48 | { | |
49 | if (it == last || *bytes++ != static_cast<unsigned char>(*it++)) | |
50 | return false; | |
51 | } | |
52 | ||
53 | first = it; | |
54 | x3::traits::move_to(n, attr_param); | |
55 | return true; | |
56 | } | |
57 | ||
58 | boost::endian::endian_arithmetic<endian, T, bits> n; | |
59 | }; | |
60 | ||
61 | /////////////////////////////////////////////////////////////////////////// | |
62 | template <typename T, boost::endian::order endian, std::size_t bits> | |
63 | struct any_binary_parser : parser<any_binary_parser<T, endian, bits > > | |
64 | { | |
65 | ||
66 | typedef T attribute_type; | |
67 | static bool const has_attribute = | |
68 | !is_same<unused_type, attribute_type>::value; | |
69 | ||
70 | template <typename Iterator, typename Context, typename Attribute> | |
71 | bool parse(Iterator& first, Iterator const& last | |
11fdf7f2 | 72 | , Context const& context, unused_type, Attribute& attr_param) const |
7c673cae FG |
73 | { |
74 | x3::skip_over(first, last, context); | |
75 | ||
20effc67 TL |
76 | // Properly align the buffer for performance reasons |
77 | alignas(T) unsigned char buf[sizeof(T)]; | |
78 | unsigned char * bytes = buf; | |
7c673cae FG |
79 | |
80 | Iterator it = first; | |
20effc67 | 81 | for (unsigned int i = 0; i < sizeof(T); ++i) |
7c673cae FG |
82 | { |
83 | if (it == last) | |
84 | return false; | |
85 | *bytes++ = *it++; | |
86 | } | |
87 | ||
88 | first = it; | |
20effc67 TL |
89 | |
90 | static_assert(bits % CHAR_BIT == 0, | |
91 | "Boost.Endian supports only multiples of CHAR_BIT"); | |
7c673cae | 92 | x3::traits::move_to( |
20effc67 TL |
93 | endian::endian_load<T, bits / CHAR_BIT, endian>(buf), |
94 | attr_param); | |
7c673cae FG |
95 | return true; |
96 | } | |
97 | ||
98 | template <typename V> | |
f67539c2 | 99 | constexpr binary_lit_parser< V, T, endian, bits> operator()(V n) const |
7c673cae FG |
100 | { |
101 | return {n}; | |
102 | } | |
103 | }; | |
104 | ||
105 | #define BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(name, endiantype, attrtype, bits) \ | |
106 | typedef any_binary_parser< attrtype, boost::endian::order::endiantype, bits > name##type; \ | |
f67539c2 | 107 | constexpr name##type name = name##type(); |
7c673cae FG |
108 | |
109 | ||
110 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(byte_, native, uint_least8_t, 8) | |
111 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(word, native, uint_least16_t, 16) | |
112 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_word, big, uint_least16_t, 16) | |
113 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_word, little, uint_least16_t, 16) | |
114 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(dword, native, uint_least32_t, 32) | |
115 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_dword, big, uint_least32_t, 32) | |
116 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_dword, little, uint_least32_t, 32) | |
117 | #ifdef BOOST_HAS_LONG_LONG | |
118 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(qword, native, uint_least64_t, 64) | |
119 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_qword, big, uint_least64_t, 64) | |
120 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_qword, little, uint_least64_t, 64) | |
121 | #endif | |
20effc67 TL |
122 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(bin_float, native, float, sizeof(float) * CHAR_BIT) |
123 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_bin_float, big, float, sizeof(float) * CHAR_BIT) | |
124 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_bin_float, little, float, sizeof(float) * CHAR_BIT) | |
125 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(bin_double, native, double, sizeof(double) * CHAR_BIT) | |
126 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_bin_double, big, double, sizeof(double) * CHAR_BIT) | |
127 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_bin_double, little, double, sizeof(double) * CHAR_BIT) | |
7c673cae FG |
128 | |
129 | #undef BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE | |
130 | ||
131 | /////////////////////////////////////////////////////////////////////////// | |
132 | template <typename T, std::size_t bits> | |
133 | struct get_info<any_binary_parser<T, endian::order::little, bits>> | |
134 | { | |
135 | typedef std::string result_type; | |
20effc67 | 136 | std::string operator()(any_binary_parser<T, endian::order::little, bits> const&) const |
7c673cae FG |
137 | { |
138 | return "little-endian binary"; | |
139 | } | |
140 | }; | |
141 | ||
142 | template <typename T, std::size_t bits> | |
143 | struct get_info<any_binary_parser<T, endian::order::big, bits>> | |
144 | { | |
145 | typedef std::string result_type; | |
20effc67 | 146 | std::string operator()(any_binary_parser<T, endian::order::big, bits> const&) const |
7c673cae FG |
147 | { |
148 | return "big-endian binary"; | |
149 | } | |
150 | }; | |
151 | ||
152 | template <typename V, typename T, std::size_t bits> | |
153 | struct get_info<binary_lit_parser<V, T, endian::order::little, bits>> | |
154 | { | |
155 | typedef std::string result_type; | |
20effc67 | 156 | std::string operator()(binary_lit_parser<V, T, endian::order::little, bits> const&) const |
7c673cae FG |
157 | { |
158 | return "little-endian binary"; | |
159 | } | |
160 | }; | |
161 | ||
162 | template <typename V, typename T, std::size_t bits> | |
163 | struct get_info<binary_lit_parser<V, T, endian::order::big, bits>> | |
164 | { | |
165 | typedef std::string result_type; | |
20effc67 | 166 | std::string operator()(binary_lit_parser<V, T, endian::order::big, bits> const&) const |
7c673cae FG |
167 | { |
168 | return "big-endian binary"; | |
169 | } | |
170 | }; | |
171 | ||
172 | }}} | |
173 | ||
174 | #endif |