lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
endianness.h
00001 /*****************************************************/
00002 /* lean IO                      (c) Tobias Zirr 2011 */
00003 /*****************************************************/
00004 
00005 #ifndef LEAN_IO_EDIANNESS
00006 #define LEAN_IO_EDIANNESS
00007 
00008 #include "../lean.h"
00009 
00010 #ifdef _MSC_VER
00011 
00012 #include <intrin.h>
00013 
00014 namespace lean
00015 {
00016 namespace io
00017 {
00018 namespace impl
00019 {
00020 
00022 __forceinline unsigned short byteswap(unsigned short value)
00023 {
00024     return _byteswap_ushort(value);
00025 }
00026 
00028 __forceinline unsigned long byteswap(unsigned long value)
00029 {
00030     return _byteswap_ulong(value);
00031 }
00032 
00034 __forceinline unsigned long long byteswap(unsigned long long value)
00035 {
00036     return _byteswap_uint64(value);
00037 }
00038 
00039 template <size_t Size>
00040 struct swap_type
00041 {
00042     // Always checked, therefore use static_assert with care
00043     LEAN_STATIC_ASSERT_MSG_ALT(Size & ~Size, // = false, dependent
00044         "Byte swap operations on values of the given type unsupported.",
00045         Byte_Swap_operations_on_values_of_the_given_type_unsupported);
00046 };
00047 
00048 template <> struct swap_type<sizeof(unsigned short)> { typedef unsigned short type; };
00049 template <> struct swap_type<sizeof(unsigned long)> { typedef unsigned long type; };
00050 template <> struct swap_type<sizeof(unsigned long long)> { typedef unsigned long long type; };
00051 
00052 } // namespace
00053 } // namespace
00054 } // namespace
00055 
00056 #else
00057 
00058 #error Unknown compiler, intrinsics unavailable.
00059 
00060 #endif
00061 
00062 namespace lean
00063 {
00064 namespace io
00065 {
00066 
00068 template <class Value>
00069 LEAN_INLINE Value byteswap(Value value)
00070 {
00071     typedef typename impl::swap_type<sizeof(Value)>::type swap_int;
00072 
00073     return reinterpret_cast<const Value&>(static_cast<const swap_int&>( impl::byteswap(
00074             reinterpret_cast<const swap_int&>(value) ) ));
00075 }
00076 
00078 template <class Value>
00079 LEAN_INLINE void byteswap(const Value *value, const Value *valueEnd, Value *dest)
00080 {
00081     LEAN_ASSERT(dest);
00082     LEAN_ASSERT(value);
00083     LEAN_ASSERT(value <= valueEnd);
00084 
00085     while (value != valueEnd)
00086         *(dest++) = byteswap(*(value++));
00087 }
00088 
00090 template <class Value>
00091 LEAN_INLINE void bytecopy(const Value *value, const Value *valueEnd, Value *dest)
00092 {
00093     LEAN_ASSERT(dest);
00094     LEAN_ASSERT(value);
00095     LEAN_ASSERT(value <= valueEnd);
00096 
00097     memcpy(dest, value, reinterpret_cast<const char*>(valueEnd) - reinterpret_cast<const char*>(value));
00098 }
00099 
00100 #ifndef LEAN_BIG_ENDIAN
00101 
00103 template <class Value>
00104 LEAN_INLINE Value byteswap_little(Value value)
00105 {
00106     return value;
00107 }
00108 
00110 template <class Value>
00111 LEAN_INLINE Value byteswap_big(Value value)
00112 {
00113     return byteswap(value);
00114 }
00115 
00117 template <class Value>
00118 LEAN_INLINE void byteswap_little(const Value *value, const Value *valueEnd, Value *dest)
00119 {
00120     bytecopy(value, valueEnd, dest);
00121 }
00122 
00124 template <class Value>
00125 LEAN_INLINE void byteswap_big(const Value *value, const Value *valueEnd, Value *dest)
00126 {
00127     byteswap(value, valueEnd, dest);
00128 }
00129 
00130 #else
00131 
00133 template <class Value>
00134 LEAN_INLINE Value byteswap_little(Value value)
00135 {
00136     return byteswap(value);
00137 }
00138 
00140 template <class Value>
00141 LEAN_INLINE Value byteswap_big(Value value)
00142 {
00143     return value;
00144 }
00145 
00147 template <class Value>
00148 LEAN_INLINE void byteswap_little(const Value *value, const Value *valueEnd, Value *dest)
00149 {
00150     byteswap(value, valueEnd, dest);
00151 }
00152 
00154 template <class Value>
00155 LEAN_INLINE void byteswap_big(const Value *value, const Value *valueEnd, Value *dest)
00156 {
00157     bytecopy(value, valueEnd, dest);
00158 }
00159 
00160 #endif
00161 
00162 } // namespace
00163 
00164 using io::byteswap;
00165 using io::byteswap_little;
00166 using io::byteswap_big;
00167 
00168 } // namespace
00169 
00170 #endif