tutils.h
Go to the documentation of this file.
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_BOOST_BYTESWAP)
38 # include <boost/endian/conversion.hpp>
39 #elif defined(HAVE_MSC_BYTESWAP)
40 # include <stdlib.h>
41 #elif defined(HAVE_GLIBC_BYTESWAP)
42 # include <byteswap.h>
43 #elif defined(HAVE_MAC_BYTESWAP)
44 # include <libkern/OSByteOrder.h>
45 #elif defined(HAVE_OPENBSD_BYTESWAP)
46 # include <sys/endian.h>
47 #endif
48 
49 #include <tstring.h>
50 #include <cstdio>
51 #include <cstdarg>
52 #include <cstring>
53 
54 namespace TagLib
55 {
56  namespace Utils
57  {
58  namespace
59  {
60 
64  inline unsigned short byteSwap(unsigned short x)
65  {
66 #if defined(HAVE_BOOST_BYTESWAP)
67 
68  return boost::endian::endian_reverse(static_cast<uint16_t>(x));
69 
70 #elif defined(HAVE_GCC_BYTESWAP)
71 
72  return __builtin_bswap16(x);
73 
74 #elif defined(HAVE_MSC_BYTESWAP)
75 
76  return _byteswap_ushort(x);
77 
78 #elif defined(HAVE_GLIBC_BYTESWAP)
79 
80  return __bswap_16(x);
81 
82 #elif defined(HAVE_MAC_BYTESWAP)
83 
84  return OSSwapInt16(x);
85 
86 #elif defined(HAVE_OPENBSD_BYTESWAP)
87 
88  return swap16(x);
89 
90 #else
91 
92  return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
93 
94 #endif
95  }
96 
100  inline unsigned int byteSwap(unsigned int x)
101  {
102 #if defined(HAVE_BOOST_BYTESWAP)
103 
104  return boost::endian::endian_reverse(static_cast<uint32_t>(x));
105 
106 #elif defined(HAVE_GCC_BYTESWAP)
107 
108  return __builtin_bswap32(x);
109 
110 #elif defined(HAVE_MSC_BYTESWAP)
111 
112  return _byteswap_ulong(x);
113 
114 #elif defined(HAVE_GLIBC_BYTESWAP)
115 
116  return __bswap_32(x);
117 
118 #elif defined(HAVE_MAC_BYTESWAP)
119 
120  return OSSwapInt32(x);
121 
122 #elif defined(HAVE_OPENBSD_BYTESWAP)
123 
124  return swap32(x);
125 
126 #else
127 
128  return ((x & 0xff000000u) >> 24)
129  | ((x & 0x00ff0000u) >> 8)
130  | ((x & 0x0000ff00u) << 8)
131  | ((x & 0x000000ffu) << 24);
132 
133 #endif
134  }
135 
139  inline unsigned long long byteSwap(unsigned long long x)
140  {
141 #if defined(HAVE_BOOST_BYTESWAP)
142 
143  return boost::endian::endian_reverse(static_cast<uint64_t>(x));
144 
145 #elif defined(HAVE_GCC_BYTESWAP)
146 
147  return __builtin_bswap64(x);
148 
149 #elif defined(HAVE_MSC_BYTESWAP)
150 
151  return _byteswap_uint64(x);
152 
153 #elif defined(HAVE_GLIBC_BYTESWAP)
154 
155  return __bswap_64(x);
156 
157 #elif defined(HAVE_MAC_BYTESWAP)
158 
159  return OSSwapInt64(x);
160 
161 #elif defined(HAVE_OPENBSD_BYTESWAP)
162 
163  return swap64(x);
164 
165 #else
166 
167  return ((x & 0xff00000000000000ull) >> 56)
168  | ((x & 0x00ff000000000000ull) >> 40)
169  | ((x & 0x0000ff0000000000ull) >> 24)
170  | ((x & 0x000000ff00000000ull) >> 8)
171  | ((x & 0x00000000ff000000ull) << 8)
172  | ((x & 0x0000000000ff0000ull) << 24)
173  | ((x & 0x000000000000ff00ull) << 40)
174  | ((x & 0x00000000000000ffull) << 56);
175 
176 #endif
177  }
178 
183  inline String formatString(const char *format, ...)
184  {
185  // Sufficient buffer size for the current internal uses.
186  // Consider changing this value when you use this function.
187 
188  static const size_t BufferSize = 128;
189 
190  va_list args;
191  va_start(args, format);
192 
193  char buf[BufferSize];
194  int length;
195 
196 #if defined(HAVE_VSNPRINTF)
197 
198  length = vsnprintf(buf, BufferSize, format, args);
199 
200 #elif defined(HAVE_VSPRINTF_S)
201 
202  length = vsprintf_s(buf, format, args);
203 
204 #else
205 
206  // The last resort. May cause a buffer overflow.
207 
208  length = vsprintf(buf, format, args);
209  if(length >= BufferSize) {
210  debug("Utils::formatString() - Buffer overflow! Returning an empty string.");
211  length = -1;
212  }
213 
214 #endif
215 
216  va_end(args);
217 
218  if(length > 0)
219  return String(buf);
220  else
221  return String();
222  }
223 
231  inline bool equalsIgnoreCase(const char *s1, const char *s2)
232  {
233  while(*s1 != '\0' && *s2 != '\0' && ::tolower(*s1) == ::tolower(*s2)) {
234  s1++;
235  s2++;
236  }
237 
238  return (*s1 == '\0' && *s2 == '\0');
239  }
240 
244  enum ByteOrder
245  {
247  LittleEndian,
249  BigEndian
250  };
251 
255  inline ByteOrder systemByteOrder()
256  {
257  union {
258  int i;
259  char c;
260  } u;
261 
262  u.i = 1;
263  if(u.c == 1)
264  return LittleEndian;
265  else
266  return BigEndian;
267  }
268 
272  inline ByteOrder floatByteOrder()
273  {
274  union {
275  double d;
276  char c;
277  } u;
278 
279  // 1.0 is stored in memory like 0x3FF0000000000000 in canonical form.
280  // So the first byte is zero if little endian.
281 
282  u.d = 1.0;
283  if(u.c == 0)
284  return LittleEndian;
285  else
286  return BigEndian;
287  }
288  }
289  }
290 }
291 
292 #endif
293 
294 #endif