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