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_MSC_BYTESWAP)
00038 # include <stdlib.h>
00039 #elif defined(HAVE_GLIBC_BYTESWAP)
00040 # include <byteswap.h>
00041 #elif defined(HAVE_MAC_BYTESWAP)
00042 # include <libkern/OSByteOrder.h>
00043 #elif defined(HAVE_OPENBSD_BYTESWAP)
00044 # include <sys/endian.h>
00045 #endif
00046 
00047 #include <tstring.h>
00048 #include <cstdio>
00049 #include <cstdarg>
00050 #include <cstring>
00051 
00052 namespace TagLib
00053 {
00054   namespace Utils
00055   {
00056 
00060     inline ushort byteSwap(ushort x)
00061     {
00062 #if defined(HAVE_GCC_BYTESWAP)
00063 
00064       return __builtin_bswap16(x);
00065 
00066 #elif defined(HAVE_MSC_BYTESWAP)
00067 
00068       return _byteswap_ushort(x);
00069 
00070 #elif defined(HAVE_GLIBC_BYTESWAP)
00071 
00072       return __bswap_16(x);
00073 
00074 #elif defined(HAVE_MAC_BYTESWAP)
00075 
00076       return OSSwapInt16(x);
00077 
00078 #elif defined(HAVE_OPENBSD_BYTESWAP)
00079 
00080       return swap16(x);
00081 
00082 #else
00083 
00084       return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
00085 
00086 #endif
00087     }
00088 
00092     inline uint byteSwap(uint x)
00093     {
00094 #if defined(HAVE_GCC_BYTESWAP)
00095 
00096       return __builtin_bswap32(x);
00097 
00098 #elif defined(HAVE_MSC_BYTESWAP)
00099 
00100       return _byteswap_ulong(x);
00101 
00102 #elif defined(HAVE_GLIBC_BYTESWAP)
00103 
00104       return __bswap_32(x);
00105 
00106 #elif defined(HAVE_MAC_BYTESWAP)
00107 
00108       return OSSwapInt32(x);
00109 
00110 #elif defined(HAVE_OPENBSD_BYTESWAP)
00111 
00112       return swap32(x);
00113 
00114 #else
00115 
00116       return ((x & 0xff000000u) >> 24)
00117         | ((x & 0x00ff0000u) >>  8)
00118         | ((x & 0x0000ff00u) <<  8)
00119         | ((x & 0x000000ffu) << 24);
00120 
00121 #endif
00122     }
00123 
00127     inline ulonglong byteSwap(ulonglong x)
00128     {
00129 #if defined(HAVE_GCC_BYTESWAP)
00130 
00131       return __builtin_bswap64(x);
00132 
00133 #elif defined(HAVE_MSC_BYTESWAP)
00134 
00135       return _byteswap_uint64(x);
00136 
00137 #elif defined(HAVE_GLIBC_BYTESWAP)
00138 
00139       return __bswap_64(x);
00140 
00141 #elif defined(HAVE_MAC_BYTESWAP)
00142 
00143       return OSSwapInt64(x);
00144 
00145 #elif defined(HAVE_OPENBSD_BYTESWAP)
00146 
00147       return swap64(x);
00148 
00149 #else
00150 
00151       return ((x & 0xff00000000000000ull) >> 56)
00152         | ((x & 0x00ff000000000000ull) >> 40)
00153         | ((x & 0x0000ff0000000000ull) >> 24)
00154         | ((x & 0x000000ff00000000ull) >> 8)
00155         | ((x & 0x00000000ff000000ull) << 8)
00156         | ((x & 0x0000000000ff0000ull) << 24)
00157         | ((x & 0x000000000000ff00ull) << 40)
00158         | ((x & 0x00000000000000ffull) << 56);
00159 
00160 #endif
00161     }
00162 
00167     inline String formatString(const char *format, ...)
00168     {
00169       // Sufficient buffer size for the current internal uses.
00170       // Consider changing this value when you use this function.
00171 
00172       static const size_t BufferSize = 128;
00173 
00174       va_list args;
00175       va_start(args, format);
00176 
00177       char buf[BufferSize];
00178       int length;
00179 
00180 #if defined(HAVE_VSNPRINTF)
00181 
00182       length = vsnprintf(buf, BufferSize, format, args);
00183 
00184 #elif defined(HAVE_VSPRINTF_S)
00185 
00186       length = vsprintf_s(buf, format, args);
00187 
00188 #else
00189 
00190       // The last resort. May cause a buffer overflow.
00191 
00192       length = vsprintf(buf, format, args);
00193       if(length >= BufferSize) {
00194         debug("Utils::formatString() - Buffer overflow! Returning an empty string.");
00195         length = -1;
00196       }
00197 
00198 #endif
00199 
00200       va_end(args);
00201 
00202       if(length != -1)
00203         return String(buf);
00204       else
00205         return String::null;
00206     }
00207 
00211     enum ByteOrder
00212     {
00214       LittleEndian,
00216       BigEndian
00217     };
00218 
00222     inline ByteOrder systemByteOrder()
00223     {
00224       union {
00225         int  i;
00226         char c;
00227       } u;
00228 
00229       u.i = 1;
00230       if(u.c == 1)
00231         return LittleEndian;
00232       else
00233         return BigEndian;
00234     }
00235 
00239     inline ByteOrder floatByteOrder()
00240     {
00241       union {
00242         double d;
00243         char   c;
00244       } u;
00245 
00246       // 1.0 is stored in memory like 0x3FF0000000000000 in canonical form.
00247       // So the first byte is zero if little endian.
00248 
00249       u.d = 1.0;
00250       if(u.c == 0)
00251         return LittleEndian;
00252       else
00253         return BigEndian;
00254     }
00255 
00256   }
00257 }
00258 
00259 #endif
00260 
00261 #endif