1 /***************************************************************************
2     copyright            : (C) 2013 by Tsuda Kageyu
3     email                : tsuda.kageyu@gmail.com
4  ***************************************************************************/
5 
6 /***************************************************************************
7  *   This library is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU Lesser General Public License version   *
9  *   2.1 as published by the Free Software Foundation.                     *
10  *                                                                         *
11  *   This library is distributed in the hope that it will be useful, but   *
12  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
14  *   Lesser General Public License for more details.                       *
15  *                                                                         *
16  *   You should have received a copy of the GNU Lesser General Public      *
17  *   License along with this library; if not, write to the Free Software   *
18  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         *
19  *   02110-1301  USA                                                       *
20  *                                                                         *
21  *   Alternatively, this file is available under the Mozilla Public        *
22  *   License Version 1.1.  You may obtain a copy of the License at         *
23  *   http://www.mozilla.org/MPL/                                           *
24  ***************************************************************************/
25 
26 #ifndef TAGLIB_TUTILS_H
27 #define TAGLIB_TUTILS_H
28 
29 // THIS FILE IS NOT A PART OF THE TAGLIB API
30 
31 #ifndef DO_NOT_DOCUMENT  // tell Doxygen not to document this header
32 
33 #ifdef HAVE_CONFIG_H
34 # include <config.h>
35 #endif
36 
37 #if defined(HAVE_MSC_BYTESWAP)
38 # include <stdlib.h>
39 #elif defined(HAVE_GLIBC_BYTESWAP)
40 # include <byteswap.h>
41 #elif defined(HAVE_MAC_BYTESWAP)
42 # include <libkern/OSByteOrder.h>
43 #elif defined(HAVE_OPENBSD_BYTESWAP)
44 # include <sys/endian.h>
45 #endif
46 
47 #include <tstring.h>
48 #include <cstdio>
49 #include <cstdarg>
50 #include <cstring>
51 
52 namespace TagLib
53 {
54   namespace Utils
55   {
56     namespace
57     {
58 
59       /*!
60        * Reverses the order of bytes in an 16-bit integer.
61        */
byteSwap(unsigned short x)62       inline unsigned short byteSwap(unsigned short x)
63       {
64 #if defined(HAVE_GCC_BYTESWAP)
65 
66         return __builtin_bswap16(x);
67 
68 #elif defined(HAVE_MSC_BYTESWAP)
69 
70         return _byteswap_ushort(x);
71 
72 #elif defined(HAVE_GLIBC_BYTESWAP)
73 
74         return __bswap_16(x);
75 
76 #elif defined(HAVE_MAC_BYTESWAP)
77 
78         return OSSwapInt16(x);
79 
80 #elif defined(HAVE_OPENBSD_BYTESWAP)
81 
82         return swap16(x);
83 
84 #else
85 
86         return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
87 
88 #endif
89       }
90 
91       /*!
92        * Reverses the order of bytes in an 32-bit integer.
93        */
byteSwap(unsigned int x)94       inline unsigned int byteSwap(unsigned int x)
95       {
96 #if defined(HAVE_GCC_BYTESWAP)
97 
98         return __builtin_bswap32(x);
99 
100 #elif defined(HAVE_MSC_BYTESWAP)
101 
102         return _byteswap_ulong(x);
103 
104 #elif defined(HAVE_GLIBC_BYTESWAP)
105 
106         return __bswap_32(x);
107 
108 #elif defined(HAVE_MAC_BYTESWAP)
109 
110         return OSSwapInt32(x);
111 
112 #elif defined(HAVE_OPENBSD_BYTESWAP)
113 
114         return swap32(x);
115 
116 #else
117 
118         return ((x & 0xff000000u) >> 24)
119           | ((x & 0x00ff0000u) >>  8)
120           | ((x & 0x0000ff00u) <<  8)
121           | ((x & 0x000000ffu) << 24);
122 
123 #endif
124       }
125 
126       /*!
127        * Reverses the order of bytes in an 64-bit integer.
128        */
byteSwap(unsigned long long x)129       inline unsigned long long byteSwap(unsigned long long x)
130       {
131 #if defined(HAVE_GCC_BYTESWAP)
132 
133         return __builtin_bswap64(x);
134 
135 #elif defined(HAVE_MSC_BYTESWAP)
136 
137         return _byteswap_uint64(x);
138 
139 #elif defined(HAVE_GLIBC_BYTESWAP)
140 
141         return __bswap_64(x);
142 
143 #elif defined(HAVE_MAC_BYTESWAP)
144 
145         return OSSwapInt64(x);
146 
147 #elif defined(HAVE_OPENBSD_BYTESWAP)
148 
149         return swap64(x);
150 
151 #else
152 
153         return ((x & 0xff00000000000000ull) >> 56)
154           | ((x & 0x00ff000000000000ull) >> 40)
155           | ((x & 0x0000ff0000000000ull) >> 24)
156           | ((x & 0x000000ff00000000ull) >> 8)
157           | ((x & 0x00000000ff000000ull) << 8)
158           | ((x & 0x0000000000ff0000ull) << 24)
159           | ((x & 0x000000000000ff00ull) << 40)
160           | ((x & 0x00000000000000ffull) << 56);
161 
162 #endif
163       }
164 
165       /*!
166        * Returns a formatted string just like standard sprintf(), but makes use of
167        * safer functions such as snprintf() if available.
168        */
formatString(const char * format,...)169       inline String formatString(const char *format, ...)
170       {
171         // Sufficient buffer size for the current internal uses.
172         // Consider changing this value when you use this function.
173 
174         static const size_t BufferSize = 128;
175 
176         va_list args;
177         va_start(args, format);
178 
179         char buf[BufferSize];
180         int length;
181 
182 #if defined(HAVE_VSNPRINTF)
183 
184         length = vsnprintf(buf, BufferSize, format, args);
185 
186 #elif defined(HAVE_VSPRINTF_S)
187 
188         length = vsprintf_s(buf, format, args);
189 
190 #else
191 
192         // The last resort. May cause a buffer overflow.
193 
194         length = vsprintf(buf, format, args);
195         if(length >= BufferSize) {
196           debug("Utils::formatString() - Buffer overflow! Returning an empty string.");
197           length = -1;
198         }
199 
200 #endif
201 
202         va_end(args);
203 
204         if(length > 0)
205           return String(buf);
206         else
207           return String();
208       }
209 
210       /*!
211        * The types of byte order of the running system.
212        */
213       enum ByteOrder
214       {
215         //! Little endian systems.
216         LittleEndian,
217         //! Big endian systems.
218         BigEndian
219       };
220 
221       /*!
222        * Returns the byte order of the system.
223        */
systemByteOrder()224       inline ByteOrder systemByteOrder()
225       {
226         union {
227           int  i;
228           char c;
229         } u;
230 
231         u.i = 1;
232         if(u.c == 1)
233           return LittleEndian;
234         else
235           return BigEndian;
236       }
237     }
238   }
239 }
240 
241 #endif
242 
243 #endif
244