summaryrefslogtreecommitdiff
path: root/libs/backends/wavesaudio/wavesapi/BasicTypes/WTByteOrder.h
blob: c217fa7a1cc36bd91dbf25df1b6e1520da5bfa71 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
    Copyright (C) 2014 Waves Audio Ltd.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#if !defined(__WTByteOrder_h__)
#define __WTByteOrder_h__

/* Copy to include
#include "BasicTypes/WTByteOrder.h"
*/

#include "WavesPublicAPI/wstdint.h"
#include "BasicTypes/WUDefines.h"

// Stuff concerning little/big endian and the conversion between them.
// most of the code here was copied from NetShell with some modifications
// Written by Udi on Nov-2005
// Adjusted to Cross platform by Shai Mar-2006

// Macros to determine endian.  __BIG_ENDIAN__ & __LITTLE_ENDIAN__ should come from the compiler.
// We try to set the macro _BYTEORDER_BIG_ENDIAN to 1 if big-endian or to 0 if little-endian.

// if the compiler properly has set either __BIG_ENDIAN__ or __LITTLE_ENDIAN__
#if defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__)
#if defined(__BIG_ENDIAN__) && defined(__LITTLE_ENDIAN__) //if both defined, check them as booleans
#if __BIG_ENDIAN__ && !__LITTLE_ENDIAN__
#define _BYTEORDER_BIG_ENDIAN 1
#elif !__BIG_ENDIAN__ && __LITTLE_ENDIAN__
#define _BYTEORDER_BIG_ENDIAN 0
#else
#error I am confused. Is this big-endian or little-endian?
#endif  // stupid compiler defines both __LITTLE_ENDIAN__ and __BIG_ENDIAN__
#elif defined(__BIG_ENDIAN__)
#define _BYTEORDER_BIG_ENDIAN 1
#else
#define _BYTEORDER_BIG_ENDIAN 0
#endif // big/little switch
#else // if the compiler proparly has NOT set either __BIG_ENDIAN__ or __LITTLE_ENDIAN__
// http://msdn.microsoft.com/en-us/library/b0084kay.aspx for all preprocessor defs. _M_X64: 64 bit. _M_IA64: Itanium 64bit
#if defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(__INTEL__) || defined(__x86_64__) || defined(_M_X64) || defined(_M_IA64)
#define _BYTEORDER_BIG_ENDIAN 0
#elif defined(_M_PPC) || defined(__POWERPC__ ) || defined(__ppc__)
#define _BYTEORDER_BIG_ENDIAN 1
#else
#error Cannot detect compiler byte-order. Please add a test for your compiler appropriate symbol to this header file.
#endif // symbol search
#endif // standard preprocessor symbol found

// code to determine which assembly code we can use
#if defined(_MSC_VER) && defined(_M_IX86)
#define _BYTEORDER_ASM_MSVC_I386  1  // Windows
#elif defined(__GNUC__) && defined(__i386__)
#define _BYTEORDER_ASM_GNUC_I386  1  // Linux, or MacOS with MacIntel on Xcode
#define _BYTEORDER_ASM_NONE		  1	 // Currently we have no assebley for GNU i386, so use the C version
#elif defined(__GNUC__) && defined(__POWERPC__)
#define _BYTEORDER_ASM_GNUC_PPC   1  // MacOS with PPC on Xcode
#define _BYTEORDER_ASM_NONE		  1	 // Currently we have no assebley for GNU PPC, so use the C version
#else
#define _BYTEORDER_ASM_NONE       1  // don't know the compiler and processor, use C implementation
#endif

namespace wvNS {

namespace wvBO // namespace Waves::ByteOrder
{
    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 :-)
    static const	byte_order_type byte_order_little_endian = 0;
    static const	byte_order_type byte_order_big_endian    = 1;


    // We try to use this static const rather than preprocessor symbols in our code wherever possible.
#if _BYTEORDER_BIG_ENDIAN == 1
    static const	byte_order_type compiler_byte_order = byte_order_big_endian;
#else
    static const	byte_order_type compiler_byte_order = byte_order_little_endian;
#endif


    //---------------------------------------------------------------------------------
    // swap functions - best if implemented in inline assembly code
    // The following are very slow swappers when compiled, do not use in loops
#if _BYTEORDER_ASM_MSVC_I386

    // assembly implementation for Intel386 on Visual Studio
    inline uint16_t swap16(uint16_t x)
    {
        __asm MOV AX,x;
        __asm XCHG AL,AH;
        __asm MOV x,AX;
        return x;
    }

    inline uint32_t swap32(uint32_t x)
    {
        __asm MOV EAX,x;
        __asm BSWAP EAX;
        __asm MOV x,EAX;
        return x;
    }
    inline uint64_t swap64(uint64_t x)  // TODO: To be replaced
    {
        return
            ((x>>7*8)&0xFF)<<0*8 | ((x>>6*8)&0xFF)<<1*8 | ((x>>5*8)&0xFF)<<2*8 | ((x>>4*8)&0xFF)<<3*8 |
            ((x>>3*8)&0xFF)<<4*8 | ((x>>2*8)&0xFF)<<5*8 | ((x>>1*8)&0xFF)<<6*8 | ((x>>0*8)&0xFF)<<7*8 ;
    }

    /* the ASM code for swap64 does not compile
    inline uint64_t swap64(uint64_t x)
    {
    __asm MOV EBX, OFFSET x;
    __asm MOV EAX, [EBX];
    __asm MOV EDX, [EBX+4];
    __asm BSWAP EAX;
    __asm BSWAP EDX;
    __asm MOV [EBX],EDX;
    __asm MOV [EBX+4],EAX;
    return x;
    }
    */
#endif // _BYTEORDER_ASM_MSVC_I386

#if _BYTEORDER_ASM_GNUC_I386
    // assembly implementation for Intel386 on GCC (Linux)
    // TODO
#endif // _BYTEORDER_ASM_GNUC_I386

#if _BYTEORDER_ASM_GNUC_PPC
    // assembly implementation for PowerPC on GCC (XCode)
    // TODO
#endif // _BYTEORDER_ASM_GNUC_PPC

#if _BYTEORDER_ASM_NONE
    inline uint16_t swap16(uint16_t x) { return (x>>8) | ((x&0xFF)<<8); }
    inline uint32_t swap32(uint32_t x) { return (x&0xFF)<<24 | (x&0xFF00)<<8 | (x&0xFF0000)>>8 | (x&0xFF000000)>>24; }
    inline uint64_t swap64(uint64_t x)
    {
        return
            ((x>>7*8)&0xFF)<<0*8 | ((x>>6*8)&0xFF)<<1*8 | ((x>>5*8)&0xFF)<<2*8 | ((x>>4*8)&0xFF)<<3*8 |
            ((x>>3*8)&0xFF)<<4*8 | ((x>>2*8)&0xFF)<<5*8 | ((x>>1*8)&0xFF)<<6*8 | ((x>>0*8)&0xFF)<<7*8 ;
    }
#endif // _BYTEORDER_ASM_NONE




    //---------------------------------------------------------------------------------

    // order conversion functions
    //    may want to overload for float and double as well.
    //    overload for signed ints is ambiguous and should be done only if no other choice exists.
    // - - - - - - - - - - - - - - - - - - - -
    inline uint16_t compiler_to_big_16(uint16_t x)
    {
        return compiler_byte_order==byte_order_big_endian ? x : swap16(x);
    }
    inline uint16_t big_to_compiler_16(uint16_t x)
    {
        return compiler_byte_order==byte_order_big_endian ? x : swap16(x);
    }
    inline uint16_t compiler_to_little_16(uint16_t x)
    {
        return compiler_byte_order==byte_order_little_endian ? x : swap16(x);
    }
    inline uint16_t little_to_compiler_16(uint16_t x)
    {
        return compiler_byte_order==byte_order_little_endian ? x : swap16(x);
    }
    // - - - - - - - - - - - - - - - - - - - -
    inline uint32_t compiler_to_big_32(uint32_t x)
    {
        return compiler_byte_order==byte_order_big_endian ? x : swap32(x);
    }
    inline uint32_t big_to_compiler_32(uint32_t x)
    {
        return compiler_byte_order==byte_order_big_endian ? x : swap32(x);
    }
    inline uint32_t compiler_to_little_32(uint32_t x)
    {
        return compiler_byte_order==byte_order_little_endian ? x : swap32(x);
    }
    inline uint32_t little_to_compiler_32(uint32_t x)
    {
        return compiler_byte_order==byte_order_little_endian ? x : swap32(x);
    }
    // - - - - - - - - - - - - - - - - - - - -
    inline uint64_t compiler_to_big_64(uint64_t x)
    {
        return compiler_byte_order==byte_order_big_endian ? x : swap64(x);
    }
    inline uint64_t big_to_compiler_64(uint64_t x)
    {
        return compiler_byte_order==byte_order_big_endian ? x : swap64(x);
    }
    inline uint64_t compiler_to_little_64(uint64_t x)
    {
        return compiler_byte_order==byte_order_little_endian ? x : swap64(x);
    }
    inline uint64_t little_to_compiler_64(uint64_t x)
    {
        return compiler_byte_order==byte_order_little_endian ? x : swap64(x);
    }

} // namespace wvBO

} // namespace wvNS {

#endif // #if !defined(__WTByteOrder_h__)