id3lib 3.8.3
|
00001 // $Id: utils.cpp,v 1.26 2002/07/02 22:04:36 t1mpy Exp $ 00002 00003 // id3lib: a C++ library for creating and manipulating id3v1/v2 tags 00004 // Copyright 1999, 2000 Scott Thomas Haug 00005 00006 // This library is free software; you can redistribute it and/or modify it 00007 // under the terms of the GNU Library General Public License as published by 00008 // the Free Software Foundation; either version 2 of the License, or (at your 00009 // option) any later version. 00010 // 00011 // This library is distributed in the hope that it will be useful, but WITHOUT 00012 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00013 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00014 // License for more details. 00015 // 00016 // You should have received a copy of the GNU Library General Public License 00017 // along with this library; if not, write to the Free Software Foundation, 00018 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00019 00020 // The id3lib authors encourage improvements and optimisations to be sent to 00021 // the id3lib coordinator. Please see the README file for details on where to 00022 // send such submissions. See the AUTHORS file for a list of people who have 00023 // contributed to id3lib. See the ChangeLog file for a list of changes to 00024 // id3lib. These files are distributed with id3lib at 00025 // http://download.sourceforge.net/id3lib/ 00026 00027 #include <ctype.h> 00028 00029 #if (defined(__GNUC__) && __GNUC__ == 2) 00030 #define NOCREATE ios::nocreate 00031 #else 00032 #if defined(macintosh) //not sure if this is still needed 00033 #define toascii(X) (X) //not sure if this is still needed 00034 #endif //not sure if this is still needed 00035 #define NOCREATE ((std::ios_base::openmode)0) 00036 #endif 00037 00038 #include "id3/utils.h" // has <config.h> "id3/id3lib_streams.h" "id3/globals.h" "id3/id3lib_strings.h" 00039 00040 #if defined HAVE_ICONV_H 00041 // check if we have all unicodes 00042 #if (defined(ID3_ICONV_FORMAT_UTF16BE) && defined(ID3_ICONV_FORMAT_UTF16) && defined(ID3_ICONV_FORMAT_UTF8) && defined(ID3_ICONV_FORMAT_ASCII)) 00043 # include <iconv.h> 00044 # include <errno.h> 00045 #else 00046 # undef HAVE_ICONV_H 00047 #endif 00048 #endif 00049 00050 // converts an ASCII string into a Unicode one 00051 dami::String mbstoucs(dami::String data) 00052 { 00053 size_t size = data.size(); 00054 dami::String unicode(size * 2, '\0'); 00055 for (size_t i = 0; i < size; ++i) 00056 { 00057 unicode[i*2+1] = toascii(data[i]); 00058 } 00059 return unicode; 00060 } 00061 00062 // converts a Unicode string into ASCII 00063 dami::String ucstombs(dami::String data) 00064 { 00065 size_t size = data.size() / 2; 00066 dami::String ascii(size, '\0'); 00067 for (size_t i = 0; i < size; ++i) 00068 { 00069 ascii[i] = toascii(data[i*2+1]); 00070 } 00071 return ascii; 00072 } 00073 00074 dami::String oldconvert(dami::String data, ID3_TextEnc sourceEnc, ID3_TextEnc targetEnc) 00075 { 00076 dami::String target; 00077 #define ID3_IS_ASCII(enc) ((enc) == ID3TE_ASCII || (enc) == ID3TE_ISO8859_1 || (enc) == ID3TE_UTF8) 00078 #define ID3_IS_UNICODE(enc) ((enc) == ID3TE_UNICODE || (enc) == ID3TE_UTF16 || (enc) == ID3TE_UTF16BE) 00079 if (ID3_IS_ASCII(sourceEnc) && ID3_IS_UNICODE(targetEnc)) 00080 { 00081 target = mbstoucs(data); 00082 } 00083 else if (ID3_IS_UNICODE(sourceEnc) && ID3_IS_ASCII(targetEnc)) 00084 { 00085 target = ucstombs(data); 00086 } 00087 return target; 00088 } 00089 00090 using namespace dami; 00091 00092 size_t dami::renderNumber(uchar *buffer, uint32 val, size_t size) 00093 { 00094 uint32 num = val; 00095 for (size_t i = 0; i < size; i++) 00096 { 00097 buffer[size - i - 1] = (uchar)(num & MASK8); 00098 num >>= 8; 00099 } 00100 return size; 00101 } 00102 00103 String dami::renderNumber(uint32 val, size_t size) 00104 { 00105 String str(size, '\0'); 00106 uint32 num = val; 00107 for (size_t i = 0; i < size; i++) 00108 { 00109 str[size - i - 1] = (uchar)(num & MASK8); 00110 num >>= 8; 00111 } 00112 return str; 00113 } 00114 00115 00116 #if defined(HAVE_ICONV_H) 00117 00118 namespace 00119 { 00120 String convert_i(iconv_t cd, String source) 00121 { 00122 String target; 00123 size_t source_size = source.size(); 00124 #if defined(ID3LIB_ICONV_OLDSTYLE) 00125 const char* source_str = source.data(); 00126 #else 00127 char *source_str = new char[source.size()+1]; 00128 source.copy(source_str, String::npos); 00129 source_str[source.length()] = 0; 00130 #endif 00131 00132 #define ID3LIB_BUFSIZ 1024 00133 char buf[ID3LIB_BUFSIZ]; 00134 char* target_str = buf; 00135 size_t target_size = ID3LIB_BUFSIZ; 00136 00137 do 00138 { 00139 errno = 0; 00140 size_t nconv = iconv(cd, 00141 &source_str, &source_size, 00142 &target_str, &target_size); 00143 if (nconv == (size_t) -1 && errno != EINVAL && errno != E2BIG) 00144 { 00145 // errno is probably EILSEQ here, which means either an invalid byte sequence or a valid but unconvertible byte sequence 00146 return target; 00147 } 00148 target.append(buf, ID3LIB_BUFSIZ - target_size); 00149 target_str = buf; 00150 target_size = ID3LIB_BUFSIZ; 00151 } 00152 while (source_size > 0); 00153 return target; 00154 } 00155 00156 const char* getFormat(ID3_TextEnc enc) 00157 { 00158 const char* format = NULL; 00159 switch (enc) 00160 { 00161 case ID3TE_ASCII: 00162 format = ID3_ICONV_FORMAT_ASCII; 00163 break; 00164 00165 case ID3TE_UTF16: 00166 format = ID3_ICONV_FORMAT_UTF16; 00167 break; 00168 00169 case ID3TE_UTF16BE: 00170 format = ID3_ICONV_FORMAT_UTF16BE; 00171 break; 00172 00173 case ID3TE_UTF8: 00174 format = ID3_ICONV_FORMAT_UTF8; 00175 break; 00176 00177 default: 00178 break; 00179 } 00180 return format; 00181 } 00182 } 00183 #endif 00184 00185 String dami::convert(String data, ID3_TextEnc sourceEnc, ID3_TextEnc targetEnc) 00186 { 00187 String target; 00188 if ((sourceEnc != targetEnc) && (data.size() > 0 )) 00189 { 00190 #if !defined HAVE_ICONV_H 00191 target = oldconvert(data, sourceEnc, targetEnc); 00192 #else 00193 const char* targetFormat = getFormat(targetEnc); 00194 const char* sourceFormat = getFormat(sourceEnc); 00195 00196 iconv_t cd = iconv_open (targetFormat, sourceFormat); 00197 if (cd != (iconv_t) -1) 00198 { 00199 target = convert_i(cd, data); 00200 if (target.size() == 0) 00201 { 00202 //try it without iconv 00203 target = oldconvert(data, sourceEnc, targetEnc); 00204 } 00205 } 00206 else 00207 { 00208 target = oldconvert(data, sourceEnc, targetEnc); 00209 } 00210 iconv_close (cd); 00211 #endif 00212 } 00213 return target; 00214 } 00215 00216 size_t dami::ucslen(const unicode_t *unicode) 00217 { 00218 if (NULL != unicode) 00219 { 00220 for (size_t size = 0; true; size++) 00221 { 00222 if (NULL_UNICODE == unicode[size]) 00223 { 00224 return size; 00225 } 00226 } 00227 } 00228 return 0; 00229 } 00230 00231 namespace 00232 { 00233 bool exists(String name) 00234 { 00235 ifstream file(name.c_str(), NOCREATE); 00236 return file.is_open() != 0; 00237 } 00238 }; 00239 00240 ID3_Err dami::createFile(String name, fstream& file) 00241 { 00242 if (file.is_open()) 00243 { 00244 file.close(); 00245 } 00246 00247 file.open(name.c_str(), ios::in | ios::out | ios::binary | ios::trunc); 00248 if (!file) 00249 { 00250 return ID3E_ReadOnly; 00251 } 00252 00253 return ID3E_NoError; 00254 } 00255 00256 size_t dami::getFileSize(fstream& file) 00257 { 00258 size_t size = 0; 00259 if (file.is_open()) 00260 { 00261 streamoff curpos = file.tellg(); 00262 file.seekg(0, ios::end); 00263 size = file.tellg(); 00264 file.seekg(curpos); 00265 } 00266 return size; 00267 } 00268 00269 size_t dami::getFileSize(ifstream& file) 00270 { 00271 size_t size = 0; 00272 if (file.is_open()) 00273 { 00274 streamoff curpos = file.tellg(); 00275 file.seekg(0, ios::end); 00276 size = file.tellg(); 00277 file.seekg(curpos); 00278 } 00279 return size; 00280 } 00281 00282 size_t dami::getFileSize(ofstream& file) 00283 { 00284 size_t size = 0; 00285 if (file.is_open()) 00286 { 00287 streamoff curpos = file.tellp(); 00288 file.seekp(0, ios::end); 00289 size = file.tellp(); 00290 file.seekp(curpos); 00291 } 00292 return size; 00293 } 00294 00295 ID3_Err dami::openWritableFile(String name, fstream& file) 00296 { 00297 if (!exists(name)) 00298 { 00299 return ID3E_NoFile; 00300 } 00301 00302 if (file.is_open()) 00303 { 00304 file.close(); 00305 } 00306 file.open(name.c_str(), ios::in | ios::out | ios::binary | NOCREATE); 00307 if (!file) 00308 { 00309 return ID3E_ReadOnly; 00310 } 00311 00312 return ID3E_NoError; 00313 } 00314 00315 ID3_Err dami::openWritableFile(String name, ofstream& file) 00316 { 00317 if (!exists(name)) 00318 { 00319 return ID3E_NoFile; 00320 } 00321 00322 if (file.is_open()) 00323 { 00324 file.close(); 00325 } 00326 file.open(name.c_str(), ios::in | ios::out | ios::binary | NOCREATE); 00327 if (!file) 00328 { 00329 return ID3E_ReadOnly; 00330 } 00331 00332 return ID3E_NoError; 00333 } 00334 00335 ID3_Err dami::openReadableFile(String name, fstream& file) 00336 { 00337 if (file.is_open()) 00338 { 00339 file.close(); 00340 } 00341 file.open(name.c_str(), ios::in | ios::binary | NOCREATE); 00342 if (!file) 00343 { 00344 return ID3E_NoFile; 00345 } 00346 00347 return ID3E_NoError; 00348 } 00349 00350 ID3_Err dami::openReadableFile(String name, ifstream& file) 00351 { 00352 if (file.is_open()) 00353 { 00354 file.close(); 00355 } 00356 file.open(name.c_str(), ios::in | ios::binary | NOCREATE); 00357 if (!file) 00358 { 00359 return ID3E_NoFile; 00360 } 00361 00362 return ID3E_NoError; 00363 } 00364 00365 String dami::toString(uint32 val) 00366 { 00367 if (val == 0) 00368 { 00369 return "0"; 00370 } 00371 String text; 00372 while (val > 0) 00373 { 00374 String tmp; 00375 char ch = (val % 10) + '0'; 00376 tmp += ch; 00377 text = tmp + text; 00378 val /= 10; 00379 } 00380 return text; 00381 } 00382 00383 WString dami::toWString(const unicode_t buf[], size_t len) 00384 { 00385 WString str; 00386 str.reserve(len); 00387 00388 for (size_t i = 0; i < len; ++i) 00389 { 00390 str += static_cast<WString::value_type>(buf[i]); 00391 } 00392 return str; 00393 } 00394