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