tutils.h
Go to the documentation of this file.
00001 /***************************************************************************
00002     copyright            : (C) 2013 by Tsuda Kageyu
00003     email                : tsuda.kageyu@gmail.com
00004  ***************************************************************************/
00005 
00006 /***************************************************************************
00007  *   This library is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU Lesser General Public License version   *
00009  *   2.1 as published by the Free Software Foundation.                     *
00010  *                                                                         *
00011  *   This library is distributed in the hope that it will be useful, but   *
00012  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the Free Software   *
00018  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         *
00019  *   02110-1301  USA                                                       *
00020  *                                                                         *
00021  *   Alternatively, this file is available under the Mozilla Public        *
00022  *   License Version 1.1.  You may obtain a copy of the License at         *
00023  *   http://www.mozilla.org/MPL/                                           *
00024  ***************************************************************************/
00025 
00026 #ifndef TAGLIB_TUTILS_H
00027 #define TAGLIB_TUTILS_H
00028 
00029 // THIS FILE IS NOT A PART OF THE TAGLIB API
00030 
00031 #ifndef DO_NOT_DOCUMENT  // tell Doxygen not to document this header
00032 
00033 #ifdef HAVE_CONFIG_H
00034 # include <config.h>
00035 #endif
00036 
00037 #if defined(HAVE_BOOST_BYTESWAP)
00038 # include <boost/endian/conversion.hpp>
00039 #elif defined(HAVE_MSC_BYTESWAP)
00040 # include <stdlib.h>
00041 #elif defined(HAVE_GLIBC_BYTESWAP)
00042 # include <byteswap.h>
00043 #elif defined(HAVE_MAC_BYTESWAP)
00044 # include <libkern/OSByteOrder.h>
00045 #elif defined(HAVE_OPENBSD_BYTESWAP)
00046 # include <sys/endian.h>
00047 #endif
00048 
00049 #include <tstring.h>
00050 #include <cstdio>
00051 #include <cstdarg>
00052 #include <cstring>
00053 
00054 namespace TagLib
00055 {
00056   namespace Utils
00057   {
00058     namespace
00059     {
00060 
00064       inline unsigned short byteSwap(unsigned short x)
00065       {
00066 #if defined(HAVE_BOOST_BYTESWAP)
00067 
00068         return boost::endian::endian_reverse(static_cast<uint16_t>(x));
00069 
00070 #elif defined(HAVE_GCC_BYTESWAP)
00071 
00072         return __builtin_bswap16(x);
00073 
00074 #elif defined(HAVE_MSC_BYTESWAP)
00075 
00076         return _byteswap_ushort(x);
00077 
00078 #elif defined(HAVE_GLIBC_BYTESWAP)
00079 
00080         return __bswap_16(x);
00081 
00082 #elif defined(HAVE_MAC_BYTESWAP)
00083 
00084         return OSSwapInt16(x);
00085 
00086 #elif defined(HAVE_OPENBSD_BYTESWAP)
00087 
00088         return swap16(x);
00089 
00090 #else
00091 
00092         return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
00093 
00094 #endif
00095       }
00096 
00100       inline unsigned int byteSwap(unsigned int x)
00101       {
00102 #if defined(HAVE_BOOST_BYTESWAP)
00103 
00104         return boost::endian::endian_reverse(static_cast<uint32_t>(x));
00105 
00106 #elif defined(HAVE_GCC_BYTESWAP)
00107 
00108         return __builtin_bswap32(x);
00109 
00110 #elif defined(HAVE_MSC_BYTESWAP)
00111 
00112         return _byteswap_ulong(x);
00113 
00114 #elif defined(HAVE_GLIBC_BYTESWAP)
00115 
00116         return __bswap_32(x);
00117 
00118 #elif defined(HAVE_MAC_BYTESWAP)
00119 
00120         return OSSwapInt32(x);
00121 
00122 #elif defined(HAVE_OPENBSD_BYTESWAP)
00123 
00124         return swap32(x);
00125 
00126 #else
00127 
00128         return ((x & 0xff000000u) >> 24)
00129           | ((x & 0x00ff0000u) >>  8)
00130           | ((x & 0x0000ff00u) <<  8)
00131           | ((x & 0x000000ffu) << 24);
00132 
00133 #endif
00134       }
00135 
00139       inline unsigned long long byteSwap(unsigned long long x)
00140       {
00141 #if defined(HAVE_BOOST_BYTESWAP)
00142 
00143         return boost::endian::endian_reverse(static_cast<uint64_t>(x));
00144 
00145 #elif defined(HAVE_GCC_BYTESWAP)
00146 
00147         return __builtin_bswap64(x);
00148 
00149 #elif defined(HAVE_MSC_BYTESWAP)
00150 
00151         return _byteswap_uint64(x);
00152 
00153 #elif defined(HAVE_GLIBC_BYTESWAP)
00154 
00155         return __bswap_64(x);
00156 
00157 #elif defined(HAVE_MAC_BYTESWAP)
00158 
00159         return OSSwapInt64(x);
00160 
00161 #elif defined(HAVE_OPENBSD_BYTESWAP)
00162 
00163         return swap64(x);
00164 
00165 #else
00166 
00167         return ((x & 0xff00000000000000ull) >> 56)
00168           | ((x & 0x00ff000000000000ull) >> 40)
00169           | ((x & 0x0000ff0000000000ull) >> 24)
00170           | ((x & 0x000000ff00000000ull) >> 8)
00171           | ((x & 0x00000000ff000000ull) << 8)
00172           | ((x & 0x0000000000ff0000ull) << 24)
00173           | ((x & 0x000000000000ff00ull) << 40)
00174           | ((x & 0x00000000000000ffull) << 56);
00175 
00176 #endif
00177       }
00178 
00183       inline String formatString(const char *format, ...)
00184       {
00185         // Sufficient buffer size for the current internal uses.
00186         // Consider changing this value when you use this function.
00187 
00188         static const size_t BufferSize = 128;
00189 
00190         va_list args;
00191         va_start(args, format);
00192 
00193         char buf[BufferSize];
00194         int length;
00195 
00196 #if defined(HAVE_VSNPRINTF)
00197 
00198         length = vsnprintf(buf, BufferSize, format, args);
00199 
00200 #elif defined(HAVE_VSPRINTF_S)
00201 
00202         length = vsprintf_s(buf, format, args);
00203 
00204 #else
00205 
00206         // The last resort. May cause a buffer overflow.
00207 
00208         length = vsprintf(buf, format, args);
00209         if(length >= BufferSize) {
00210           debug("Utils::formatString() - Buffer overflow! Returning an empty string.");
00211           length = -1;
00212         }
00213 
00214 #endif
00215 
00216         va_end(args);
00217 
00218         if(length > 0)
00219           return String(buf);
00220         else
00221           return String();
00222       }
00223 
00231       inline bool equalsIgnoreCase(const char *s1, const char *s2)
00232       {
00233         while(*s1 != '\0' && *s2 != '\0' && ::tolower(*s1) == ::tolower(*s2)) {
00234           s1++;
00235           s2++;
00236         }
00237 
00238         return (*s1 == '\0' && *s2 == '\0');
00239       }
00240 
00244       enum ByteOrder
00245       {
00247         LittleEndian,
00249         BigEndian
00250       };
00251 
00255       inline ByteOrder systemByteOrder()
00256       {
00257         union {
00258           int  i;
00259           char c;
00260         } u;
00261 
00262         u.i = 1;
00263         if(u.c == 1)
00264           return LittleEndian;
00265         else
00266           return BigEndian;
00267       }
00268 
00272       inline ByteOrder floatByteOrder()
00273       {
00274         union {
00275           double d;
00276           char   c;
00277         } u;
00278 
00279         // 1.0 is stored in memory like 0x3FF0000000000000 in canonical form.
00280         // So the first byte is zero if little endian.
00281 
00282         u.d = 1.0;
00283         if(u.c == 0)
00284           return LittleEndian;
00285         else
00286           return BigEndian;
00287       }
00288     }
00289   }
00290 }
00291 
00292 #endif
00293 
00294 #endif