1 /* 2 Open Asset Import Library (assimp) 3 ---------------------------------------------------------------------- 4 5 Copyright (c) 2006-2015, assimp team 6 All rights reserved. 7 8 Redistribution and use of this software in source and binary forms, 9 with or without modification, are permitted provided that the 10 following conditions are met: 11 12 * Redistributions of source code must retain the above 13 copyright notice, this list of conditions and the 14 following disclaimer. 15 16 * Redistributions in binary form must reproduce the above 17 copyright notice, this list of conditions and the 18 following disclaimer in the documentation and/or other 19 materials provided with the distribution. 20 21 * Neither the name of the assimp team, nor the names of its 22 contributors may be used to endorse or promote products 23 derived from this software without specific prior 24 written permission of the assimp team. 25 26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 38 ---------------------------------------------------------------------- 39 */ 40 41 // Modified by Lasse Oorni for Urho3D 42 43 /** @file Helper class tp perform various byte oder swappings 44 (e.g. little to big endian) */ 45 #ifndef AI_BYTESWAPPER_H_INC 46 #define AI_BYTESWAPPER_H_INC 47 48 #include "../include/assimp/ai_assert.h" 49 #include "../include/assimp/types.h" 50 // Urho3D: VS2008 compatibility 51 #if !defined(_MSC_VER) || (_MSC_VER >= 1600) 52 #include <stdint.h> 53 #else 54 #include "../include/assimp/Compiler/pstdint.h" 55 #endif 56 57 #if _MSC_VER >= 1400 58 #include <stdlib.h> 59 #endif 60 61 namespace Assimp { 62 // -------------------------------------------------------------------------------------- 63 /** Defines some useful byte order swap routines. 64 * 65 * This is required to read big-endian model formats on little-endian machines, 66 * and vice versa. Direct use of this class is DEPRECATED. Use #StreamReader instead. */ 67 // -------------------------------------------------------------------------------------- 68 class ByteSwap 69 { ByteSwap()70 ByteSwap() {} 71 72 public: 73 74 // ---------------------------------------------------------------------- 75 /** Swap two bytes of data 76 * @param[inout] _szOut A void* to save the reintcasts for the caller. */ Swap2(void * _szOut)77 static inline void Swap2(void* _szOut) 78 { 79 ai_assert(_szOut); 80 81 #if _MSC_VER >= 1400 82 uint16_t* const szOut = reinterpret_cast<uint16_t*>(_szOut); 83 *szOut = _byteswap_ushort(*szOut); 84 #else 85 uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut); 86 std::swap(szOut[0],szOut[1]); 87 #endif 88 } 89 90 // ---------------------------------------------------------------------- 91 /** Swap four bytes of data 92 * @param[inout] _szOut A void* to save the reintcasts for the caller. */ Swap4(void * _szOut)93 static inline void Swap4(void* _szOut) 94 { 95 ai_assert(_szOut); 96 97 #if _MSC_VER >= 1400 98 uint32_t* const szOut = reinterpret_cast<uint32_t*>(_szOut); 99 *szOut = _byteswap_ulong(*szOut); 100 #else 101 uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut); 102 std::swap(szOut[0],szOut[3]); 103 std::swap(szOut[1],szOut[2]); 104 #endif 105 } 106 107 // ---------------------------------------------------------------------- 108 /** Swap eight bytes of data 109 * @param[inout] _szOut A void* to save the reintcasts for the caller. */ Swap8(void * _szOut)110 static inline void Swap8(void* _szOut) 111 { 112 ai_assert(_szOut); 113 114 #if _MSC_VER >= 1400 115 uint64_t* const szOut = reinterpret_cast<uint64_t*>(_szOut); 116 *szOut = _byteswap_uint64(*szOut); 117 #else 118 uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut); 119 std::swap(szOut[0],szOut[7]); 120 std::swap(szOut[1],szOut[6]); 121 std::swap(szOut[2],szOut[5]); 122 std::swap(szOut[3],szOut[4]); 123 #endif 124 } 125 126 // ---------------------------------------------------------------------- 127 /** ByteSwap a float. Not a joke. 128 * @param[inout] fOut ehm. .. */ Swap(float * fOut)129 static inline void Swap(float* fOut) { 130 Swap4(fOut); 131 } 132 133 // ---------------------------------------------------------------------- 134 /** ByteSwap a double. Not a joke. 135 * @param[inout] fOut ehm. .. */ Swap(double * fOut)136 static inline void Swap(double* fOut) { 137 Swap8(fOut); 138 } 139 140 141 // ---------------------------------------------------------------------- 142 /** ByteSwap an int16t. Not a joke. 143 * @param[inout] fOut ehm. .. */ Swap(int16_t * fOut)144 static inline void Swap(int16_t* fOut) { 145 Swap2(fOut); 146 } 147 Swap(uint16_t * fOut)148 static inline void Swap(uint16_t* fOut) { 149 Swap2(fOut); 150 } 151 152 // ---------------------------------------------------------------------- 153 /** ByteSwap an int32t. Not a joke. 154 * @param[inout] fOut ehm. .. */ Swap(int32_t * fOut)155 static inline void Swap(int32_t* fOut){ 156 Swap4(fOut); 157 } 158 Swap(uint32_t * fOut)159 static inline void Swap(uint32_t* fOut){ 160 Swap4(fOut); 161 } 162 163 // ---------------------------------------------------------------------- 164 /** ByteSwap an int64t. Not a joke. 165 * @param[inout] fOut ehm. .. */ Swap(int64_t * fOut)166 static inline void Swap(int64_t* fOut) { 167 Swap8(fOut); 168 } 169 Swap(uint64_t * fOut)170 static inline void Swap(uint64_t* fOut) { 171 Swap8(fOut); 172 } 173 174 // ---------------------------------------------------------------------- 175 //! Templatized ByteSwap 176 //! \returns param tOut as swapped 177 template<typename Type> Swapped(Type tOut)178 static inline Type Swapped(Type tOut) 179 { 180 return _swapper<Type,sizeof(Type)>()(tOut); 181 } 182 183 private: 184 185 template <typename T, size_t size> struct _swapper; 186 }; 187 188 template <typename T> struct ByteSwap::_swapper<T,2> { 189 T operator() (T tOut) { 190 Swap2(&tOut); 191 return tOut; 192 } 193 }; 194 195 template <typename T> struct ByteSwap::_swapper<T,4> { 196 T operator() (T tOut) { 197 Swap4(&tOut); 198 return tOut; 199 } 200 }; 201 202 template <typename T> struct ByteSwap::_swapper<T,8> { 203 T operator() (T tOut) { 204 Swap8(&tOut); 205 return tOut; 206 } 207 }; 208 209 210 // -------------------------------------------------------------------------------------- 211 // ByteSwap macros for BigEndian/LittleEndian support 212 // -------------------------------------------------------------------------------------- 213 #if (defined AI_BUILD_BIG_ENDIAN) 214 # define AI_LE(t) (t) 215 # define AI_BE(t) ByteSwap::Swapped(t) 216 # define AI_LSWAP2(p) 217 # define AI_LSWAP4(p) 218 # define AI_LSWAP8(p) 219 # define AI_LSWAP2P(p) 220 # define AI_LSWAP4P(p) 221 # define AI_LSWAP8P(p) 222 # define LE_NCONST const 223 # define AI_SWAP2(p) ByteSwap::Swap2(&(p)) 224 # define AI_SWAP4(p) ByteSwap::Swap4(&(p)) 225 # define AI_SWAP8(p) ByteSwap::Swap8(&(p)) 226 # define AI_SWAP2P(p) ByteSwap::Swap2((p)) 227 # define AI_SWAP4P(p) ByteSwap::Swap4((p)) 228 # define AI_SWAP8P(p) ByteSwap::Swap8((p)) 229 # define BE_NCONST 230 #else 231 # define AI_BE(t) (t) 232 # define AI_LE(t) ByteSwap::Swapped(t) 233 # define AI_SWAP2(p) 234 # define AI_SWAP4(p) 235 # define AI_SWAP8(p) 236 # define AI_SWAP2P(p) 237 # define AI_SWAP4P(p) 238 # define AI_SWAP8P(p) 239 # define BE_NCONST const 240 # define AI_LSWAP2(p) ByteSwap::Swap2(&(p)) 241 # define AI_LSWAP4(p) ByteSwap::Swap4(&(p)) 242 # define AI_LSWAP8(p) ByteSwap::Swap8(&(p)) 243 # define AI_LSWAP2P(p) ByteSwap::Swap2((p)) 244 # define AI_LSWAP4P(p) ByteSwap::Swap4((p)) 245 # define AI_LSWAP8P(p) ByteSwap::Swap8((p)) 246 # define LE_NCONST 247 #endif 248 249 250 namespace Intern { 251 252 // -------------------------------------------------------------------------------------------- 253 template <typename T, bool doit> 254 struct ByteSwapper { 255 void operator() (T* inout) { 256 ByteSwap::Swap(inout); 257 } 258 }; 259 260 template <typename T> 261 struct ByteSwapper<T,false> { 262 void operator() (T*) { 263 } 264 }; 265 266 // -------------------------------------------------------------------------------------------- 267 template <bool SwapEndianess, typename T, bool RuntimeSwitch> 268 struct Getter { 269 void operator() (T* inout, bool le) { 270 #ifdef AI_BUILD_BIG_ENDIAN 271 le = le; 272 #else 273 le = !le; 274 #endif 275 if (le) { 276 ByteSwapper<T,(sizeof(T)>1?true:false)> () (inout); 277 } 278 else ByteSwapper<T,false> () (inout); 279 } 280 }; 281 282 template <bool SwapEndianess, typename T> 283 struct Getter<SwapEndianess,T,false> { 284 285 void operator() (T* inout, bool /*le*/) { 286 // static branch 287 ByteSwapper<T,(SwapEndianess && sizeof(T)>1)> () (inout); 288 } 289 }; 290 } // end Intern 291 } // end Assimp 292 293 #endif //!! AI_BYTESWAPPER_H_INC 294