Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:35:32

0001 //  boost/endian/buffers.hpp  ----------------------------------------------------------//
0002 
0003 //  (C) Copyright Darin Adler 2000
0004 //  (C) Copyright Beman Dawes 2006, 2009, 2014
0005 //  (C) Copyright Peter Dimov 2019
0006 
0007 //  Distributed under the Boost Software License, Version 1.0.
0008 //  See http://www.boost.org/LICENSE_1_0.txt
0009 
0010 //  See library home page at http://www.boost.org/libs/endian
0011 
0012 //--------------------------------------------------------------------------------------//
0013 
0014 //  Original design developed by Darin Adler based on classes developed by Mark
0015 //  Borgerding. Four original class templates were combined into a single endian
0016 //  class template by Beman Dawes, who also added the unrolled_byte_loops sign
0017 //  partial specialization to correctly extend the sign when cover integer size
0018 //  differs from endian representation size.
0019 
0020 // TODO: When a compiler supporting constexpr becomes available, try possible uses.
0021 
0022 #ifndef BOOST_ENDIAN_BUFFERS_HPP
0023 #define BOOST_ENDIAN_BUFFERS_HPP
0024 
0025 #if defined(_MSC_VER)
0026 # pragma warning(push)
0027 # pragma warning(disable: 4127)  // conditional expression is constant
0028 #endif
0029 
0030 #include <boost/endian/detail/endian_store.hpp>
0031 #include <boost/endian/detail/endian_load.hpp>
0032 #include <boost/endian/detail/static_assert.hpp>
0033 #include <boost/config.hpp>
0034 #include <cstdint>
0035 #include <iosfwd>
0036 #include <climits>
0037 #include <cstring>
0038 
0039 #if defined(BOOST_BORLANDC) || defined(BOOST_CODEGEARC)
0040 # pragma pack(push, 1)
0041 #endif
0042 
0043 # if CHAR_BIT != 8
0044 #   error Platforms with CHAR_BIT != 8 are not supported
0045 # endif
0046 
0047 //----------------------------------  synopsis  ----------------------------------------//
0048 
0049 namespace boost
0050 {
0051 namespace endian
0052 {
0053 
0054   enum class align
0055   {no, yes
0056 #   ifdef BOOST_ENDIAN_DEPRECATED_NAMES
0057       , unaligned = no, aligned = yes
0058 #   endif
0059   };
0060 
0061   template <order Order, class T, std::size_t n_bits,
0062     align A = align::no>
0063       class endian_buffer;
0064 
0065   // aligned big endian signed integer buffers
0066   typedef endian_buffer<order::big, std::int8_t, 8, align::yes>       big_int8_buf_at;
0067   typedef endian_buffer<order::big, std::int16_t, 16, align::yes>     big_int16_buf_at;
0068   typedef endian_buffer<order::big, std::int32_t, 32, align::yes>     big_int32_buf_at;
0069   typedef endian_buffer<order::big, std::int64_t, 64, align::yes>     big_int64_buf_at;
0070 
0071   // aligned big endian unsigned integer buffers
0072   typedef endian_buffer<order::big, std::uint8_t, 8, align::yes>      big_uint8_buf_at;
0073   typedef endian_buffer<order::big, std::uint16_t, 16, align::yes>    big_uint16_buf_at;
0074   typedef endian_buffer<order::big, std::uint32_t, 32, align::yes>    big_uint32_buf_at;
0075   typedef endian_buffer<order::big, std::uint64_t, 64, align::yes>    big_uint64_buf_at;
0076 
0077   // aligned little endian signed integer buffers
0078   typedef endian_buffer<order::little, std::int8_t, 8, align::yes>    little_int8_buf_at;
0079   typedef endian_buffer<order::little, std::int16_t, 16, align::yes>  little_int16_buf_at;
0080   typedef endian_buffer<order::little, std::int32_t, 32, align::yes>  little_int32_buf_at;
0081   typedef endian_buffer<order::little, std::int64_t, 64, align::yes>  little_int64_buf_at;
0082 
0083   // aligned little endian unsigned integer buffers
0084   typedef endian_buffer<order::little, std::uint8_t, 8, align::yes>   little_uint8_buf_at;
0085   typedef endian_buffer<order::little, std::uint16_t, 16, align::yes> little_uint16_buf_at;
0086   typedef endian_buffer<order::little, std::uint32_t, 32, align::yes> little_uint32_buf_at;
0087   typedef endian_buffer<order::little, std::uint64_t, 64, align::yes> little_uint64_buf_at;
0088 
0089   // aligned floating point buffers
0090   typedef endian_buffer<order::big, float, 32, align::yes>       big_float32_buf_at;
0091   typedef endian_buffer<order::big, double, 64, align::yes>      big_float64_buf_at;
0092   typedef endian_buffer<order::little, float, 32, align::yes>    little_float32_buf_at;
0093   typedef endian_buffer<order::little, double, 64, align::yes>   little_float64_buf_at;
0094 
0095   // aligned native endian typedefs are not provided because
0096   // <cstdint> types are superior for this use case
0097 
0098   // unaligned big endian signed integer buffers
0099   typedef endian_buffer<order::big, std::int_least8_t, 8>        big_int8_buf_t;
0100   typedef endian_buffer<order::big, std::int_least16_t, 16>      big_int16_buf_t;
0101   typedef endian_buffer<order::big, std::int_least32_t, 24>      big_int24_buf_t;
0102   typedef endian_buffer<order::big, std::int_least32_t, 32>      big_int32_buf_t;
0103   typedef endian_buffer<order::big, std::int_least64_t, 40>      big_int40_buf_t;
0104   typedef endian_buffer<order::big, std::int_least64_t, 48>      big_int48_buf_t;
0105   typedef endian_buffer<order::big, std::int_least64_t, 56>      big_int56_buf_t;
0106   typedef endian_buffer<order::big, std::int_least64_t, 64>      big_int64_buf_t;
0107 
0108   // unaligned big endian unsigned integer buffers
0109   typedef endian_buffer<order::big, std::uint_least8_t, 8>       big_uint8_buf_t;
0110   typedef endian_buffer<order::big, std::uint_least16_t, 16>     big_uint16_buf_t;
0111   typedef endian_buffer<order::big, std::uint_least32_t, 24>     big_uint24_buf_t;
0112   typedef endian_buffer<order::big, std::uint_least32_t, 32>     big_uint32_buf_t;
0113   typedef endian_buffer<order::big, std::uint_least64_t, 40>     big_uint40_buf_t;
0114   typedef endian_buffer<order::big, std::uint_least64_t, 48>     big_uint48_buf_t;
0115   typedef endian_buffer<order::big, std::uint_least64_t, 56>     big_uint56_buf_t;
0116   typedef endian_buffer<order::big, std::uint_least64_t, 64>     big_uint64_buf_t;
0117 
0118   // unaligned little endian signed integer buffers
0119   typedef endian_buffer<order::little, std::int_least8_t, 8>     little_int8_buf_t;
0120   typedef endian_buffer<order::little, std::int_least16_t, 16>   little_int16_buf_t;
0121   typedef endian_buffer<order::little, std::int_least32_t, 24>   little_int24_buf_t;
0122   typedef endian_buffer<order::little, std::int_least32_t, 32>   little_int32_buf_t;
0123   typedef endian_buffer<order::little, std::int_least64_t, 40>   little_int40_buf_t;
0124   typedef endian_buffer<order::little, std::int_least64_t, 48>   little_int48_buf_t;
0125   typedef endian_buffer<order::little, std::int_least64_t, 56>   little_int56_buf_t;
0126   typedef endian_buffer<order::little, std::int_least64_t, 64>   little_int64_buf_t;
0127 
0128   // unaligned little endian unsigned integer buffers
0129   typedef endian_buffer<order::little, std::uint_least8_t, 8>    little_uint8_buf_t;
0130   typedef endian_buffer<order::little, std::uint_least16_t, 16>  little_uint16_buf_t;
0131   typedef endian_buffer<order::little, std::uint_least32_t, 24>  little_uint24_buf_t;
0132   typedef endian_buffer<order::little, std::uint_least32_t, 32>  little_uint32_buf_t;
0133   typedef endian_buffer<order::little, std::uint_least64_t, 40>  little_uint40_buf_t;
0134   typedef endian_buffer<order::little, std::uint_least64_t, 48>  little_uint48_buf_t;
0135   typedef endian_buffer<order::little, std::uint_least64_t, 56>  little_uint56_buf_t;
0136   typedef endian_buffer<order::little, std::uint_least64_t, 64>  little_uint64_buf_t;
0137 
0138   // unaligned native endian signed integer buffers
0139   typedef endian_buffer<order::native, std::int_least8_t, 8>     native_int8_buf_t;
0140   typedef endian_buffer<order::native, std::int_least16_t, 16>   native_int16_buf_t;
0141   typedef endian_buffer<order::native, std::int_least32_t, 24>   native_int24_buf_t;
0142   typedef endian_buffer<order::native, std::int_least32_t, 32>   native_int32_buf_t;
0143   typedef endian_buffer<order::native, std::int_least64_t, 40>   native_int40_buf_t;
0144   typedef endian_buffer<order::native, std::int_least64_t, 48>   native_int48_buf_t;
0145   typedef endian_buffer<order::native, std::int_least64_t, 56>   native_int56_buf_t;
0146   typedef endian_buffer<order::native, std::int_least64_t, 64>   native_int64_buf_t;
0147 
0148   // unaligned native endian unsigned integer buffers
0149   typedef endian_buffer<order::native, std::uint_least8_t, 8>    native_uint8_buf_t;
0150   typedef endian_buffer<order::native, std::uint_least16_t, 16>  native_uint16_buf_t;
0151   typedef endian_buffer<order::native, std::uint_least32_t, 24>  native_uint24_buf_t;
0152   typedef endian_buffer<order::native, std::uint_least32_t, 32>  native_uint32_buf_t;
0153   typedef endian_buffer<order::native, std::uint_least64_t, 40>  native_uint40_buf_t;
0154   typedef endian_buffer<order::native, std::uint_least64_t, 48>  native_uint48_buf_t;
0155   typedef endian_buffer<order::native, std::uint_least64_t, 56>  native_uint56_buf_t;
0156   typedef endian_buffer<order::native, std::uint_least64_t, 64>  native_uint64_buf_t;
0157 
0158   // unaligned floating point buffers
0159   typedef endian_buffer<order::big, float, 32, align::no>       big_float32_buf_t;
0160   typedef endian_buffer<order::big, double, 64, align::no>      big_float64_buf_t;
0161   typedef endian_buffer<order::little, float, 32, align::no>    little_float32_buf_t;
0162   typedef endian_buffer<order::little, double, 64, align::no>   little_float64_buf_t;
0163   typedef endian_buffer<order::native, float, 32, align::no>    native_float32_buf_t;
0164   typedef endian_buffer<order::native, double, 64, align::no>   native_float64_buf_t;
0165 
0166   // Stream inserter
0167   template <class charT, class traits, order Order, class T,
0168     std::size_t n_bits, align A>
0169   std::basic_ostream<charT, traits>&
0170     operator<<(std::basic_ostream<charT, traits>& os,
0171       const endian_buffer<Order, T, n_bits, A>& x)
0172   {
0173     return os << x.value();
0174   }
0175 
0176   // Stream extractor
0177   template <class charT, class traits, order Order, class T,
0178     std::size_t n_bits, align A>
0179   std::basic_istream<charT, traits>&
0180     operator>>(std::basic_istream<charT, traits>& is,
0181       endian_buffer<Order, T, n_bits, A>& x)
0182   {
0183     T i;
0184     if (is >> i)
0185       x = i;
0186     return is;
0187   }
0188 
0189 //----------------------------------  end synopsis  ------------------------------------//
0190 
0191 //  endian_buffer class template specializations  --------------------------------------//
0192 
0193 //  Specializations that represent unaligned bytes.
0194 //  Taking an integer type as a parameter provides a nice way to pass both
0195 //  the size and signedness of the desired integer and get the appropriate
0196 //  corresponding integer type for the interface.
0197 
0198 // Q: Should endian_buffer supply "value_type operator value_type() const noexcept"?
0199 // A: No. The rationale for endian_buffers is to prevent high-cost hidden
0200 //    conversions. If an implicit conversion operator is supplied, hidden conversions
0201 //    can occur.
0202 
0203 //  unaligned endian_buffer specialization
0204 
0205 template< order Order, class T, std::size_t n_bits >
0206 class endian_buffer<Order, T, n_bits, align::no>
0207 {
0208 #ifdef BOOST_ENDIAN_NO_CTORS
0209 public:
0210 #endif
0211 
0212     BOOST_ENDIAN_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
0213 
0214     unsigned char value_[ n_bits / 8 ];
0215 
0216 public:
0217 
0218     typedef T value_type;
0219 
0220 #ifndef BOOST_ENDIAN_NO_CTORS
0221 
0222     endian_buffer() = default;
0223 
0224     explicit endian_buffer( T val ) BOOST_NOEXCEPT
0225     {
0226         boost::endian::endian_store<T, n_bits / 8, Order>( value_, val );
0227     }
0228 
0229 #endif
0230 
0231     endian_buffer& operator=( T val ) BOOST_NOEXCEPT
0232     {
0233         boost::endian::endian_store<T, n_bits / 8, Order>( value_, val );
0234         return *this;
0235     }
0236 
0237     value_type value() const BOOST_NOEXCEPT
0238     {
0239         return boost::endian::endian_load<T, n_bits / 8, Order>( value_ );
0240     }
0241 
0242     unsigned char const * data() const BOOST_NOEXCEPT
0243     {
0244         return value_;
0245     }
0246 
0247     unsigned char * data() BOOST_NOEXCEPT
0248     {
0249         return value_;
0250     }
0251 };
0252 
0253 // aligned specializations; only n_bits == 16/32/64 supported
0254 
0255 // aligned endian_buffer specialization
0256 
0257 template< order Order, class T, std::size_t n_bits >
0258 class endian_buffer<Order, T, n_bits, align::yes>
0259 {
0260 private:
0261 
0262     BOOST_ENDIAN_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
0263     BOOST_ENDIAN_STATIC_ASSERT( sizeof(T) == n_bits/8 );
0264 
0265     union
0266     {
0267         unsigned char value_[ n_bits / 8 ];
0268         T align_;
0269     };
0270 
0271 public:
0272 
0273     typedef T value_type;
0274 
0275 #ifndef BOOST_ENDIAN_NO_CTORS
0276 
0277     endian_buffer() = default;
0278 
0279     explicit endian_buffer( T val ) BOOST_NOEXCEPT
0280     {
0281         boost::endian::endian_store<T, n_bits / 8, Order>( value_, val );
0282     }
0283 
0284 #endif
0285 
0286     endian_buffer& operator=( T val ) BOOST_NOEXCEPT
0287     {
0288         boost::endian::endian_store<T, n_bits / 8, Order>( value_, val );
0289         return *this;
0290     }
0291 
0292     value_type value() const BOOST_NOEXCEPT
0293     {
0294         return boost::endian::endian_load<T, n_bits / 8, Order>( value_ );
0295     }
0296 
0297     unsigned char const * data() const BOOST_NOEXCEPT
0298     {
0299         return value_;
0300     }
0301 
0302     unsigned char * data() BOOST_NOEXCEPT
0303     {
0304         return value_;
0305     }
0306 };
0307 
0308 // aligned native endian_buffer specialization
0309 
0310 template< class T, std::size_t n_bits >
0311 class endian_buffer<order::native, T, n_bits, align::yes>
0312 {
0313 private:
0314 
0315     BOOST_ENDIAN_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
0316     BOOST_ENDIAN_STATIC_ASSERT( sizeof(T) == n_bits/8 );
0317 
0318     T value_;
0319 
0320 public:
0321 
0322     typedef T value_type;
0323 
0324 #ifndef BOOST_ENDIAN_NO_CTORS
0325 
0326     endian_buffer() = default;
0327 
0328     explicit endian_buffer( T val ) BOOST_NOEXCEPT: value_( val )
0329     {
0330     }
0331 
0332 #endif
0333 
0334     endian_buffer& operator=( T val ) BOOST_NOEXCEPT
0335     {
0336         value_ = val;
0337         return *this;
0338     }
0339 
0340     value_type value() const BOOST_NOEXCEPT
0341     {
0342         return value_;
0343     }
0344 
0345     unsigned char const * data() const BOOST_NOEXCEPT
0346     {
0347         return reinterpret_cast< unsigned char const* >( &value_ );
0348     }
0349 
0350     unsigned char * data() BOOST_NOEXCEPT
0351     {
0352         return reinterpret_cast< unsigned char* >( &value_ );
0353     }
0354 };
0355 
0356 } // namespace endian
0357 } // namespace boost
0358 
0359 #if defined(BOOST_BORLANDC) || defined(BOOST_CODEGEARC)
0360 # pragma pack(pop)
0361 #endif
0362 
0363 #if defined(_MSC_VER)
0364 # pragma warning(pop)
0365 #endif
0366 
0367 #endif // BOOST_ENDIAN_BUFFERS_HPP