// © Copyright 2006-2010, Terry Golubiewski, all rights reserved. #ifndef BOOST_INTERFACE_ENDIAN_H #define BOOST_INTERFACE_ENDIAN_H #pragma once #include #include #include #include #include #include namespace boost { namespace interface { struct uninitialized_t { }; static const uninitialized_t uninitialized; /// Endian type enumeration. enum endian_t { little, big }; #ifdef BOOST_BIG_ENDIAN static const endian_t native = big; #else static const endian_t native = little; #endif namespace detail { #ifndef NDEBUG // Check (at runtime) that BOOST_BIG_ENDIAN and "native" are set correctly. namespace { const unsigned short Dummy = 1; const endian_t ActualEndian = bool(*reinterpret_cast(&Dummy)) ? little : big; int InitDummy2() { assert(ActualEndian == native); return 0; } // InitDummy2() const int Dummy2 = InitDummy2(); } // static #endif template inline void unrolled_reverse_copy(char* dst, const char* src) { *dst = *src; unrolled_reverse_copy(dst+1, src-1); } // unrolled_reverse_copy template<> inline void unrolled_reverse_copy<1>(char* dst, const char* src) { *dst = *src; } template<> inline void unrolled_reverse_copy<0>(char*, const char*) { } template struct reverse_copy_helper { static void copy(char* dst, const char* src) { std::reverse_copy(src, src+L, dst); } }; template struct reverse_copy_helper { static void copy(char* dst, const char* src) { unrolled_reverse_copy(dst, src+(L-1)); } }; template inline void reverse_copy(void* dst, const void* src) { reverse_copy_helper< L, (L<=16) >::copy(static_cast(dst), static_cast(src)); } } // detail #pragma pack(push, 1) template class endian { public: static const endian_t endian_type = E; typedef T value_type; private: char m_storage[sizeof(value_type)]; void store(const value_type& v) { detail::reverse_copy(m_storage, &v); } void retrieve(value_type* result) const { detail::reverse_copy(result, m_storage); } public: endian() { store(value_type()); } endian(uninitialized_t) { } endian(const value_type& x) { store(x); } value_type value() const { value_type rval; retrieve(&rval); return rval; } operator value_type() const { return value(); } endian& operator=(const value_type& rhs) { store(rhs); return *this; } }; // endian // Specialize for native endian. template class endian { public: static const endian_t endian_type = native; typedef T value_type; private: value_type m_value; public: endian() : m_value() { } endian(uninitialized_t) { } endian(const value_type& x) : m_value(x) { } const value_type& value() const { return m_value; } operator value_type() const { return value(); } endian& operator=(const value_type& rhs) { m_value = rhs; return *this; } }; // endian #pragma pack(pop) template inline endian* copy(const endian* first_, const endian* last_, endian* dest_) { if ((void*) first_ == (void*) dest_) { if (E1 == E2) return dest_ + (last_ - first_); if (E2 != native) { while (first_ != last_) { T tmp = *first_++; *dest_++ = tmp; } return dest_; } } while (first_ != last_) *dest_++ = *first_++; return dest_; } // copy template inline endian* copy(const T* first_, const T* last_, endian* dest_) { if ((void*) first_ == (void*) dest_) { if (E == native) return dest_ + (last_ - first_); while (first_ != last_) { T tmp = *first_++; *dest_++ = tmp; } } else { while (first_ != last_) *dest_++ = *first_++; } return dest_; } // copy template inline T* copy(const endian* first_, const endian* last_, T* dest_) { if (E == native && (void*) first_ == (void*) dest_) return dest_ + (last_ - first_); while (first_ != last_) *dest_++ = *first_++; return dest_; } // copy /// @name Convenient Typedefs /// Use these convenient typedefs to save typing. //@{ typedef endian little_int8_t; typedef endian little_int16_t; typedef endian little_int32_t; typedef endian little_int64_t; typedef endian little_uint8_t; typedef endian little_uint16_t; typedef endian little_uint32_t; typedef endian little_uint64_t; typedef endian big_int8_t; typedef endian big_int16_t; typedef endian big_int32_t; typedef endian big_int64_t; typedef endian big_uint8_t; typedef endian big_uint16_t; typedef endian big_uint32_t; typedef endian big_uint64_t; typedef endian native_int8_t; typedef endian native_int16_t; typedef endian native_int32_t; typedef endian native_int64_t; typedef endian native_uint8_t; typedef endian native_uint16_t; typedef endian native_uint32_t; typedef endian native_uint64_t; typedef endian little_float; typedef endian big_float; typedef endian native_float; typedef endian little_double; typedef endian big_double; typedef endian native_double; //@} } } // boost::interface #endif