]>
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> | |
18 | #include <boost/fusion/include/at.hpp> | |
19 | #include <boost/mpl/or.hpp> | |
20 | #include <boost/type_traits/is_integral.hpp> | |
21 | #include <boost/type_traits/is_enum.hpp> | |
22 | #include <boost/type_traits/is_floating_point.hpp> | |
23 | #include <boost/config.hpp> | |
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 | ||
35 | binary_lit_parser(V n_) | |
36 | : n(n_) {} | |
37 | ||
38 | template <typename Iterator, typename Context, typename Attribute> | |
39 | bool parse(Iterator& first, Iterator const& last | |
40 | , Context& context, unused_type, Attribute& attr_param) const | |
41 | { | |
42 | x3::skip_over(first, last, context); | |
43 | ||
44 | auto bytes = reinterpret_cast<const unsigned char*>(&n); | |
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 | |
72 | , Context& context, unused_type, Attribute& attr_param) const | |
73 | { | |
74 | x3::skip_over(first, last, context); | |
75 | ||
76 | attribute_type attr_; | |
77 | auto bytes = reinterpret_cast<unsigned char*>(&attr_); | |
78 | ||
79 | Iterator it = first; | |
80 | for (unsigned int i = 0; i < sizeof(attr_); ++i) | |
81 | { | |
82 | if (it == last) | |
83 | return false; | |
84 | *bytes++ = *it++; | |
85 | } | |
86 | ||
87 | first = it; | |
88 | x3::traits::move_to( | |
89 | endian::conditional_reverse<endian, endian::order::native>(attr_) | |
90 | , attr_param ); | |
91 | return true; | |
92 | } | |
93 | ||
94 | template <typename V> | |
95 | binary_lit_parser< V, T, endian, bits> operator()(V n) const | |
96 | { | |
97 | return {n}; | |
98 | } | |
99 | }; | |
100 | ||
101 | #define BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(name, endiantype, attrtype, bits) \ | |
102 | typedef any_binary_parser< attrtype, boost::endian::order::endiantype, bits > name##type; \ | |
103 | name##type const name = name##type(); | |
104 | ||
105 | ||
106 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(byte_, native, uint_least8_t, 8) | |
107 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(word, native, uint_least16_t, 16) | |
108 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_word, big, uint_least16_t, 16) | |
109 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_word, little, uint_least16_t, 16) | |
110 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(dword, native, uint_least32_t, 32) | |
111 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_dword, big, uint_least32_t, 32) | |
112 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_dword, little, uint_least32_t, 32) | |
113 | #ifdef BOOST_HAS_LONG_LONG | |
114 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(qword, native, uint_least64_t, 64) | |
115 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_qword, big, uint_least64_t, 64) | |
116 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_qword, little, uint_least64_t, 64) | |
117 | #endif | |
118 | ||
119 | // Use a pseudo configuration macro to make clear that endian libray support | |
120 | // for floating point types is required. Must be removed as soon as the endian library | |
121 | // properly supports floating point types. | |
122 | #ifdef BOOST_ENDIAN_HAS_FLOATING_POINT | |
123 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(bin_float, native, float, 32) | |
124 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_bin_float, big, float, 32) | |
125 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_bin_float, little, float, 32) | |
126 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(bin_double, native, double, 64) | |
127 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_bin_double, big, double, 64) | |
128 | BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_bin_double, little, double, 64) | |
129 | #endif | |
130 | ||
131 | #undef BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE | |
132 | ||
133 | /////////////////////////////////////////////////////////////////////////// | |
134 | template <typename T, std::size_t bits> | |
135 | struct get_info<any_binary_parser<T, endian::order::little, bits>> | |
136 | { | |
137 | typedef std::string result_type; | |
138 | std::string operator()(any_binary_parser<T, endian::order::little, bits> const& p) const | |
139 | { | |
140 | return "little-endian binary"; | |
141 | } | |
142 | }; | |
143 | ||
144 | template <typename T, std::size_t bits> | |
145 | struct get_info<any_binary_parser<T, endian::order::big, bits>> | |
146 | { | |
147 | typedef std::string result_type; | |
148 | std::string operator()(any_binary_parser<T, endian::order::big, bits> const& p) const | |
149 | { | |
150 | return "big-endian binary"; | |
151 | } | |
152 | }; | |
153 | ||
154 | template <typename V, typename T, std::size_t bits> | |
155 | struct get_info<binary_lit_parser<V, T, endian::order::little, bits>> | |
156 | { | |
157 | typedef std::string result_type; | |
158 | std::string operator()(binary_lit_parser<V, T, endian::order::little, bits> const& p) const | |
159 | { | |
160 | return "little-endian binary"; | |
161 | } | |
162 | }; | |
163 | ||
164 | template <typename V, typename T, std::size_t bits> | |
165 | struct get_info<binary_lit_parser<V, T, endian::order::big, bits>> | |
166 | { | |
167 | typedef std::string result_type; | |
168 | std::string operator()(binary_lit_parser<V, T, endian::order::big, bits> const& p) const | |
169 | { | |
170 | return "big-endian binary"; | |
171 | } | |
172 | }; | |
173 | ||
174 | }}} | |
175 | ||
176 | #endif |