2 Copyright (C) 2014 Waves Audio Ltd.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #if !defined(__WTByteOrder_h__)
21 #define __WTByteOrder_h__
24 #include "BasicTypes/WTByteOrder.h"
27 #include "WavesPublicAPI/wstdint.h"
28 #include "BasicTypes/WUDefines.h"
30 // Stuff concerning little/big endian and the conversion between them.
31 // most of the code here was copied from NetShell with some modifications
32 // Written by Udi on Nov-2005
33 // Adjusted to Cross platform by Shai Mar-2006
35 // Macros to determine endian. __BIG_ENDIAN__ & __LITTLE_ENDIAN__ should come from the compiler.
36 // We try to set the macro _BYTEORDER_BIG_ENDIAN to 1 if big-endian or to 0 if little-endian.
38 // if the compiler properly has set either __BIG_ENDIAN__ or __LITTLE_ENDIAN__
39 #if defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__)
40 #if defined(__BIG_ENDIAN__) && defined(__LITTLE_ENDIAN__) //if both defined, check them as booleans
41 #if __BIG_ENDIAN__ && !__LITTLE_ENDIAN__
42 #define _BYTEORDER_BIG_ENDIAN 1
43 #elif !__BIG_ENDIAN__ && __LITTLE_ENDIAN__
44 #define _BYTEORDER_BIG_ENDIAN 0
46 #error I am confused. Is this big-endian or little-endian?
47 #endif // stupid compiler defines both __LITTLE_ENDIAN__ and __BIG_ENDIAN__
48 #elif defined(__BIG_ENDIAN__)
49 #define _BYTEORDER_BIG_ENDIAN 1
51 #define _BYTEORDER_BIG_ENDIAN 0
52 #endif // big/little switch
53 #else // if the compiler proparly has NOT set either __BIG_ENDIAN__ or __LITTLE_ENDIAN__
54 // http://msdn.microsoft.com/en-us/library/b0084kay.aspx for all preprocessor defs. _M_X64: 64 bit. _M_IA64: Itanium 64bit
55 #if defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(__INTEL__) || defined(__x86_64__) || defined(_M_X64) || defined(_M_IA64)
56 #define _BYTEORDER_BIG_ENDIAN 0
57 #elif defined(_M_PPC) || defined(__POWERPC__ ) || defined(__ppc__)
58 #define _BYTEORDER_BIG_ENDIAN 1
60 #error Cannot detect compiler byte-order. Please add a test for your compiler appropriate symbol to this header file.
61 #endif // symbol search
62 #endif // standard preprocessor symbol found
64 // code to determine which assembly code we can use
65 #if defined(_MSC_VER) && defined(_M_IX86)
66 #define _BYTEORDER_ASM_MSVC_I386 1 // Windows
67 #elif defined(__GNUC__) && defined(__i386__)
68 #define _BYTEORDER_ASM_GNUC_I386 1 // Linux, or MacOS with MacIntel on Xcode
69 #define _BYTEORDER_ASM_NONE 1 // Currently we have no assebley for GNU i386, so use the C version
70 #elif defined(__GNUC__) && defined(__POWERPC__)
71 #define _BYTEORDER_ASM_GNUC_PPC 1 // MacOS with PPC on Xcode
72 #define _BYTEORDER_ASM_NONE 1 // Currently we have no assebley for GNU PPC, so use the C version
74 #define _BYTEORDER_ASM_NONE 1 // don't know the compiler and processor, use C implementation
79 namespace wvBO // namespace Waves::ByteOrder
81 typedef int byte_order_type; // we use int rather than enum because some compilers cannot resolve enum constants at compile-time. There are only two options anyway :-)
82 static const byte_order_type byte_order_little_endian = 0;
83 static const byte_order_type byte_order_big_endian = 1;
86 // We try to use this static const rather than preprocessor symbols in our code wherever possible.
87 #if _BYTEORDER_BIG_ENDIAN == 1
88 static const byte_order_type compiler_byte_order = byte_order_big_endian;
90 static const byte_order_type compiler_byte_order = byte_order_little_endian;
94 //---------------------------------------------------------------------------------
95 // swap functions - best if implemented in inline assembly code
96 // The following are very slow swappers when compiled, do not use in loops
97 #if _BYTEORDER_ASM_MSVC_I386
99 // assembly implementation for Intel386 on Visual Studio
100 inline uint16_t swap16(uint16_t x)
108 inline uint32_t swap32(uint32_t x)
115 inline uint64_t swap64(uint64_t x) // TODO: To be replaced
118 ((x>>7*8)&0xFF)<<0*8 | ((x>>6*8)&0xFF)<<1*8 | ((x>>5*8)&0xFF)<<2*8 | ((x>>4*8)&0xFF)<<3*8 |
119 ((x>>3*8)&0xFF)<<4*8 | ((x>>2*8)&0xFF)<<5*8 | ((x>>1*8)&0xFF)<<6*8 | ((x>>0*8)&0xFF)<<7*8 ;
122 /* the ASM code for swap64 does not compile
123 inline uint64_t swap64(uint64_t x)
125 __asm MOV EBX, OFFSET x;
126 __asm MOV EAX, [EBX];
127 __asm MOV EDX, [EBX+4];
131 __asm MOV [EBX+4],EAX;
135 #endif // _BYTEORDER_ASM_MSVC_I386
137 #if _BYTEORDER_ASM_GNUC_I386
138 // assembly implementation for Intel386 on GCC (Linux)
140 #endif // _BYTEORDER_ASM_GNUC_I386
142 #if _BYTEORDER_ASM_GNUC_PPC
143 // assembly implementation for PowerPC on GCC (XCode)
145 #endif // _BYTEORDER_ASM_GNUC_PPC
147 #if _BYTEORDER_ASM_NONE
148 inline uint16_t swap16(uint16_t x) { return (x>>8) | ((x&0xFF)<<8); }
149 inline uint32_t swap32(uint32_t x) { return (x&0xFF)<<24 | (x&0xFF00)<<8 | (x&0xFF0000)>>8 | (x&0xFF000000)>>24; }
150 inline uint64_t swap64(uint64_t x)
153 ((x>>7*8)&0xFF)<<0*8 | ((x>>6*8)&0xFF)<<1*8 | ((x>>5*8)&0xFF)<<2*8 | ((x>>4*8)&0xFF)<<3*8 |
154 ((x>>3*8)&0xFF)<<4*8 | ((x>>2*8)&0xFF)<<5*8 | ((x>>1*8)&0xFF)<<6*8 | ((x>>0*8)&0xFF)<<7*8 ;
156 #endif // _BYTEORDER_ASM_NONE
161 //---------------------------------------------------------------------------------
163 // order conversion functions
164 // may want to overload for float and double as well.
165 // overload for signed ints is ambiguous and should be done only if no other choice exists.
166 // - - - - - - - - - - - - - - - - - - - -
167 inline uint16_t compiler_to_big_16(uint16_t x)
169 return compiler_byte_order==byte_order_big_endian ? x : swap16(x);
171 inline uint16_t big_to_compiler_16(uint16_t x)
173 return compiler_byte_order==byte_order_big_endian ? x : swap16(x);
175 inline uint16_t compiler_to_little_16(uint16_t x)
177 return compiler_byte_order==byte_order_little_endian ? x : swap16(x);
179 inline uint16_t little_to_compiler_16(uint16_t x)
181 return compiler_byte_order==byte_order_little_endian ? x : swap16(x);
183 // - - - - - - - - - - - - - - - - - - - -
184 inline uint32_t compiler_to_big_32(uint32_t x)
186 return compiler_byte_order==byte_order_big_endian ? x : swap32(x);
188 inline uint32_t big_to_compiler_32(uint32_t x)
190 return compiler_byte_order==byte_order_big_endian ? x : swap32(x);
192 inline uint32_t compiler_to_little_32(uint32_t x)
194 return compiler_byte_order==byte_order_little_endian ? x : swap32(x);
196 inline uint32_t little_to_compiler_32(uint32_t x)
198 return compiler_byte_order==byte_order_little_endian ? x : swap32(x);
200 // - - - - - - - - - - - - - - - - - - - -
201 inline uint64_t compiler_to_big_64(uint64_t x)
203 return compiler_byte_order==byte_order_big_endian ? x : swap64(x);
205 inline uint64_t big_to_compiler_64(uint64_t x)
207 return compiler_byte_order==byte_order_big_endian ? x : swap64(x);
209 inline uint64_t compiler_to_little_64(uint64_t x)
211 return compiler_byte_order==byte_order_little_endian ? x : swap64(x);
213 inline uint64_t little_to_compiler_64(uint64_t x)
215 return compiler_byte_order==byte_order_little_endian ? x : swap64(x);
220 } // namespace wvNS {
222 #endif // #if !defined(__WTByteOrder_h__)