13
0
livetrax/libs/backends/wavesaudio/wavesapi/BasicTypes/WTByteOrder.h
Paul Davis 000609901b add correct copyright statements to all files in Waves backend except those derived from portaudio/portmidi
This follows the letter sent from Waves Audio Ltd. to Paul Davis dated February 20th 2014 agreeing to release this code
under the GNU Public License, version 2, with copyright owned by Waves Audio Ltd
2014-10-07 16:17:34 -04:00

224 lines
8.1 KiB
C++

/*
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__)