File indexing completed on 2025-07-01 08:31:50
0001
0002
0003
0004
0005
0006 #if !defined(BOOST_SPIRIT_KARMA_BINARY_MAY_04_2007_0904AM)
0007 #define BOOST_SPIRIT_KARMA_BINARY_MAY_04_2007_0904AM
0008
0009 #if defined(_MSC_VER)
0010 #pragma once
0011 #endif
0012
0013 #include <boost/spirit/home/support/common_terminals.hpp>
0014 #include <boost/spirit/home/support/info.hpp>
0015 #include <boost/spirit/home/support/detail/endian.hpp>
0016
0017 #include <boost/spirit/home/karma/domain.hpp>
0018 #include <boost/spirit/home/karma/meta_compiler.hpp>
0019 #include <boost/spirit/home/karma/delimit_out.hpp>
0020 #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
0021 #include <boost/spirit/home/karma/detail/generate_to.hpp>
0022 #include <boost/spirit/home/karma/detail/extract_from.hpp>
0023 #include <boost/spirit/home/support/unused.hpp>
0024 #include <boost/spirit/home/support/container.hpp>
0025 #include <boost/core/scoped_enum.hpp>
0026 #include <boost/fusion/include/vector.hpp>
0027 #include <boost/fusion/include/at.hpp>
0028 #include <boost/mpl/or.hpp>
0029 #include <boost/type_traits/is_integral.hpp>
0030 #include <boost/type_traits/is_enum.hpp>
0031 #include <boost/type_traits/is_floating_point.hpp>
0032 #include <boost/config.hpp>
0033
0034
0035 #define BOOST_SPIRIT_ENABLE_BINARY(name) \
0036 template <> \
0037 struct use_terminal<karma::domain, tag::name> \
0038 : mpl::true_ {}; \
0039 \
0040 template <typename A0> \
0041 struct use_terminal<karma::domain \
0042 , terminal_ex<tag::name, fusion::vector1<A0> > > \
0043 : mpl::or_<is_integral<A0>, is_enum<A0> > {}; \
0044 \
0045 template <> \
0046 struct use_lazy_terminal<karma::domain, tag::name, 1> : mpl::true_ {}; \
0047 \
0048
0049
0050 #define BOOST_SPIRIT_ENABLE_BINARY_IEEE754(name) \
0051 template<> \
0052 struct use_terminal<karma::domain, tag::name>: mpl::true_ {}; \
0053 \
0054 template<typename A0> \
0055 struct use_terminal<karma::domain, terminal_ex<tag::name, \
0056 fusion::vector1<A0> > >: is_floating_point<A0> {}; \
0057 \
0058 template<> \
0059 struct use_lazy_terminal<karma::domain, tag::name, 1> : mpl::true_ {}; \
0060 \
0061
0062
0063 namespace boost { namespace spirit
0064 {
0065
0066
0067
0068
0069 BOOST_SPIRIT_ENABLE_BINARY(byte_)
0070 BOOST_SPIRIT_ENABLE_BINARY(word)
0071 BOOST_SPIRIT_ENABLE_BINARY(big_word)
0072 BOOST_SPIRIT_ENABLE_BINARY(little_word)
0073 BOOST_SPIRIT_ENABLE_BINARY(dword)
0074 BOOST_SPIRIT_ENABLE_BINARY(big_dword)
0075 BOOST_SPIRIT_ENABLE_BINARY(little_dword)
0076 #ifdef BOOST_HAS_LONG_LONG
0077 BOOST_SPIRIT_ENABLE_BINARY(qword)
0078 BOOST_SPIRIT_ENABLE_BINARY(big_qword)
0079 BOOST_SPIRIT_ENABLE_BINARY(little_qword)
0080 #endif
0081 BOOST_SPIRIT_ENABLE_BINARY_IEEE754(bin_float)
0082 BOOST_SPIRIT_ENABLE_BINARY_IEEE754(big_bin_float)
0083 BOOST_SPIRIT_ENABLE_BINARY_IEEE754(little_bin_float)
0084 BOOST_SPIRIT_ENABLE_BINARY_IEEE754(bin_double)
0085 BOOST_SPIRIT_ENABLE_BINARY_IEEE754(big_bin_double)
0086 BOOST_SPIRIT_ENABLE_BINARY_IEEE754(little_bin_double)
0087 }}
0088
0089 #undef BOOST_SPIRIT_ENABLE_BINARY
0090 #undef BOOST_SPIRIT_ENABLE_BINARY_IEEE754
0091
0092
0093 namespace boost { namespace spirit { namespace karma
0094 {
0095 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0096 using boost::spirit::byte_;
0097 using boost::spirit::word;
0098 using boost::spirit::big_word;
0099 using boost::spirit::little_word;
0100 using boost::spirit::dword;
0101 using boost::spirit::big_dword;
0102 using boost::spirit::little_dword;
0103 #ifdef BOOST_HAS_LONG_LONG
0104 using boost::spirit::qword;
0105 using boost::spirit::big_qword;
0106 using boost::spirit::little_qword;
0107 #endif
0108 using boost::spirit::bin_float;
0109 using boost::spirit::big_bin_float;
0110 using boost::spirit::little_bin_float;
0111 using boost::spirit::bin_double;
0112 using boost::spirit::big_bin_double;
0113 using boost::spirit::little_bin_double;
0114 #endif
0115
0116 using boost::spirit::byte_type;
0117 using boost::spirit::word_type;
0118 using boost::spirit::big_word_type;
0119 using boost::spirit::little_word_type;
0120 using boost::spirit::dword_type;
0121 using boost::spirit::big_dword_type;
0122 using boost::spirit::little_dword_type;
0123 #ifdef BOOST_HAS_LONG_LONG
0124 using boost::spirit::qword_type;
0125 using boost::spirit::big_qword_type;
0126 using boost::spirit::little_qword_type;
0127 #endif
0128 using boost::spirit::bin_float_type;
0129 using boost::spirit::big_bin_float_type;
0130 using boost::spirit::little_bin_float_type;
0131 using boost::spirit::bin_double_type;
0132 using boost::spirit::big_bin_double_type;
0133 using boost::spirit::little_bin_double_type;
0134
0135 namespace detail
0136 {
0137 template <int bits>
0138 struct integer
0139 {
0140 #ifdef BOOST_HAS_LONG_LONG
0141 BOOST_SPIRIT_ASSERT_MSG(
0142 bits == 8 || bits == 16 || bits == 32 || bits == 64,
0143 not_supported_binary_size, ());
0144 #else
0145 BOOST_SPIRIT_ASSERT_MSG(
0146 bits == 8 || bits == 16 || bits == 32,
0147 not_supported_binary_size, ());
0148 #endif
0149 };
0150
0151 template <>
0152 struct integer<8>
0153 {
0154 typedef uint_least8_t type;
0155 };
0156
0157 template <>
0158 struct integer<16>
0159 {
0160 typedef uint_least16_t type;
0161 };
0162
0163 template <>
0164 struct integer<32>
0165 {
0166 typedef uint_least32_t type;
0167 };
0168
0169 #ifdef BOOST_HAS_LONG_LONG
0170 template <>
0171 struct integer<64>
0172 {
0173 typedef uint_least64_t type;
0174 };
0175 #endif
0176
0177 template <int bits>
0178 struct floating_point
0179 {
0180 BOOST_SPIRIT_ASSERT_MSG(
0181 bits == 32 || bits == 64,
0182 not_supported_binary_size, ());
0183 };
0184
0185 template <>
0186 struct floating_point<32>
0187 {
0188 typedef float type;
0189 };
0190
0191 template <>
0192 struct floating_point<64>
0193 {
0194 typedef double type;
0195 };
0196
0197
0198 template <BOOST_SCOPED_ENUM(boost::endian::order) bits>
0199 struct what;
0200
0201 template <>
0202 struct what<boost::endian::order::little>
0203 {
0204 static info is()
0205 {
0206 return info("little-endian binary");
0207 }
0208 };
0209
0210 template <>
0211 struct what<boost::endian::order::big>
0212 {
0213 static info is()
0214 {
0215 return info("big-endian binary");
0216 }
0217 };
0218 }
0219
0220
0221 template <typename T, BOOST_SCOPED_ENUM(boost::endian::order) endian, int bits>
0222 struct any_binary_generator
0223 : primitive_generator<any_binary_generator<T, endian, bits> >
0224 {
0225 template <typename Context, typename Unused = unused_type>
0226 struct attribute: T {};
0227
0228 template <
0229 typename OutputIterator, typename Context, typename Delimiter
0230 , typename Attribute>
0231 static bool generate(OutputIterator& sink, Context& context
0232 , Delimiter const& d, Attribute const& attr)
0233 {
0234 if (!traits::has_optional_value(attr))
0235 return false;
0236
0237 boost::endian::endian_arithmetic<endian, typename T::type, bits> p;
0238
0239 #if defined(BOOST_MSVC)
0240
0241 #pragma warning(push)
0242 #pragma warning(disable: 4244)
0243 #endif
0244 typedef typename T::type attribute_type;
0245 p = traits::extract_from<attribute_type>(attr, context);
0246 #if defined(BOOST_MSVC)
0247 #pragma warning(pop)
0248 #endif
0249
0250 unsigned char const* bytes = p.data();
0251
0252 for (unsigned int i = 0; i < sizeof(p); ++i)
0253 {
0254 if (!detail::generate_to(sink, *bytes++))
0255 return false;
0256 }
0257 return karma::delimit_out(sink, d);
0258 }
0259
0260
0261
0262 template <
0263 typename OutputIterator, typename Context, typename Delimiter>
0264 static bool generate(OutputIterator&, Context&, Delimiter const&
0265 , unused_type)
0266 {
0267
0268
0269
0270
0271 BOOST_SPIRIT_ASSERT_FAIL(OutputIterator,
0272 binary_generator_not_usable_without_attribute, ());
0273 return false;
0274 }
0275
0276 template <typename Context>
0277 static info what(Context const& )
0278 {
0279 return karma::detail::what<endian>::is();
0280 }
0281 };
0282
0283
0284 template <typename T, BOOST_SCOPED_ENUM(boost::endian::order) endian, int bits>
0285 struct literal_binary_generator
0286 : primitive_generator<literal_binary_generator<T, endian, bits> >
0287 {
0288 template <typename Context, typename Unused>
0289 struct attribute
0290 {
0291 typedef unused_type type;
0292 };
0293
0294 template <typename V>
0295 literal_binary_generator(V const& v)
0296 {
0297 #if defined(BOOST_MSVC)
0298
0299 #pragma warning(push)
0300 #pragma warning(disable: 4244)
0301 #endif
0302 data_ = v;
0303 #if defined(BOOST_MSVC)
0304 #pragma warning(pop)
0305 #endif
0306 }
0307
0308 template <
0309 typename OutputIterator, typename Context, typename Delimiter
0310 , typename Attribute>
0311 bool generate(OutputIterator& sink, Context&, Delimiter const& d
0312 , Attribute const&) const
0313 {
0314 unsigned char const* bytes = data_.data();
0315
0316 for (unsigned int i = 0; i < sizeof(data_type); ++i)
0317 {
0318 if (!detail::generate_to(sink, *bytes++))
0319 return false;
0320 }
0321 return karma::delimit_out(sink, d);
0322 }
0323
0324 template <typename Context>
0325 static info what(Context const& )
0326 {
0327 return karma::detail::what<endian>::is();
0328 }
0329
0330 typedef boost::endian::endian_arithmetic<endian, typename T::type,
0331 bits> data_type;
0332
0333 data_type data_;
0334 };
0335
0336
0337
0338
0339 namespace detail
0340 {
0341 template <typename T, BOOST_SCOPED_ENUM(boost::endian::order) endian
0342 , int bits>
0343 struct basic_binary
0344 {
0345 typedef any_binary_generator<T, endian, bits> result_type;
0346
0347 result_type operator()(unused_type, unused_type) const
0348 {
0349 return result_type();
0350 }
0351 };
0352
0353 template <typename Modifiers, typename T
0354 , BOOST_SCOPED_ENUM(boost::endian::order) endian, int bits>
0355 struct basic_binary_literal
0356 {
0357 typedef literal_binary_generator<T, endian, bits> result_type;
0358
0359 template <typename Terminal>
0360 result_type operator()(Terminal const& term, unused_type) const
0361 {
0362 return result_type(fusion::at_c<0>(term.args));
0363 }
0364 };
0365 }
0366
0367 #define BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(name, endiantype, bits) \
0368 template <typename Modifiers> \
0369 struct make_primitive<tag::name, Modifiers> \
0370 : detail::basic_binary<detail::integer<bits>, \
0371 boost::endian::order::endiantype, bits> {}; \
0372 \
0373 template <typename Modifiers, typename A0> \
0374 struct make_primitive<terminal_ex<tag::name, fusion::vector1<A0> > \
0375 , Modifiers> \
0376 : detail::basic_binary_literal<Modifiers, detail::integer<bits> \
0377 , boost::endian::order::endiantype, bits> {}; \
0378 \
0379
0380
0381 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(byte_, native, 8)
0382 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(word, native, 16)
0383 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_word, big, 16)
0384 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_word, little, 16)
0385 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(dword, native, 32)
0386 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_dword, big, 32)
0387 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_dword, little, 32)
0388 #ifdef BOOST_HAS_LONG_LONG
0389 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(qword, native, 64)
0390 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_qword, big, 64)
0391 BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_qword, little, 64)
0392 #endif
0393
0394 #undef BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE
0395
0396 #define BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE(name, endiantype, bits) \
0397 template <typename Modifiers> \
0398 struct make_primitive<tag::name, Modifiers> \
0399 : detail::basic_binary<detail::floating_point<bits>, \
0400 boost::endian::order::endiantype, bits> {}; \
0401 \
0402 template <typename Modifiers, typename A0> \
0403 struct make_primitive<terminal_ex<tag::name, fusion::vector1<A0> > \
0404 , Modifiers> \
0405 : detail::basic_binary_literal<Modifiers, detail::floating_point<bits> \
0406 , boost::endian::order::endiantype, bits> {}; \
0407 \
0408
0409
0410 BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE(bin_float, native, 32)
0411 BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE(big_bin_float, big, 32)
0412 BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE(little_bin_float, little, 32)
0413 BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE(bin_double, native, 64)
0414 BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE(big_bin_double, big, 64)
0415 BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE(little_bin_double, little, 64)
0416
0417 #undef BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE
0418
0419 }}}
0420
0421 #endif