lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
|
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