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