Merge pull request #132 from TsudaKageyu/byteswap

Add cross-platform byte order conversions
This commit is contained in:
Tsuda Kageyu 2013-04-15 08:26:32 -07:00
commit f0edca2f8c
6 changed files with 249 additions and 64 deletions

View File

@ -50,6 +50,7 @@ set(tag_HDRS
toolkit/tmap.h
toolkit/tmap.tcc
toolkit/tpropertymap.h
toolkit/tbyteswap.h
mpeg/mpegfile.h
mpeg/mpegproperties.h
mpeg/mpegheader.h
@ -289,6 +290,7 @@ set(toolkit_SRCS
toolkit/tfilestream.cpp
toolkit/tdebug.cpp
toolkit/tpropertymap.cpp
toolkit/tbyteswap.cpp
toolkit/unicode.cpp
)

View File

@ -43,6 +43,7 @@
#endif
#include <string>
#include <climits>
#ifdef __APPLE__
# include <libkern/OSAtomic.h>
@ -75,6 +76,30 @@
*/
#endif
// Check the widths of integral types.
#if UCHAR_MAX != 255U
# error TagLib assumes that char is 8-bit wide.
#endif
#if USHRT_MAX != 65535U
# error TagLib assumes that short is 16-bit wide.
#endif
#if UINT_MAX != 4294967295U
# error TagLib assumes that int is 32-bit wide.
#endif
#if !defined(ULLONG_MAX) && !defined(ULONGLONG_MAX) && !defined(ULONG_LONG_MAX)
# error TagLib assumes that long long is 64-bit wide.
#elif defined(ULLONG_MAX) && ULLONG_MAX != 18446744073709551615ULL
# error TagLib assumes that long long is 64-bit wide.
#elif defined(ULONGLONG_MAX) && ULONGLONG_MAX != 18446744073709551615ULL
# error TagLib assumes that long long is 64-bit wide.
#elif defined(ULONG_LONG_MAX) && ULONG_LONG_MAX != 18446744073709551615ULL
# error TagLib assumes that long long is 64-bit wide.
#endif
//! A namespace for all TagLib related classes and functions
/*!
@ -89,10 +114,13 @@ namespace TagLib {
class String;
typedef wchar_t wchar;
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef wchar_t wchar; // Assumed to be sufficient to store a UTF-16 char.
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long long ulonglong;
// long/ulong can be either 32-bit or 64-bit wide.
typedef unsigned long ulong;
/*!

View File

@ -0,0 +1,160 @@
/***************************************************************************
copyright : (C) 2013 by Tsuda Kageyu
email : tsuda.kageyu@gmail.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include "taglib.h"
#include "tbyteswap.h"
// Determines if compiler intrinsic functions are available.
// MSVC: Intrinsic _byteswap_* functions.
#if defined(_MSC_VER) && _MSC_VER >= 1400
# include <stdlib.h>
# define TAGLIB_BYTESWAP_MSC
// GCC 4.8 or above: __builtin_bswap16(), 32 and 64.
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
# define TAGLIB_BYTESWAP_GCC 2
// GCC 4.3 or above: __builtin_bswap16 is missing.
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
# define TAGLIB_BYTESWAP_GCC 1
#endif
// Determines if platform or library specific functions are available.
#if defined(__APPLE__)
# include <libkern/OSByteOrder.h>
# define TAGLIB_BYTESWAP_MAC
#elif defined(__OpenBSD__)
# include <sys/endian.h>
# define TAGLIB_BYTESWAP_OPENBSD
#elif defined(__GLIBC__)
# include <byteswap.h>
# define TAGLIB_BYTESWAP_GLIBC
#endif
namespace TagLib
{
ushort byteSwap16(ushort x)
{
#if defined(TAGLIB_BYTESWAP_MSC)
return _byteswap_ushort(x);
#elif defined(TAGLIB_BYTESWAP_GCC) && TAGLIB_BYTESWAP_GCC == 2
return __builtin_bswap16(x);
#elif defined(TAGLIB_BYTESWAP_MAC)
return OSSwapInt16(x);
#elif defined(TAGLIB_BYTESWAP_OPENBSD)
return swap16(x);
#elif defined(TAGLIB_BYTESWAP_GLIBC)
return __bswap_16(x);
#else
return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
#endif
}
uint byteSwap32(uint x)
{
#if defined(TAGLIB_BYTESWAP_MSC)
return _byteswap_ulong(x);
#elif defined(TAGLIB_BYTESWAP_GCC)
return __builtin_bswap32(x);
#elif defined(TAGLIB_BYTESWAP_MAC)
return OSSwapInt32(x);
#elif defined(TAGLIB_BYTESWAP_OPENBSD)
return swap32(x);
#elif defined(TAGLIB_BYTESWAP_GLIBC)
return __bswap_32(x);
#else
return ((x & 0xff000000) >> 24)
| ((x & 0x00ff0000) >> 8)
| ((x & 0x0000ff00) << 8)
| ((x & 0x000000ff) << 24);
#endif
}
ulonglong byteSwap64(ulonglong x)
{
#if defined(TAGLIB_BYTESWAP_MSC)
return _byteswap_uint64(x);
#elif defined(TAGLIB_BYTESWAP_GCC)
return __builtin_bswap64(x);
#elif defined(TAGLIB_BYTESWAP_MAC)
return OSSwapInt64(x);
#elif defined(TAGLIB_BYTESWAP_OPENBSD)
return swap64(x);
#elif defined(TAGLIB_BYTESWAP_GLIBC)
return __bswap_64(x);
#else
return ((x & 0xff00000000000000ull) >> 56)
| ((x & 0x00ff000000000000ull) >> 40)
| ((x & 0x0000ff0000000000ull) >> 24)
| ((x & 0x000000ff00000000ull) >> 8)
| ((x & 0x00000000ff000000ull) << 8)
| ((x & 0x0000000000ff0000ull) << 24)
| ((x & 0x000000000000ff00ull) << 40)
| ((x & 0x00000000000000ffull) << 56);
#endif
}
}

View File

@ -0,0 +1,49 @@
/***************************************************************************
copyright : (C) 2013 by Tsuda Kageyu
email : tsuda.kageyu@gmail.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifndef TAGLIB_BYTESWAP_H
#define TAGLIB_BYTESWAP_H
namespace TagLib
{
// Cross-platform byte order conversion functions.
/*!
* Converts the byte order of \a x as a 16-bit unsigned integer.
*/
ushort byteSwap16(ushort x);
/*!
* Converts the byte order of \a x as a 32-bit unsigned integer.
*/
uint byteSwap32(uint x);
/*!
* Converts the byte order of \a x as a 64-bit unsigned integer.
*/
ulonglong byteSwap64(ulonglong x);
}
#endif

View File

@ -24,23 +24,12 @@
***************************************************************************/
#include <iostream>
#include <tstring.h>
#include <tdebug.h>
#include <string.h>
#if defined(_MSC_VER) && _MSC_VER >= 1400 && (defined(_M_IX86) || defined(_M_X64))
# define TAGLIB_MSC_BYTESWAP
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
# define TAGLIB_GCC_BYTESWAP
#endif
#ifdef TAGLIB_GCC_BYTESWAP
# include <byteswap.h>
#endif
#include "tbytevector.h"
#include "tbyteswap.h"
// This is a bit ugly to keep writing over and over again.
@ -184,8 +173,6 @@ namespace TagLib {
return -1;
}
#if defined(TAGLIB_MSC_BYTESWAP) || defined(TAGLIB_GCC_BYTESWAP)
template <class T>
T byteSwap(T x)
{
@ -194,52 +181,24 @@ namespace TagLib {
return 0;
}
#endif
#ifdef TAGLIB_MSC_BYTESWAP
template <>
unsigned short byteSwap<unsigned short>(unsigned short x)
{
return _byteswap_ushort(x);
return byteSwap16(x);
}
template <>
unsigned int byteSwap<unsigned int>(unsigned int x)
{
return _byteswap_ulong(x);
return byteSwap32(x);
}
template <>
unsigned long long byteSwap<unsigned long long>(unsigned long long x)
{
return _byteswap_uint64(x);
return byteSwap64(x);
}
#endif
#ifdef TAGLIB_GCC_BYTESWAP
template <>
unsigned short byteSwap<unsigned short>(unsigned short x)
{
return __bswap_16(x);
}
template <>
unsigned int byteSwap<unsigned int>(unsigned int x)
{
return __bswap_32(x);
}
template <>
unsigned long long byteSwap<unsigned long long>(unsigned long long x)
{
return __bswap_64(x);
}
#endif
template <class T>
T toNumber(const ByteVector &v, bool mostSignificantByteFirst)
{

View File

@ -29,9 +29,9 @@
#include "tstring.h"
#include "tdebug.h"
#include "tstringlist.h"
#include "tbyteswap.h"
#include <iostream>
#include <string.h>
// Determine if the compiler supports codecvt.
@ -49,19 +49,6 @@ typedef std::codecvt_utf8_utf16<wchar_t> utf8_utf16_t;
namespace {
inline unsigned short byteSwap(unsigned short x)
{
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
return _byteswap_ushort(x);
#else
return (((x) >> 8) & 0xff) | (((x) & 0xff) << 8);
#endif
}
inline unsigned short combine(unsigned char c1, unsigned char c2)
{
return (c1 << 8) | c2;
@ -806,7 +793,7 @@ void String::copyFromUTF16(const wchar_t *s, size_t length, Type t)
if(swap) {
for(size_t i = 0; i < length; ++i)
d->data[i] = byteSwap(static_cast<unsigned short>(s[i]));
d->data[i] = byteSwap16(static_cast<ushort>(s[i]));
}
}