supernova: c++11 compile fixes
[supercollider.git] / external_libraries / boost_endian / boost / integer / endian.hpp
blobb267b84a7722cf4c4bd15a17f5d45d1668f0c5d7
1 // Boost endian.hpp header file -------------------------------------------------------//
3 // (C) Copyright Darin Adler 2000
4 // (C) Copyright Beman Dawes 2006, 2009
6 // Distributed under the Boost Software License, Version 1.0.
7 // See http://www.boost.org/LICENSE_1_0.txt
9 // See library home page at http://www.boost.org/libs/endian
11 //--------------------------------------------------------------------------------------//
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.
19 // TODO: When a compiler supporting constexpr becomes available, try possible uses.
21 #ifndef BOOST_ENDIAN_HPP
22 #define BOOST_ENDIAN_HPP
24 #ifdef BOOST_ENDIAN_LOG
25 # include <iostream>
26 #endif
28 #if defined(__BORLANDC__) || defined( __CODEGEARC__)
29 # pragma pack(push, 1)
30 #endif
32 #include <boost/config.hpp>
33 #include <boost/detail/endian.hpp>
34 #define BOOST_MINIMAL_INTEGER_COVER_OPERATORS
35 #define BOOST_NO_IO_COVER_OPERATORS
36 #include <boost/integer/cover_operators.hpp>
37 #undef BOOST_NO_IO_COVER_OPERATORS
38 #undef BOOST_MINIMAL_INTEGER_COVER_OPERATORS
39 #include <boost/type_traits/is_signed.hpp>
40 #include <boost/cstdint.hpp>
41 #include <boost/static_assert.hpp>
42 #include <boost/detail/scoped_enum_emulation.hpp>
43 #include <iosfwd>
44 #include <climits>
46 # if CHAR_BIT != 8
47 # error Platforms with CHAR_BIT != 8 are not supported
48 # endif
50 # ifdef BOOST_NO_DEFAULTED_FUNCTIONS
51 # define BOOST_ENDIAN_DEFAULT_CONSTRUCT {} // C++03
52 # else
53 # define BOOST_ENDIAN_DEFAULT_CONSTRUCT = default; // C++0x
54 # endif
56 # if defined(BOOST_NO_DEFAULTED_FUNCTIONS) && defined(BOOST_ENDIAN_FORCE_PODNESS)
57 # define BOOST_ENDIAN_NO_CTORS
58 # endif
61 namespace boost
63 namespace detail
65 // Unrolled loops for loading and storing streams of bytes.
67 template <typename T, std::size_t n_bytes,
68 bool sign=boost::is_signed<T>::value >
69 struct unrolled_byte_loops
71 typedef unrolled_byte_loops<T, n_bytes - 1, sign> next;
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); }
78 static void store_big(char* bytes, T value)
80 *(bytes - 1) = static_cast<char>(value);
81 next::store_big(bytes - 1, value >> 8);
83 static void store_little(char* bytes, T value)
85 *bytes = static_cast<char>(value);
86 next::store_little(bytes + 1, value >> 8);
90 template <typename T>
91 struct unrolled_byte_loops<T, 1, false>
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); }
104 template <typename T>
105 struct unrolled_byte_loops<T, 1, true>
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); }
117 template <typename T, std::size_t n_bytes>
118 inline
119 T load_big_endian(const void* bytes)
121 return unrolled_byte_loops<T, n_bytes>::load_big
122 (static_cast<const unsigned char*>(bytes) + n_bytes);
125 template <typename T, std::size_t n_bytes>
126 inline
127 T load_little_endian(const void* bytes)
129 return unrolled_byte_loops<T, n_bytes>::load_little
130 (static_cast<const unsigned char*>(bytes));
133 template <typename T, std::size_t n_bytes>
134 inline
135 void store_big_endian(void* bytes, T value)
137 unrolled_byte_loops<T, n_bytes>::store_big
138 (static_cast<char*>(bytes) + n_bytes, value);
141 template <typename T, std::size_t n_bytes>
142 inline
143 void store_little_endian(void* bytes, T value)
145 unrolled_byte_loops<T, n_bytes>::store_little
146 (static_cast<char*>(bytes), value);
149 } // namespace detail
151 namespace integer
154 # ifdef BOOST_ENDIAN_LOG
155 bool endian_log(true);
156 # endif
159 // endian class template and specializations ---------------------------------------//
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
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;
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.
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 >
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)
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);
191 # endif
192 endian & operator=(T val) { detail::store_big_endian<T, n_bits/8>(m_value, val); return *this; }
193 operator T() const
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);
201 private:
202 char m_value[n_bits/8];
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 >
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)
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);
223 # endif
224 endian & operator=(T val) { detail::store_little_endian<T, n_bits/8>(m_value, val); return *this; }
225 operator T() const
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);
233 private:
234 char m_value[n_bits/8];
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 >
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];
264 // Specializations that mimic built-in integer types.
265 // These typically have the same alignment as the underlying types.
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 >
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;
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 >
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;
323 // naming convention typedefs ------------------------------------------------------//
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;
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;
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;
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;
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;
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;
385 #define BOOST_HAS_INT16_T
386 #define BOOST_HAS_INT32_T
387 #define BOOST_HAS_INT64_T
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
395 // aligned native endian typedefs are not provided because
396 // <cstdint> types are superior for this use case
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
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
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
419 } // namespace integer
420 } // namespace boost
422 #if defined(__BORLANDC__) || defined( __CODEGEARC__)
423 # pragma pack(pop)
424 #endif
426 #endif // BOOST_ENDIAN_HPP