1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-25 02:04:23 +00:00
JUCE/src/core/juce_DataConversions.h
2009-10-12 13:40:26 +01:00

210 lines
9.4 KiB
C

/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-9 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE 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.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_DATACONVERSIONS_JUCEHEADER__
#define __JUCE_DATACONVERSIONS_JUCEHEADER__
#if JUCE_USE_INTRINSICS
#pragma intrinsic (_byteswap_ulong)
#endif
//==============================================================================
// Endianness conversions..
#if JUCE_IPHONE
// a gcc compiler error seems to mean that these functions only work properly
// on the iPhone if they are declared static..
static forcedinline uint32 swapByteOrder (uint32 n) throw();
static inline uint16 swapByteOrder (const uint16 n) throw();
static inline uint64 swapByteOrder (const uint64 value) throw();
#endif
/** Swaps the byte-order in an integer from little to big-endianness or vice-versa. */
forcedinline uint32 swapByteOrder (uint32 n) throw()
{
#if JUCE_MAC || JUCE_IPHONE
// Mac version
return OSSwapInt32 (n);
#elif JUCE_GCC
// Inpenetrable GCC version..
asm("bswap %%eax" : "=a"(n) : "a"(n));
return n;
#elif JUCE_USE_INTRINSICS
// Win32 intrinsics version..
return _byteswap_ulong (n);
#else
// Win32 version..
__asm {
mov eax, n
bswap eax
mov n, eax
}
return n;
#endif
}
/** Swaps the byte-order of a 16-bit short. */
inline uint16 swapByteOrder (const uint16 n) throw()
{
#if JUCE_USE_INTRINSICSxxx // agh - the MS compiler has an internal error when you try to use this intrinsic!
// Win32 intrinsics version..
return (uint16) _byteswap_ushort (n);
#else
return (uint16) ((n << 8) | (n >> 8));
#endif
}
inline uint64 swapByteOrder (const uint64 value) throw()
{
#if JUCE_MAC || JUCE_IPHONE
return OSSwapInt64 (value);
#elif JUCE_USE_INTRINSICS
return _byteswap_uint64 (value);
#else
return (((int64) swapByteOrder ((uint32) value)) << 32)
| swapByteOrder ((uint32) (value >> 32));
#endif
}
#if JUCE_LITTLE_ENDIAN
/** Swaps the byte order of a 16-bit int if the CPU is big-endian */
inline uint16 swapIfBigEndian (const uint16 v) throw() { return v; }
/** Swaps the byte order of a 32-bit int if the CPU is big-endian */
inline uint32 swapIfBigEndian (const uint32 v) throw() { return v; }
/** Swaps the byte order of a 64-bit int if the CPU is big-endian */
inline uint64 swapIfBigEndian (const uint64 v) throw() { return v; }
/** Swaps the byte order of a 16-bit int if the CPU is little-endian */
inline uint16 swapIfLittleEndian (const uint16 v) throw() { return swapByteOrder (v); }
/** Swaps the byte order of a 32-bit int if the CPU is little-endian */
inline uint32 swapIfLittleEndian (const uint32 v) throw() { return swapByteOrder (v); }
/** Swaps the byte order of a 64-bit int if the CPU is little-endian */
inline uint64 swapIfLittleEndian (const uint64 v) throw() { return swapByteOrder (v); }
/** Turns 4 bytes into a little-endian integer. */
inline uint32 littleEndianInt (const char* const bytes) throw() { return *(uint32*) bytes; }
/** Turns 2 bytes into a little-endian integer. */
inline uint16 littleEndianShort (const char* const bytes) throw() { return *(uint16*) bytes; }
/** Turns 4 bytes into a big-endian integer. */
inline uint32 bigEndianInt (const char* const bytes) throw() { return swapByteOrder (*(uint32*) bytes); }
/** Turns 2 bytes into a big-endian integer. */
inline uint16 bigEndianShort (const char* const bytes) throw() { return swapByteOrder (*(uint16*) bytes); }
#else
/** Swaps the byte order of a 16-bit int if the CPU is big-endian */
inline uint16 swapIfBigEndian (const uint16 v) throw() { return swapByteOrder (v); }
/** Swaps the byte order of a 32-bit int if the CPU is big-endian */
inline uint32 swapIfBigEndian (const uint32 v) throw() { return swapByteOrder (v); }
/** Swaps the byte order of a 64-bit int if the CPU is big-endian */
inline uint64 swapIfBigEndian (const uint64 v) throw() { return swapByteOrder (v); }
/** Swaps the byte order of a 16-bit int if the CPU is little-endian */
inline uint16 swapIfLittleEndian (const uint16 v) throw() { return v; }
/** Swaps the byte order of a 32-bit int if the CPU is little-endian */
inline uint32 swapIfLittleEndian (const uint32 v) throw() { return v; }
/** Swaps the byte order of a 64-bit int if the CPU is little-endian */
inline uint64 swapIfLittleEndian (const uint64 v) throw() { return v; }
/** Turns 4 bytes into a little-endian integer. */
inline uint32 littleEndianInt (const char* const bytes) throw() { return swapByteOrder (*(uint32*) bytes); }
/** Turns 2 bytes into a little-endian integer. */
inline uint16 littleEndianShort (const char* const bytes) throw() { return swapByteOrder (*(uint16*) bytes); }
/** Turns 4 bytes into a big-endian integer. */
inline uint32 bigEndianInt (const char* const bytes) throw() { return *(uint32*) bytes; }
/** Turns 2 bytes into a big-endian integer. */
inline uint16 bigEndianShort (const char* const bytes) throw() { return *(uint16*) bytes; }
#endif
/** Converts 3 little-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */
inline int littleEndian24Bit (const char* const bytes) throw() { return (((int) bytes[2]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[0]); }
/** Converts 3 big-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */
inline int bigEndian24Bit (const char* const bytes) throw() { return (((int) bytes[0]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[2]); }
/** Copies a 24-bit number to 3 little-endian bytes. */
inline void littleEndian24BitToChars (const int value, char* const destBytes) throw() { destBytes[0] = (char)(value & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)((value >> 16) & 0xff); }
/** Copies a 24-bit number to 3 big-endian bytes. */
inline void bigEndian24BitToChars (const int value, char* const destBytes) throw() { destBytes[0] = (char)((value >> 16) & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)(value & 0xff); }
//==============================================================================
/** Fast floating-point-to-integer conversion.
This is faster than using the normal c++ cast to convert a double to an int, and
it will round the value to the nearest integer, rather than rounding it down
like the normal cast does.
Note that this routine gets its speed at the expense of some accuracy, and when
rounding values whose floating point component is exactly 0.5, odd numbers and
even numbers will be rounded up or down differently. For a more accurate conversion,
see roundDoubleToIntAccurate().
*/
inline int roundDoubleToInt (const double value) throw()
{
union { int asInt[2]; double asDouble; } n;
n.asDouble = value + 6755399441055744.0;
#if JUCE_BIG_ENDIAN
return n.asInt [1];
#else
return n.asInt [0];
#endif
}
/** Fast floating-point-to-integer conversion.
This is a slightly slower and slightly more accurate version of roundDoubleToInt(). It works
fine for values above zero, but negative numbers are rounded the wrong way.
*/
inline int roundDoubleToIntAccurate (const double value) throw()
{
return roundDoubleToInt (value + 1.5e-8);
}
/** Fast floating-point-to-integer conversion.
This is faster than using the normal c++ cast to convert a float to an int, and
it will round the value to the nearest integer, rather than rounding it down
like the normal cast does.
Note that this routine gets its speed at the expense of some accuracy, and when
rounding values whose floating point component is exactly 0.5, odd numbers and
even numbers will be rounded up or down differently.
*/
inline int roundFloatToInt (const float value) throw()
{
union { int asInt[2]; double asDouble; } n;
n.asDouble = value + 6755399441055744.0;
#if JUCE_BIG_ENDIAN
return n.asInt [1];
#else
return n.asInt [0];
#endif
}
#endif // __JUCE_DATACONVERSIONS_JUCEHEADER__