From f5462e3e19278a8105da8ece407eb0ab953d7595 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Tue, 16 Apr 2013 00:09:18 +0900 Subject: [PATCH] Add cross-platform byte order conversions --- taglib/CMakeLists.txt | 2 + taglib/toolkit/taglib.h | 36 +++++++- taglib/toolkit/tbyteswap.cpp | 160 +++++++++++++++++++++++++++++++++ taglib/toolkit/tbyteswap.h | 49 ++++++++++ taglib/toolkit/tbytevector.cpp | 49 +--------- taglib/toolkit/tstring.cpp | 17 +--- 6 files changed, 249 insertions(+), 64 deletions(-) create mode 100644 taglib/toolkit/tbyteswap.cpp create mode 100644 taglib/toolkit/tbyteswap.h diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt index 72712ca2..a940caf5 100644 --- a/taglib/CMakeLists.txt +++ b/taglib/CMakeLists.txt @@ -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 ) diff --git a/taglib/toolkit/taglib.h b/taglib/toolkit/taglib.h index ed82b0fe..696174e9 100755 --- a/taglib/toolkit/taglib.h +++ b/taglib/toolkit/taglib.h @@ -43,6 +43,7 @@ #endif #include +#include #ifdef __APPLE__ # include @@ -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; /*! diff --git a/taglib/toolkit/tbyteswap.cpp b/taglib/toolkit/tbyteswap.cpp new file mode 100644 index 00000000..cf0c9b9b --- /dev/null +++ b/taglib/toolkit/tbyteswap.cpp @@ -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 +# 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 +# define TAGLIB_BYTESWAP_MAC + +#elif defined(__OpenBSD__) +# include +# define TAGLIB_BYTESWAP_OPENBSD + +#elif defined(__GLIBC__) +# include +# 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 + } +} diff --git a/taglib/toolkit/tbyteswap.h b/taglib/toolkit/tbyteswap.h new file mode 100644 index 00000000..ed20125c --- /dev/null +++ b/taglib/toolkit/tbyteswap.h @@ -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 diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp index 89785d04..63aad50f 100644 --- a/taglib/toolkit/tbytevector.cpp +++ b/taglib/toolkit/tbytevector.cpp @@ -24,23 +24,12 @@ ***************************************************************************/ #include - #include #include - #include -#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 -#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 T byteSwap(T x) { @@ -194,52 +181,24 @@ namespace TagLib { return 0; } -#endif - -#ifdef TAGLIB_MSC_BYTESWAP - template <> unsigned short byteSwap(unsigned short x) { - return _byteswap_ushort(x); + return byteSwap16(x); } template <> unsigned int byteSwap(unsigned int x) { - return _byteswap_ulong(x); + return byteSwap32(x); } template <> unsigned long long byteSwap(unsigned long long x) { - return _byteswap_uint64(x); + return byteSwap64(x); } -#endif - -#ifdef TAGLIB_GCC_BYTESWAP - - template <> - unsigned short byteSwap(unsigned short x) - { - return __bswap_16(x); - } - - template <> - unsigned int byteSwap(unsigned int x) - { - return __bswap_32(x); - } - - template <> - unsigned long long byteSwap(unsigned long long x) - { - return __bswap_64(x); - } - -#endif - template T toNumber(const ByteVector &v, bool mostSignificantByteFirst) { diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp index 42505cbe..2c80e80c 100644 --- a/taglib/toolkit/tstring.cpp +++ b/taglib/toolkit/tstring.cpp @@ -29,9 +29,9 @@ #include "tstring.h" #include "tdebug.h" #include "tstringlist.h" +#include "tbyteswap.h" #include - #include // Determine if the compiler supports codecvt. @@ -49,19 +49,6 @@ typedef std::codecvt_utf8_utf16 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(s[i])); + d->data[i] = byteSwap16(static_cast(s[i])); } }