PageRenderTime 78ms CodeModel.GetById 17ms app.highlight 55ms RepoModel.GetById 1ms app.codeStats 1ms

/src/contrib/boost/spirit/home/support/detail/integer/endian.hpp

http://pythonocc.googlecode.com/
C++ Header | 426 lines | 330 code | 56 blank | 40 comment | 21 complexity | f62f013424dbac334546abdf5660782d MD5 | raw file
  1//  Boost endian.hpp header file -------------------------------------------------------//
  2
  3//  (C) Copyright Darin Adler 2000
  4//  (C) Copyright Beman Dawes 2006, 2009
  5
  6//  Distributed under the Boost Software License, Version 1.0.
  7//  See http://www.boost.org/LICENSE_1_0.txt
  8
  9//  See library home page at http://www.boost.org/libs/endian
 10
 11//--------------------------------------------------------------------------------------//
 12
 13//  Original design developed by Darin Adler based on classes developed by Mark
 14//  Borgerding. Four original class templates were combined into a single endian
 15//  class template by Beman Dawes, who also added the unrolled_byte_loops sign
 16//  partial specialization to correctly extend the sign when cover integer size
 17//  differs from endian representation size.
 18
 19// TODO: When a compiler supporting constexpr becomes available, try possible uses.
 20
 21#ifndef BOOST_SPIRIT_ENDIAN_HPP
 22#define BOOST_SPIRIT_ENDIAN_HPP
 23
 24#if defined(_MSC_VER)
 25#pragma once
 26#endif
 27
 28#ifdef BOOST_ENDIAN_LOG
 29# include <iostream>
 30#endif
 31
 32#if defined(__BORLANDC__) || defined( __CODEGEARC__)
 33# pragma pack(push, 1)
 34#endif
 35
 36#include <boost/config.hpp>
 37#include <boost/detail/endian.hpp>
 38#define BOOST_MINIMAL_INTEGER_COVER_OPERATORS
 39#define BOOST_NO_IO_COVER_OPERATORS
 40#include <boost/spirit/home/support/detail/integer/cover_operators.hpp>
 41#undef  BOOST_NO_IO_COVER_OPERATORS
 42#undef  BOOST_MINIMAL_INTEGER_COVER_OPERATORS
 43#include <boost/type_traits/is_signed.hpp>
 44#include <boost/cstdint.hpp>
 45#include <boost/static_assert.hpp>
 46#include <boost/spirit/home/support/detail/scoped_enum_emulation.hpp>
 47#include <iosfwd>
 48#include <climits>
 49
 50# if CHAR_BIT != 8
 51#   error Platforms with CHAR_BIT != 8 are not supported
 52# endif
 53
 54# define BOOST_ENDIAN_DEFAULT_CONSTRUCT {}          // C++03
 55
 56# if defined(BOOST_ENDIAN_FORCE_PODNESS)
 57#   define BOOST_ENDIAN_NO_CTORS
 58# endif
 59
 60
 61namespace boost
 62{
 63  namespace detail
 64  {
 65    // Unrolled loops for loading and storing streams of bytes.
 66
 67    template <typename T, std::size_t n_bytes,
 68      bool sign=boost::is_signed<T>::value >
 69    struct unrolled_byte_loops
 70    {
 71      typedef unrolled_byte_loops<T, n_bytes - 1, sign> next;
 72
 73      static T load_big(const unsigned char* bytes)
 74        { return *(bytes - 1) | (next::load_big(bytes - 1) << 8); }
 75      static T load_little(const unsigned char* bytes)
 76        { return *bytes | (next::load_little(bytes + 1) << 8); }
 77
 78      static void store_big(char* bytes, T value)
 79        {
 80          *(bytes - 1) = static_cast<char>(value);
 81          next::store_big(bytes - 1, value >> 8);
 82        }
 83      static void store_little(char* bytes, T value)
 84        {
 85          *bytes = static_cast<char>(value);
 86          next::store_little(bytes + 1, value >> 8);
 87        }
 88    };
 89
 90    template <typename T>
 91    struct unrolled_byte_loops<T, 1, false>
 92    {
 93      static T load_big(const unsigned char* bytes)
 94        { return *(bytes - 1); }
 95      static T load_little(const unsigned char* bytes)
 96        { return *bytes; }
 97      static void store_big(char* bytes, T value)
 98        { *(bytes - 1) = static_cast<char>(value); }
 99      static void store_little(char* bytes, T value)
100        { *bytes = static_cast<char>(value); }
101
102    };
103
104    template <typename T>
105    struct unrolled_byte_loops<T, 1, true>
106    {
107      static T load_big(const unsigned char* bytes)
108        { return *reinterpret_cast<const signed char*>(bytes - 1); }
109      static T load_little(const unsigned char* bytes)
110        { return *reinterpret_cast<const signed char*>(bytes); }
111      static void store_big(char* bytes, T value)
112        { *(bytes - 1) = static_cast<char>(value); }
113      static void store_little(char* bytes, T value)
114        { *bytes = static_cast<char>(value); }
115    };
116
117    template <typename T, std::size_t n_bytes>
118    inline
119    T load_big_endian(const void* bytes)
120    {
121      return unrolled_byte_loops<T, n_bytes>::load_big
122        (static_cast<const unsigned char*>(bytes) + n_bytes);
123    }
124
125    template <typename T, std::size_t n_bytes>
126    inline
127    T load_little_endian(const void* bytes)
128    {
129      return unrolled_byte_loops<T, n_bytes>::load_little
130        (static_cast<const unsigned char*>(bytes));
131    }
132
133    template <typename T, std::size_t n_bytes>
134    inline
135    void store_big_endian(void* bytes, T value)
136    {
137      unrolled_byte_loops<T, n_bytes>::store_big
138        (static_cast<char*>(bytes) + n_bytes, value);
139    }
140
141    template <typename T, std::size_t n_bytes>
142    inline
143    void store_little_endian(void* bytes, T value)
144    {
145      unrolled_byte_loops<T, n_bytes>::store_little
146        (static_cast<char*>(bytes), value);
147    }
148
149  } // namespace detail
150
151  namespace integer
152  {
153
154# ifdef BOOST_ENDIAN_LOG
155    bool endian_log(true);
156# endif
157
158
159  //  endian class template and specializations  ---------------------------------------//
160
161  BOOST_SCOPED_ENUM_START(endianness) { big, little, native }; BOOST_SCOPED_ENUM_END
162  BOOST_SCOPED_ENUM_START(alignment) { unaligned, aligned }; BOOST_SCOPED_ENUM_END
163
164  template <BOOST_SCOPED_ENUM(endianness) E, typename T, std::size_t n_bits,
165    BOOST_SCOPED_ENUM(alignment) A = alignment::unaligned>
166    class endian;
167
168    //  Specializations that represent unaligned bytes.
169    //  Taking an integer type as a parameter provides a nice way to pass both
170    //  the size and signedness of the desired integer and get the appropriate
171    //  corresponding integer type for the interface.
172
173    //  unaligned big endian specialization
174    template <typename T, std::size_t n_bits>
175    class endian< endianness::big, T, n_bits, alignment::unaligned >
176      : cover_operators< endian< endianness::big, T, n_bits >, T >
177    {
178        BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
179      public:
180        typedef T value_type;
181#     ifndef BOOST_ENDIAN_NO_CTORS
182        endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT
183        explicit endian(T val)
184        { 
185#       ifdef BOOST_ENDIAN_LOG
186          if ( endian_log )
187            std::clog << "big, unaligned, " << n_bits << "-bits, construct(" << val << ")\n";
188#       endif
189          detail::store_big_endian<T, n_bits/8>(m_value, val);
190        }
191#     endif
192        endian & operator=(T val) { detail::store_big_endian<T, n_bits/8>(m_value, val); return *this; }
193        operator T() const
194        { 
195#       ifdef BOOST_ENDIAN_LOG
196          if ( endian_log )
197            std::clog << "big, unaligned, " << n_bits << "-bits, convert(" << detail::load_big_endian<T, n_bits/8>(m_value) << ")\n";
198#       endif
199          return detail::load_big_endian<T, n_bits/8>(m_value);
200        }
201      private:
202        char m_value[n_bits/8];
203    };
204
205    //  unaligned little endian specialization
206    template <typename T, std::size_t n_bits>
207    class endian< endianness::little, T, n_bits, alignment::unaligned >
208      : cover_operators< endian< endianness::little, T, n_bits >, T >
209    {
210        BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
211      public:
212        typedef T value_type;
213#     ifndef BOOST_ENDIAN_NO_CTORS
214        endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT
215        explicit endian(T val)
216        { 
217#       ifdef BOOST_ENDIAN_LOG
218          if ( endian_log )
219            std::clog << "little, unaligned, " << n_bits << "-bits, construct(" << val << ")\n";
220#       endif
221          detail::store_little_endian<T, n_bits/8>(m_value, val);
222        }
223#     endif
224        endian & operator=(T val) { detail::store_little_endian<T, n_bits/8>(m_value, val); return *this; }
225        operator T() const
226        { 
227#       ifdef BOOST_ENDIAN_LOG
228          if ( endian_log )
229            std::clog << "little, unaligned, " << n_bits << "-bits, convert(" << detail::load_little_endian<T, n_bits/8>(m_value) << ")\n";
230#       endif
231          return detail::load_little_endian<T, n_bits/8>(m_value);
232        }
233      private:
234        char m_value[n_bits/8];
235    };
236
237    //  unaligned native endian specialization
238    template <typename T, std::size_t n_bits>
239    class endian< endianness::native, T, n_bits, alignment::unaligned >
240      : cover_operators< endian< endianness::native, T, n_bits >, T >
241    {
242        BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
243      public:
244        typedef T value_type;
245#   ifndef BOOST_ENDIAN_NO_CTORS
246        endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT
247#     ifdef BOOST_BIG_ENDIAN
248        explicit endian(T val)    { detail::store_big_endian<T, n_bits/8>(m_value, val); }
249#     else
250        explicit endian(T val)    { detail::store_little_endian<T, n_bits/8>(m_value, val); }
251#     endif
252#   endif
253#   ifdef BOOST_BIG_ENDIAN  
254        endian & operator=(T val) { detail::store_big_endian<T, n_bits/8>(m_value, val); return *this; }
255        operator T() const        { return detail::load_big_endian<T, n_bits/8>(m_value); }
256#   else
257        endian & operator=(T val) { detail::store_little_endian<T, n_bits/8>(m_value, val); return *this; }
258        operator T() const        { return detail::load_little_endian<T, n_bits/8>(m_value); }
259#   endif
260      private:
261        char m_value[n_bits/8];
262    };
263
264    //  Specializations that mimic built-in integer types.
265    //  These typically have the same alignment as the underlying types.
266
267    //  aligned big endian specialization
268    template <typename T, std::size_t n_bits>
269    class endian< endianness::big, T, n_bits, alignment::aligned  >
270      : cover_operators< endian< endianness::big, T, n_bits, alignment::aligned >, T >
271    {
272        BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
273        BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
274      public:
275        typedef T value_type;
276#   ifndef BOOST_ENDIAN_NO_CTORS
277        endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT
278#     ifdef BOOST_BIG_ENDIAN
279        endian(T val) : m_value(val) { }
280#     else
281        explicit endian(T val)    { detail::store_big_endian<T, sizeof(T)>(&m_value, val); }
282#     endif
283#   endif
284#   ifdef BOOST_BIG_ENDIAN  
285        endian & operator=(T val) { m_value = val; return *this; }
286        operator T() const        { return m_value; }
287#   else  
288        endian & operator=(T val) { detail::store_big_endian<T, sizeof(T)>(&m_value, val); return *this; }
289        operator T() const        { return detail::load_big_endian<T, sizeof(T)>(&m_value); }
290#   endif  
291      private:
292        T m_value;
293    };
294
295    //  aligned little endian specialization
296    template <typename T, std::size_t n_bits>
297    class endian< endianness::little, T, n_bits, alignment::aligned  >
298      : cover_operators< endian< endianness::little, T, n_bits, alignment::aligned >, T >
299    {
300        BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
301        BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
302      public:
303        typedef T value_type;
304#   ifndef BOOST_ENDIAN_NO_CTORS
305        endian() BOOST_ENDIAN_DEFAULT_CONSTRUCT
306#     ifdef BOOST_LITTLE_ENDIAN
307        endian(T val) : m_value(val) { }
308#     else
309        explicit endian(T val)    { detail::store_little_endian<T, sizeof(T)>(&m_value, val); }
310#     endif
311#   endif
312#   ifdef BOOST_LITTLE_ENDIAN
313        endian & operator=(T val) { m_value = val; return *this; }
314        operator T() const        { return m_value; }
315    #else
316        endian & operator=(T val) { detail::store_little_endian<T, sizeof(T)>(&m_value, val); return *this; }
317        operator T() const        { return detail::load_little_endian<T, sizeof(T)>(&m_value); }
318    #endif
319      private:
320        T m_value;
321    };
322
323  //  naming convention typedefs  ------------------------------------------------------//
324
325    // unaligned big endian signed integer types
326    typedef endian< endianness::big, int_least8_t, 8 >           big8_t;
327    typedef endian< endianness::big, int_least16_t, 16 >         big16_t;
328    typedef endian< endianness::big, int_least32_t, 24 >         big24_t;
329    typedef endian< endianness::big, int_least32_t, 32 >         big32_t;
330    typedef endian< endianness::big, int_least64_t, 40 >         big40_t;
331    typedef endian< endianness::big, int_least64_t, 48 >         big48_t;
332    typedef endian< endianness::big, int_least64_t, 56 >         big56_t;
333    typedef endian< endianness::big, int_least64_t, 64 >         big64_t;
334
335    // unaligned big endian unsigned integer types
336    typedef endian< endianness::big, uint_least8_t, 8 >          ubig8_t;
337    typedef endian< endianness::big, uint_least16_t, 16 >        ubig16_t;
338    typedef endian< endianness::big, uint_least32_t, 24 >        ubig24_t;
339    typedef endian< endianness::big, uint_least32_t, 32 >        ubig32_t;
340    typedef endian< endianness::big, uint_least64_t, 40 >        ubig40_t;
341    typedef endian< endianness::big, uint_least64_t, 48 >        ubig48_t;
342    typedef endian< endianness::big, uint_least64_t, 56 >        ubig56_t;
343    typedef endian< endianness::big, uint_least64_t, 64 >        ubig64_t;
344
345    // unaligned little endian signed integer types
346    typedef endian< endianness::little, int_least8_t, 8 >        little8_t;
347    typedef endian< endianness::little, int_least16_t, 16 >      little16_t;
348    typedef endian< endianness::little, int_least32_t, 24 >      little24_t;
349    typedef endian< endianness::little, int_least32_t, 32 >      little32_t;
350    typedef endian< endianness::little, int_least64_t, 40 >      little40_t;
351    typedef endian< endianness::little, int_least64_t, 48 >      little48_t;
352    typedef endian< endianness::little, int_least64_t, 56 >      little56_t;
353    typedef endian< endianness::little, int_least64_t, 64 >      little64_t;
354
355    // unaligned little endian unsigned integer types
356    typedef endian< endianness::little, uint_least8_t, 8 >       ulittle8_t;
357    typedef endian< endianness::little, uint_least16_t, 16 >     ulittle16_t;
358    typedef endian< endianness::little, uint_least32_t, 24 >     ulittle24_t;
359    typedef endian< endianness::little, uint_least32_t, 32 >     ulittle32_t;
360    typedef endian< endianness::little, uint_least64_t, 40 >     ulittle40_t;
361    typedef endian< endianness::little, uint_least64_t, 48 >     ulittle48_t;
362    typedef endian< endianness::little, uint_least64_t, 56 >     ulittle56_t;
363    typedef endian< endianness::little, uint_least64_t, 64 >     ulittle64_t;
364
365    // unaligned native endian signed integer types
366    typedef endian< endianness::native, int_least8_t, 8 >        native8_t;
367    typedef endian< endianness::native, int_least16_t, 16 >      native16_t;
368    typedef endian< endianness::native, int_least32_t, 24 >      native24_t;
369    typedef endian< endianness::native, int_least32_t, 32 >      native32_t;
370    typedef endian< endianness::native, int_least64_t, 40 >      native40_t;
371    typedef endian< endianness::native, int_least64_t, 48 >      native48_t;
372    typedef endian< endianness::native, int_least64_t, 56 >      native56_t;
373    typedef endian< endianness::native, int_least64_t, 64 >      native64_t;
374
375    // unaligned native endian unsigned integer types
376    typedef endian< endianness::native, uint_least8_t, 8 >       unative8_t;
377    typedef endian< endianness::native, uint_least16_t, 16 >     unative16_t;
378    typedef endian< endianness::native, uint_least32_t, 24 >     unative24_t;
379    typedef endian< endianness::native, uint_least32_t, 32 >     unative32_t;
380    typedef endian< endianness::native, uint_least64_t, 40 >     unative40_t;
381    typedef endian< endianness::native, uint_least64_t, 48 >     unative48_t;
382    typedef endian< endianness::native, uint_least64_t, 56 >     unative56_t;
383    typedef endian< endianness::native, uint_least64_t, 64 >     unative64_t;
384
385#define BOOST_HAS_INT16_T
386#define BOOST_HAS_INT32_T
387#define BOOST_HAS_INT64_T
388  
389  //  These types only present if platform has exact size integers:
390  //     aligned big endian signed integer types
391  //     aligned big endian unsigned integer types
392  //     aligned little endian signed integer types
393  //     aligned little endian unsigned integer types
394
395  //     aligned native endian typedefs are not provided because
396  //     <cstdint> types are superior for this use case
397
398# if defined(BOOST_HAS_INT16_T)
399    typedef endian< endianness::big, int16_t, 16, alignment::aligned >      aligned_big16_t;
400    typedef endian< endianness::big, uint16_t, 16, alignment::aligned >     aligned_ubig16_t;
401    typedef endian< endianness::little, int16_t, 16, alignment::aligned >   aligned_little16_t;
402    typedef endian< endianness::little, uint16_t, 16, alignment::aligned >  aligned_ulittle16_t;
403# endif
404
405# if defined(BOOST_HAS_INT32_T)
406    typedef endian< endianness::big, int32_t, 32, alignment::aligned >      aligned_big32_t;
407    typedef endian< endianness::big, uint32_t, 32, alignment::aligned >     aligned_ubig32_t;
408    typedef endian< endianness::little, int32_t, 32, alignment::aligned >   aligned_little32_t;
409    typedef endian< endianness::little, uint32_t, 32, alignment::aligned >  aligned_ulittle32_t;
410# endif
411
412# if defined(BOOST_HAS_INT64_T)
413    typedef endian< endianness::big, int64_t, 64, alignment::aligned >      aligned_big64_t;
414    typedef endian< endianness::big, uint64_t, 64, alignment::aligned >     aligned_ubig64_t;
415    typedef endian< endianness::little, int64_t, 64, alignment::aligned >   aligned_little64_t;
416    typedef endian< endianness::little, uint64_t, 64, alignment::aligned >  aligned_ulittle64_t;
417# endif
418
419  } // namespace integer
420} // namespace boost
421
422#if defined(__BORLANDC__) || defined( __CODEGEARC__)
423# pragma pack(pop)
424#endif
425
426#endif // BOOST_SPIRIT_ENDIAN_HPP