1 //  boost/endian/arithmetic.hpp  -------------------------------------------------------//
2 
3 //  (C) Copyright Darin Adler 2000
4 //  (C) Copyright Beman Dawes 2006, 2009, 2014
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_ENDIAN_ARITHMETIC_HPP
22 #define BOOST_ENDIAN_ARITHMETIC_HPP
23 
24 #if defined(_MSC_VER)
25 # pragma warning(push)
26 # pragma warning(disable:4365)  // conversion ... signed/unsigned mismatch
27 #endif
28 
29 #ifdef BOOST_ENDIAN_LOG
30 # include <iostream>
31 #endif
32 
33 #if defined(__BORLANDC__) || defined( __CODEGEARC__)
34 # pragma pack(push, 1)
35 #endif
36 
37 #include <boost/config.hpp>
38 #include <boost/predef/detail/endian_compat.h>
39 #include <boost/endian/conversion.hpp>
40 #include <boost/endian/buffers.hpp>
41 #define  BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
42 #include <boost/endian/detail/cover_operators.hpp>
43 #undef   BOOST_ENDIAN_MINIMAL_COVER_OPERATORS
44 #include <boost/type_traits/is_signed.hpp>
45 #include <boost/cstdint.hpp>
46 #include <boost/static_assert.hpp>
47 #include <boost/core/scoped_enum.hpp>
48 #include <iosfwd>
49 #include <climits>
50 
51 # if CHAR_BIT != 8
52 #   error Platforms with CHAR_BIT != 8 are not supported
53 # endif
54 
55 # ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
56 #   define BOOST_ENDIAN_DEFAULT_CONSTRUCT {}          // C++03
57 # else
58 #   define BOOST_ENDIAN_DEFAULT_CONSTRUCT = default;  // C++0x
59 # endif
60 
61 # if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && defined(BOOST_ENDIAN_FORCE_PODNESS)
62 #   define BOOST_ENDIAN_NO_CTORS
63 # endif
64 
65 # ifndef BOOST_ENDIAN_EXPLICIT_CTORS
66 #   define BOOST_ENDIAN_EXPLICIT_OPT
67 # else
68 #   define BOOST_ENDIAN_EXPLICIT_OPT explicit
69 # endif
70 
71 //----------------------------------  synopsis  ----------------------------------------//
72 
73 namespace boost
74 {
75 namespace endian
76 {
77 
78   template <BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits,
79     BOOST_SCOPED_ENUM(align) A = align::no>
80       class endian_arithmetic;
81 
82   // big endian signed integer aligned types
83   typedef endian_arithmetic<order::big, int8_t, 8, align::yes>        big_int8_at;
84   typedef endian_arithmetic<order::big, int16_t, 16, align::yes>      big_int16_at;
85   typedef endian_arithmetic<order::big, int32_t, 32, align::yes>      big_int32_at;
86   typedef endian_arithmetic<order::big, int64_t, 64, align::yes>      big_int64_at;
87 
88   // big endian unsigned integer aligned types
89   typedef endian_arithmetic<order::big, uint8_t, 8, align::yes>       big_uint8_at;
90   typedef endian_arithmetic<order::big, uint16_t, 16, align::yes>     big_uint16_at;
91   typedef endian_arithmetic<order::big, uint32_t, 32, align::yes>     big_uint32_at;
92   typedef endian_arithmetic<order::big, uint64_t, 64, align::yes>     big_uint64_at;
93 
94   // little endian signed integer aligned types
95   typedef endian_arithmetic<order::little, int8_t, 8, align::yes>     little_int8_at;
96   typedef endian_arithmetic<order::little, int16_t, 16, align::yes>   little_int16_at;
97   typedef endian_arithmetic<order::little, int32_t, 32, align::yes>   little_int32_at;
98   typedef endian_arithmetic<order::little, int64_t, 64, align::yes>   little_int64_at;
99 
100   // little endian unsigned integer aligned types
101   typedef endian_arithmetic<order::little, uint8_t, 8, align::yes>    little_uint8_at;
102   typedef endian_arithmetic<order::little, uint16_t, 16, align::yes>  little_uint16_at;
103   typedef endian_arithmetic<order::little, uint32_t, 32, align::yes>  little_uint32_at;
104   typedef endian_arithmetic<order::little, uint64_t, 64, align::yes>  little_uint64_at;
105 
106   // aligned native endian typedefs are not provided because
107   // <cstdint> types are superior for this use case
108 
109   // big endian signed integer unaligned types
110   typedef endian_arithmetic<order::big, int_least8_t, 8>        big_int8_t;
111   typedef endian_arithmetic<order::big, int_least16_t, 16>      big_int16_t;
112   typedef endian_arithmetic<order::big, int_least32_t, 24>      big_int24_t;
113   typedef endian_arithmetic<order::big, int_least32_t, 32>      big_int32_t;
114   typedef endian_arithmetic<order::big, int_least64_t, 40>      big_int40_t;
115   typedef endian_arithmetic<order::big, int_least64_t, 48>      big_int48_t;
116   typedef endian_arithmetic<order::big, int_least64_t, 56>      big_int56_t;
117   typedef endian_arithmetic<order::big, int_least64_t, 64>      big_int64_t;
118 
119   // big endian unsigned integer unaligned types
120   typedef endian_arithmetic<order::big, uint_least8_t, 8>       big_uint8_t;
121   typedef endian_arithmetic<order::big, uint_least16_t, 16>     big_uint16_t;
122   typedef endian_arithmetic<order::big, uint_least32_t, 24>     big_uint24_t;
123   typedef endian_arithmetic<order::big, uint_least32_t, 32>     big_uint32_t;
124   typedef endian_arithmetic<order::big, uint_least64_t, 40>     big_uint40_t;
125   typedef endian_arithmetic<order::big, uint_least64_t, 48>     big_uint48_t;
126   typedef endian_arithmetic<order::big, uint_least64_t, 56>     big_uint56_t;
127   typedef endian_arithmetic<order::big, uint_least64_t, 64>     big_uint64_t;
128 
129   // little endian signed integer unaligned types
130   typedef endian_arithmetic<order::little, int_least8_t, 8>     little_int8_t;
131   typedef endian_arithmetic<order::little, int_least16_t, 16>   little_int16_t;
132   typedef endian_arithmetic<order::little, int_least32_t, 24>   little_int24_t;
133   typedef endian_arithmetic<order::little, int_least32_t, 32>   little_int32_t;
134   typedef endian_arithmetic<order::little, int_least64_t, 40>   little_int40_t;
135   typedef endian_arithmetic<order::little, int_least64_t, 48>   little_int48_t;
136   typedef endian_arithmetic<order::little, int_least64_t, 56>   little_int56_t;
137   typedef endian_arithmetic<order::little, int_least64_t, 64>   little_int64_t;
138 
139   // little endian unsigned integer unaligned types
140   typedef endian_arithmetic<order::little, uint_least8_t, 8>    little_uint8_t;
141   typedef endian_arithmetic<order::little, uint_least16_t, 16>  little_uint16_t;
142   typedef endian_arithmetic<order::little, uint_least32_t, 24>  little_uint24_t;
143   typedef endian_arithmetic<order::little, uint_least32_t, 32>  little_uint32_t;
144   typedef endian_arithmetic<order::little, uint_least64_t, 40>  little_uint40_t;
145   typedef endian_arithmetic<order::little, uint_least64_t, 48>  little_uint48_t;
146   typedef endian_arithmetic<order::little, uint_least64_t, 56>  little_uint56_t;
147   typedef endian_arithmetic<order::little, uint_least64_t, 64>  little_uint64_t;
148 
149 # ifdef BOOST_BIG_ENDIAN
150   // native endian signed integer unaligned types
151   typedef big_int8_t   native_int8_t;
152   typedef big_int16_t  native_int16_t;
153   typedef big_int24_t  native_int24_t;
154   typedef big_int32_t  native_int32_t;
155   typedef big_int40_t  native_int40_t;
156   typedef big_int48_t  native_int48_t;
157   typedef big_int56_t  native_int56_t;
158   typedef big_int64_t  native_int64_t;
159 
160   // native endian unsigned integer unaligned types
161   typedef big_uint8_t   native_uint8_t;
162   typedef big_uint16_t  native_uint16_t;
163   typedef big_uint24_t  native_uint24_t;
164   typedef big_uint32_t  native_uint32_t;
165   typedef big_uint40_t  native_uint40_t;
166   typedef big_uint48_t  native_uint48_t;
167   typedef big_uint56_t  native_uint56_t;
168   typedef big_uint64_t  native_uint64_t;
169 # else
170   // native endian signed integer unaligned types
171   typedef little_int8_t   native_int8_t;
172   typedef little_int16_t  native_int16_t;
173   typedef little_int24_t  native_int24_t;
174   typedef little_int32_t  native_int32_t;
175   typedef little_int40_t  native_int40_t;
176   typedef little_int48_t  native_int48_t;
177   typedef little_int56_t  native_int56_t;
178   typedef little_int64_t  native_int64_t;
179 
180   // native endian unsigned integer unaligned types
181   typedef little_uint8_t   native_uint8_t;
182   typedef little_uint16_t  native_uint16_t;
183   typedef little_uint24_t  native_uint24_t;
184   typedef little_uint32_t  native_uint32_t;
185   typedef little_uint40_t  native_uint40_t;
186   typedef little_uint48_t  native_uint48_t;
187   typedef little_uint56_t  native_uint56_t;
188   typedef little_uint64_t  native_uint64_t;
189 # endif
190 
191 # ifdef BOOST_ENDIAN_DEPRECATED_NAMES
192 
193   typedef order endianness;
194   typedef align alignment;
195 
196 # ifndef  BOOST_NO_CXX11_TEMPLATE_ALIASES
197   template <BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits,
198     BOOST_SCOPED_ENUM(align) Align = align::no>
199   using endian = endian_arithmetic<Order, T, n_bits, Align>;
200 # endif
201 
202   // unaligned big endian signed integer types
203   typedef endian_arithmetic< order::big, int_least8_t, 8 >           big8_t;
204   typedef endian_arithmetic< order::big, int_least16_t, 16 >         big16_t;
205   typedef endian_arithmetic< order::big, int_least32_t, 24 >         big24_t;
206   typedef endian_arithmetic< order::big, int_least32_t, 32 >         big32_t;
207   typedef endian_arithmetic< order::big, int_least64_t, 40 >         big40_t;
208   typedef endian_arithmetic< order::big, int_least64_t, 48 >         big48_t;
209   typedef endian_arithmetic< order::big, int_least64_t, 56 >         big56_t;
210   typedef endian_arithmetic< order::big, int_least64_t, 64 >         big64_t;
211 
212   // unaligned big endian_arithmetic unsigned integer types
213   typedef endian_arithmetic< order::big, uint_least8_t, 8 >          ubig8_t;
214   typedef endian_arithmetic< order::big, uint_least16_t, 16 >        ubig16_t;
215   typedef endian_arithmetic< order::big, uint_least32_t, 24 >        ubig24_t;
216   typedef endian_arithmetic< order::big, uint_least32_t, 32 >        ubig32_t;
217   typedef endian_arithmetic< order::big, uint_least64_t, 40 >        ubig40_t;
218   typedef endian_arithmetic< order::big, uint_least64_t, 48 >        ubig48_t;
219   typedef endian_arithmetic< order::big, uint_least64_t, 56 >        ubig56_t;
220   typedef endian_arithmetic< order::big, uint_least64_t, 64 >        ubig64_t;
221 
222   // unaligned little endian_arithmetic signed integer types
223   typedef endian_arithmetic< order::little, int_least8_t, 8 >        little8_t;
224   typedef endian_arithmetic< order::little, int_least16_t, 16 >      little16_t;
225   typedef endian_arithmetic< order::little, int_least32_t, 24 >      little24_t;
226   typedef endian_arithmetic< order::little, int_least32_t, 32 >      little32_t;
227   typedef endian_arithmetic< order::little, int_least64_t, 40 >      little40_t;
228   typedef endian_arithmetic< order::little, int_least64_t, 48 >      little48_t;
229   typedef endian_arithmetic< order::little, int_least64_t, 56 >      little56_t;
230   typedef endian_arithmetic< order::little, int_least64_t, 64 >      little64_t;
231 
232   // unaligned little endian_arithmetic unsigned integer types
233   typedef endian_arithmetic< order::little, uint_least8_t, 8 >       ulittle8_t;
234   typedef endian_arithmetic< order::little, uint_least16_t, 16 >     ulittle16_t;
235   typedef endian_arithmetic< order::little, uint_least32_t, 24 >     ulittle24_t;
236   typedef endian_arithmetic< order::little, uint_least32_t, 32 >     ulittle32_t;
237   typedef endian_arithmetic< order::little, uint_least64_t, 40 >     ulittle40_t;
238   typedef endian_arithmetic< order::little, uint_least64_t, 48 >     ulittle48_t;
239   typedef endian_arithmetic< order::little, uint_least64_t, 56 >     ulittle56_t;
240   typedef endian_arithmetic< order::little, uint_least64_t, 64 >     ulittle64_t;
241 
242   // unaligned native endian_arithmetic signed integer types
243   typedef endian_arithmetic< order::native, int_least8_t, 8 >        native8_t;
244   typedef endian_arithmetic< order::native, int_least16_t, 16 >      native16_t;
245   typedef endian_arithmetic< order::native, int_least32_t, 24 >      native24_t;
246   typedef endian_arithmetic< order::native, int_least32_t, 32 >      native32_t;
247   typedef endian_arithmetic< order::native, int_least64_t, 40 >      native40_t;
248   typedef endian_arithmetic< order::native, int_least64_t, 48 >      native48_t;
249   typedef endian_arithmetic< order::native, int_least64_t, 56 >      native56_t;
250   typedef endian_arithmetic< order::native, int_least64_t, 64 >      native64_t;
251 
252   // unaligned native endian_arithmetic unsigned integer types
253   typedef endian_arithmetic< order::native, uint_least8_t, 8 >       unative8_t;
254   typedef endian_arithmetic< order::native, uint_least16_t, 16 >     unative16_t;
255   typedef endian_arithmetic< order::native, uint_least32_t, 24 >     unative24_t;
256   typedef endian_arithmetic< order::native, uint_least32_t, 32 >     unative32_t;
257   typedef endian_arithmetic< order::native, uint_least64_t, 40 >     unative40_t;
258   typedef endian_arithmetic< order::native, uint_least64_t, 48 >     unative48_t;
259   typedef endian_arithmetic< order::native, uint_least64_t, 56 >     unative56_t;
260   typedef endian_arithmetic< order::native, uint_least64_t, 64 >     unative64_t;
261 
262   //     aligned native endian_arithmetic typedefs are not provided because
263   //     <cstdint> types are superior for this use case
264 
265   typedef endian_arithmetic< order::big, int16_t, 16, align::yes >      aligned_big16_t;
266   typedef endian_arithmetic< order::big, uint16_t, 16, align::yes >     aligned_ubig16_t;
267   typedef endian_arithmetic< order::little, int16_t, 16, align::yes >   aligned_little16_t;
268   typedef endian_arithmetic< order::little, uint16_t, 16, align::yes >  aligned_ulittle16_t;
269 
270   typedef endian_arithmetic< order::big, int32_t, 32, align::yes >      aligned_big32_t;
271   typedef endian_arithmetic< order::big, uint32_t, 32, align::yes >     aligned_ubig32_t;
272   typedef endian_arithmetic< order::little, int32_t, 32, align::yes >   aligned_little32_t;
273   typedef endian_arithmetic< order::little, uint32_t, 32, align::yes >  aligned_ulittle32_t;
274 
275   typedef endian_arithmetic< order::big, int64_t, 64, align::yes >      aligned_big64_t;
276   typedef endian_arithmetic< order::big, uint64_t, 64, align::yes >     aligned_ubig64_t;
277   typedef endian_arithmetic< order::little, int64_t, 64, align::yes >   aligned_little64_t;
278   typedef endian_arithmetic< order::little, uint64_t, 64, align::yes >  aligned_ulittle64_t;
279 
280 # endif
281 
282 //----------------------------------  end synopsis  ------------------------------------//
283 
284 //  endian class template specializations  ---------------------------------------------//
285 
286     //  Specializations that represent unaligned bytes.
287     //  Taking an integer type as a parameter provides a nice way to pass both
288     //  the size and signness of the desired integer and get the appropriate
289     //  corresponding integer type for the interface.
290 
291     //  unaligned integer big endian specialization
292     template <typename T, std::size_t n_bits>
293     class endian_arithmetic< order::big, T, n_bits, align::no >
294       : public endian_buffer< order::big, T, n_bits, align::no >,
295         cover_operators<endian_arithmetic<order::big, T, n_bits>, T>
296     {
297         BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
298       public:
299         typedef T value_type;
300 #     ifndef BOOST_ENDIAN_NO_CTORS
endian_arithmetic()301         endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
302         BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT
303         {
304 #       ifdef BOOST_ENDIAN_LOG
305           if ( endian_log )
306             std::cout << "big, unaligned, " << n_bits << "-bits, construct(" << val << ")\n";
307 #       endif
308           detail::store_big_endian<T, n_bits/8>(this->m_value, val);
309         }
310 #     endif
operator =(T val)311         endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
312           { detail::store_big_endian<T, n_bits/8>(this->m_value, val); return *this; }
operator value_type() const313         operator value_type() const BOOST_NOEXCEPT { return this->value(); }
314     };
315 
316     //  unaligned little endian specialization
317     template <typename T, std::size_t n_bits>
318     class endian_arithmetic< order::little, T, n_bits, align::no >
319       : public endian_buffer< order::little, T, n_bits, align::no >,
320         cover_operators< endian_arithmetic< order::little, T, n_bits >, T >
321     {
322         BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
323       public:
324         typedef T value_type;
325 #     ifndef BOOST_ENDIAN_NO_CTORS
endian_arithmetic()326         endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
327         BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT
328         {
329 #       ifdef BOOST_ENDIAN_LOG
330           if ( endian_log )
331             std::cout << "little, unaligned, " << n_bits << "-bits, construct(" << val << ")\n";
332 #       endif
333           detail::store_little_endian<T, n_bits/8>(this->m_value, val);
334         }
335 #     endif
operator =(T val)336         endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
337           { detail::store_little_endian<T, n_bits/8>(this->m_value, val); return *this; }
operator value_type() const338         operator value_type() const BOOST_NOEXCEPT { return this->value(); }
339     };
340 
341   //  align::yes specializations; only n_bits == 16/32/64 supported
342 
343     //  aligned big endian specialization
344     template <typename T, std::size_t n_bits>
345     class endian_arithmetic<order::big, T, n_bits, align::yes>
346       : public endian_buffer< order::big, T, n_bits, align::yes >,
347         cover_operators<endian_arithmetic<order::big, T, n_bits, align::yes>, T>
348     {
349         BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
350         BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
351       public:
352         typedef T value_type;
353 #     ifndef BOOST_ENDIAN_NO_CTORS
endian_arithmetic()354         endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
355         BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT
356         {
357 #       ifdef BOOST_ENDIAN_LOG
358           if ( endian_log )
359             std::cout << "big, aligned, " << n_bits << "-bits, construct(" << val << ")\n";
360 #       endif
361           this->m_value = ::boost::endian::native_to_big(val);
362         }
363 
364 #     endif
operator =(T val)365         endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
366         {
367           this->m_value = ::boost::endian::native_to_big(val);
368           return *this;
369         }
operator value_type() const370         operator value_type() const BOOST_NOEXCEPT { return this->value(); }
371     };
372 
373     //  aligned little endian specialization
374     template <typename T, std::size_t n_bits>
375     class endian_arithmetic<order::little, T, n_bits, align::yes>
376       : public endian_buffer< order::little, T, n_bits, align::yes >,
377         cover_operators<endian_arithmetic<order::little, T, n_bits, align::yes>, T>
378     {
379         BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits );
380         BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 );
381       public:
382         typedef T value_type;
383 #     ifndef BOOST_ENDIAN_NO_CTORS
endian_arithmetic()384         endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT
385         BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT
386         {
387 #       ifdef BOOST_ENDIAN_LOG
388           if ( endian_log )
389             std::cout << "little, aligned, " << n_bits << "-bits, construct(" << val << ")\n";
390 #       endif
391           this->m_value = ::boost::endian::native_to_little(val);
392         }
393 #     endif
operator =(T val)394         endian_arithmetic& operator=(T val) BOOST_NOEXCEPT
395         {
396           this->m_value = ::boost::endian::native_to_little(val);
397           return *this;
398         }
operator value_type() const399         operator value_type() const BOOST_NOEXCEPT { return this->value(); }
400     };
401 
402 } // namespace endian
403 } // namespace boost
404 
405 #if defined(__BORLANDC__) || defined( __CODEGEARC__)
406 # pragma pack(pop)
407 #endif
408 
409 #if defined(_MSC_VER)
410 # pragma warning(pop)
411 #endif
412 
413 #endif // BOOST_ENDIAN_ARITHMETIC_HPP
414