id3lib  3.8.3
utils.cpp
Go to the documentation of this file.
1 // $Id: utils.cpp,v 1.26 2002/07/02 22:04:36 t1mpy Exp $
2 
3 // id3lib: a C++ library for creating and manipulating id3v1/v2 tags
4 // Copyright 1999, 2000 Scott Thomas Haug
5 
6 // This library is free software; you can redistribute it and/or modify it
7 // under the terms of the GNU Library General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or (at your
9 // option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful, but WITHOUT
12 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
14 // License for more details.
15 //
16 // You should have received a copy of the GNU Library General Public License
17 // along with this library; if not, write to the Free Software Foundation,
18 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 
20 // The id3lib authors encourage improvements and optimisations to be sent to
21 // the id3lib coordinator. Please see the README file for details on where to
22 // send such submissions. See the AUTHORS file for a list of people who have
23 // contributed to id3lib. See the ChangeLog file for a list of changes to
24 // id3lib. These files are distributed with id3lib at
25 // http://download.sourceforge.net/id3lib/
26 
27 #include <ctype.h>
28 
29 #if (defined(__GNUC__) && __GNUC__ == 2)
30 #define NOCREATE ios::nocreate
31 #else
32 #if defined(macintosh) //not sure if this is still needed
33 #define toascii(X) (X) //not sure if this is still needed
34 #endif //not sure if this is still needed
35 #define NOCREATE ((std::ios_base::openmode)0)
36 #endif
37 
38 #include "id3/utils.h" // has <config.h> "id3/id3lib_streams.h" "id3/globals.h" "id3/id3lib_strings.h"
39 
40 #if defined HAVE_ICONV_H
41 // check if we have all unicodes
42 #if (defined(ID3_ICONV_FORMAT_UTF16BE) && defined(ID3_ICONV_FORMAT_UTF16) && defined(ID3_ICONV_FORMAT_UTF8) && defined(ID3_ICONV_FORMAT_ASCII))
43 # include <iconv.h>
44 # include <errno.h>
45 #else
46 # undef HAVE_ICONV_H
47 #endif
48 #endif
49 
50  // converts an ASCII string into a Unicode one
51 dami::String mbstoucs(dami::String data)
52 {
53  size_t size = data.size();
54  dami::String unicode(size * 2, '\0');
55  for (size_t i = 0; i < size; ++i)
56  {
57  unicode[i*2+1] = toascii(data[i]);
58  }
59  return unicode;
60 }
61 
62 // converts a Unicode string into ASCII
63 dami::String ucstombs(dami::String data)
64 {
65  size_t size = data.size() / 2;
66  dami::String ascii(size, '\0');
67  for (size_t i = 0; i < size; ++i)
68  {
69  ascii[i] = toascii(data[i*2+1]);
70  }
71  return ascii;
72 }
73 
74 dami::String oldconvert(dami::String data, ID3_TextEnc sourceEnc, ID3_TextEnc targetEnc)
75 {
76  dami::String target;
77 #define ID3_IS_ASCII(enc) ((enc) == ID3TE_ASCII || (enc) == ID3TE_ISO8859_1 || (enc) == ID3TE_UTF8)
78 #define ID3_IS_UNICODE(enc) ((enc) == ID3TE_UNICODE || (enc) == ID3TE_UTF16 || (enc) == ID3TE_UTF16BE)
79  if (ID3_IS_ASCII(sourceEnc) && ID3_IS_UNICODE(targetEnc))
80  {
81  target = mbstoucs(data);
82  }
83  else if (ID3_IS_UNICODE(sourceEnc) && ID3_IS_ASCII(targetEnc))
84  {
85  target = ucstombs(data);
86  }
87  return target;
88 }
89 
90 using namespace dami;
91 
92 size_t dami::renderNumber(uchar *buffer, uint32 val, size_t size)
93 {
94  uint32 num = val;
95  for (size_t i = 0; i < size; i++)
96  {
97  buffer[size - i - 1] = (uchar)(num & MASK8);
98  num >>= 8;
99  }
100  return size;
101 }
102 
103 String dami::renderNumber(uint32 val, size_t size)
104 {
105  String str(size, '\0');
106  uint32 num = val;
107  for (size_t i = 0; i < size; i++)
108  {
109  str[size - i - 1] = (uchar)(num & MASK8);
110  num >>= 8;
111  }
112  return str;
113 }
114 
115 
116 #if defined(HAVE_ICONV_H)
117 
118 namespace
119 {
120  String convert_i(iconv_t cd, String source)
121  {
122  String target;
123  size_t source_size = source.size();
124 #if defined(ID3LIB_ICONV_OLDSTYLE)
125  const char* source_str = source.data();
126 #else
127  char *source_str = new char[source.size()+1];
128  source.copy(source_str, String::npos);
129  source_str[source.length()] = 0;
130 #endif
131 
132 #define ID3LIB_BUFSIZ 1024
133  char buf[ID3LIB_BUFSIZ];
134  char* target_str = buf;
135  size_t target_size = ID3LIB_BUFSIZ;
136 
137  do
138  {
139  errno = 0;
140  size_t nconv = iconv(cd,
141  &source_str, &source_size,
142  &target_str, &target_size);
143  if (nconv == (size_t) -1 && errno != EINVAL && errno != E2BIG)
144  {
145 // errno is probably EILSEQ here, which means either an invalid byte sequence or a valid but unconvertible byte sequence
146  return target;
147  }
148  target.append(buf, ID3LIB_BUFSIZ - target_size);
149  target_str = buf;
150  target_size = ID3LIB_BUFSIZ;
151  }
152  while (source_size > 0);
153  return target;
154  }
155 
156  const char* getFormat(ID3_TextEnc enc)
157  {
158  const char* format = NULL;
159  switch (enc)
160  {
161  case ID3TE_ASCII:
162  format = ID3_ICONV_FORMAT_ASCII;
163  break;
164 
165  case ID3TE_UTF16:
166  format = ID3_ICONV_FORMAT_UTF16;
167  break;
168 
169  case ID3TE_UTF16BE:
170  format = ID3_ICONV_FORMAT_UTF16BE;
171  break;
172 
173  case ID3TE_UTF8:
174  format = ID3_ICONV_FORMAT_UTF8;
175  break;
176 
177  default:
178  break;
179  }
180  return format;
181  }
182 }
183 #endif
184 
185 String dami::convert(String data, ID3_TextEnc sourceEnc, ID3_TextEnc targetEnc)
186 {
187  String target;
188  if ((sourceEnc != targetEnc) && (data.size() > 0 ))
189  {
190 #if !defined HAVE_ICONV_H
191  target = oldconvert(data, sourceEnc, targetEnc);
192 #else
193  const char* targetFormat = getFormat(targetEnc);
194  const char* sourceFormat = getFormat(sourceEnc);
195 
196  iconv_t cd = iconv_open (targetFormat, sourceFormat);
197  if (cd != (iconv_t) -1)
198  {
199  target = convert_i(cd, data);
200  if (target.size() == 0)
201  {
202  //try it without iconv
203  target = oldconvert(data, sourceEnc, targetEnc);
204  }
205  }
206  else
207  {
208  target = oldconvert(data, sourceEnc, targetEnc);
209  }
210  iconv_close (cd);
211 #endif
212  }
213  return target;
214 }
215 
216 size_t dami::ucslen(const unicode_t *unicode)
217 {
218  if (NULL != unicode)
219  {
220  for (size_t size = 0; true; size++)
221  {
222  if (NULL_UNICODE == unicode[size])
223  {
224  return size;
225  }
226  }
227  }
228  return 0;
229 }
230 
231 namespace
232 {
233  bool exists(String name)
234  {
235  ifstream file(name.c_str(), NOCREATE);
236  return file.is_open() != 0;
237  }
238 };
239 
240 ID3_Err dami::createFile(String name, fstream& file)
241 {
242  if (file.is_open())
243  {
244  file.close();
245  }
246 
247  file.open(name.c_str(), ios::in | ios::out | ios::binary | ios::trunc);
248  if (!file)
249  {
250  return ID3E_ReadOnly;
251  }
252 
253  return ID3E_NoError;
254 }
255 
256 size_t dami::getFileSize(fstream& file)
257 {
258  size_t size = 0;
259  if (file.is_open())
260  {
261  streamoff curpos = streamoff(file.tellg());
262  file.seekg(0, ios::end);
263  size = streamoff(file.tellg());
264  file.seekg(curpos);
265  }
266  return size;
267 }
268 
269 size_t dami::getFileSize(ifstream& file)
270 {
271  size_t size = 0;
272  if (file.is_open())
273  {
274  streamoff curpos = streamoff(file.tellg());
275  file.seekg(0, ios::end);
276  size = streamoff(file.tellg());
277  file.seekg(curpos);
278  }
279  return size;
280 }
281 
282 size_t dami::getFileSize(ofstream& file)
283 {
284  size_t size = 0;
285  if (file.is_open())
286  {
287  streamoff curpos = streamoff(file.tellp());
288  file.seekp(0, ios::end);
289  size = streamoff(file.tellp());
290  file.seekp(curpos);
291  }
292  return size;
293 }
294 
295 ID3_Err dami::openWritableFile(String name, fstream& file)
296 {
297  if (!exists(name))
298  {
299  return ID3E_NoFile;
300  }
301 
302  if (file.is_open())
303  {
304  file.close();
305  }
306  file.open(name.c_str(), ios::in | ios::out | ios::binary | NOCREATE);
307  if (!file)
308  {
309  return ID3E_ReadOnly;
310  }
311 
312  return ID3E_NoError;
313 }
314 
315 ID3_Err dami::openWritableFile(String name, ofstream& file)
316 {
317  if (!exists(name))
318  {
319  return ID3E_NoFile;
320  }
321 
322  if (file.is_open())
323  {
324  file.close();
325  }
326  file.open(name.c_str(), ios::in | ios::out | ios::binary | NOCREATE);
327  if (!file)
328  {
329  return ID3E_ReadOnly;
330  }
331 
332  return ID3E_NoError;
333 }
334 
335 ID3_Err dami::openReadableFile(String name, fstream& file)
336 {
337  if (file.is_open())
338  {
339  file.close();
340  }
341  file.open(name.c_str(), ios::in | ios::binary | NOCREATE);
342  if (!file)
343  {
344  return ID3E_NoFile;
345  }
346 
347  return ID3E_NoError;
348 }
349 
350 ID3_Err dami::openReadableFile(String name, ifstream& file)
351 {
352  if (file.is_open())
353  {
354  file.close();
355  }
356  file.open(name.c_str(), ios::in | ios::binary | NOCREATE);
357  if (!file)
358  {
359  return ID3E_NoFile;
360  }
361 
362  return ID3E_NoError;
363 }
364 
365 String dami::toString(uint32 val)
366 {
367  if (val == 0)
368  {
369  return "0";
370  }
371  String text;
372  while (val > 0)
373  {
374  String tmp;
375  char ch = (val % 10) + '0';
376  tmp += ch;
377  text = tmp + text;
378  val /= 10;
379  }
380  return text;
381 }
382 
383 WString dami::toWString(const unicode_t buf[], size_t len)
384 {
385  WString str;
386  str.reserve(len);
387 
388  for (size_t i = 0; i < len; ++i)
389  {
390  str += static_cast<WString::value_type>(buf[i]);
391  }
392  return str;
393 }
394 
#define MASK8
Definition: globals.h:705
#define NULL
Definition: globals.h:743
ID3_Err
Predefined id3lib error types.
Definition: globals.h:364
@ ID3E_ReadOnly
Attempting to write to a read-only file.
Definition: globals.h:377
@ ID3E_NoError
No error reported.
Definition: globals.h:365
@ ID3E_NoFile
No file to parse.
Definition: globals.h:376
ID3_TextEnc
Enumeration of the types of text encodings: ascii or unicode.
Definition: globals.h:138
@ ID3TE_UTF16BE
Definition: globals.h:142
@ ID3TE_UTF16
Definition: globals.h:141
@ ID3TE_ASCII
Definition: globals.h:145
@ ID3TE_UTF8
Definition: globals.h:143
unsigned char uchar
Definition: globals.h:114
uint16 unicode_t
Definition: globals.h:117
#define NULL_UNICODE
Definition: globals.h:120
Definition: tag_impl.h:42
size_t ID3_C_EXPORT getFileSize(fstream &)
Definition: utils.cpp:256
String ID3_C_EXPORT toString(uint32 val)
Definition: utils.cpp:365
String ID3_C_EXPORT convert(String data, ID3_TextEnc, ID3_TextEnc)
Definition: utils.cpp:185
ID3_Err ID3_C_EXPORT openWritableFile(String, fstream &)
Definition: utils.cpp:295
size_t ID3_C_EXPORT renderNumber(uchar *buffer, uint32 val, size_t size=sizeof(uint32))
Definition: utils.cpp:92
ID3_Err ID3_C_EXPORT createFile(String, fstream &)
Definition: utils.cpp:240
WString ID3_C_EXPORT toWString(const unicode_t[], size_t)
Definition: utils.cpp:383
size_t ID3_C_EXPORT ucslen(const unicode_t *unicode)
Definition: utils.cpp:216
ID3_Err ID3_C_EXPORT openReadableFile(String, fstream &)
Definition: utils.cpp:335
dami::String ucstombs(dami::String data)
Definition: utils.cpp:63
dami::String mbstoucs(dami::String data)
Definition: utils.cpp:51
#define ID3_IS_ASCII(enc)
dami::String oldconvert(dami::String data, ID3_TextEnc sourceEnc, ID3_TextEnc targetEnc)
Definition: utils.cpp:74
#define ID3_IS_UNICODE(enc)
#define NOCREATE
Definition: utils.cpp:35