00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #if defined HAVE_CONFIG_H
00028 #include <config.h>
00029 #endif
00030
00031
00032
00033 #include "io_decorators.h"
00034 #include "io_helpers.h"
00035 #include "utils.h"
00036
00037 using namespace dami;
00038
00039 String io::readString(ID3_Reader& reader)
00040 {
00041 String str;
00042 while (!reader.atEnd())
00043 {
00044 ID3_Reader::char_type ch = reader.readChar();
00045 if (ch == '\0')
00046 {
00047 break;
00048 }
00049 str += static_cast<char>(ch);
00050 }
00051 return str;
00052 }
00053
00054 String io::readText(ID3_Reader& reader, size_t len)
00055 {
00056 String str;
00057 str.reserve(len);
00058 const size_t SIZE = 1024;
00059 ID3_Reader::char_type buf[SIZE];
00060 size_t remaining = len;
00061 while (remaining > 0 && !reader.atEnd())
00062 {
00063 size_t numRead = reader.readChars(buf, min(remaining, SIZE));
00064 remaining -= numRead;
00065 str.append(reinterpret_cast<String::value_type *>(buf), numRead);
00066 }
00067 return str;
00068 }
00069
00070 namespace
00071 {
00072 bool isNull(unsigned char ch1, unsigned char ch2)
00073 {
00074 return ch1 == '\0' && ch2 == '\0';
00075 }
00076
00077 int isBOM(unsigned char ch1, unsigned char ch2)
00078 {
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 if (ch1 == 0xFE && ch2 == 0xFF)
00099 {
00100 return 1;
00101 }
00102 else if (ch1 == 0xFF && ch2 == 0xFE)
00103 {
00104 return -1;
00105 }
00106 return 0;
00107 }
00108
00109 bool readTwoChars(ID3_Reader& reader,
00110 ID3_Reader::char_type& ch1,
00111 ID3_Reader::char_type& ch2)
00112 {
00113 if (reader.atEnd())
00114 {
00115 return false;
00116 }
00117 io::ExitTrigger et(reader);
00118 ch1 = reader.readChar();
00119 if (reader.atEnd())
00120 {
00121 return false;
00122 }
00123 et.release();
00124 ch2 = reader.readChar();
00125 return true;
00126 }
00127 }
00128
00129 String io::readUnicodeString(ID3_Reader& reader)
00130 {
00131 String unicode;
00132 ID3_Reader::char_type ch1, ch2;
00133 if (!readTwoChars(reader, ch1, ch2) || isNull(ch1, ch2))
00134 {
00135 return unicode;
00136 }
00137 int bom = isBOM(ch1, ch2);
00138 if (!bom)
00139 {
00140 unicode += static_cast<char>(ch1);
00141 unicode += static_cast<char>(ch2);
00142 }
00143 while (!reader.atEnd())
00144 {
00145 if (!readTwoChars(reader, ch1, ch2) || isNull(ch1, ch2))
00146 {
00147 break;
00148 }
00149 if (bom == -1)
00150 {
00151 unicode += static_cast<char>(ch2);
00152 unicode += static_cast<char>(ch1);
00153 }
00154 else
00155 {
00156 unicode += static_cast<char>(ch1);
00157 unicode += static_cast<char>(ch2);
00158 }
00159 }
00160 return unicode;
00161 }
00162
00163 String io::readUnicodeText(ID3_Reader& reader, size_t len)
00164 {
00165 String unicode;
00166 ID3_Reader::char_type ch1, ch2;
00167 if (!readTwoChars(reader, ch1, ch2))
00168 {
00169 return unicode;
00170 }
00171 len -= 2;
00172 int bom = isBOM(ch1, ch2);
00173 if (!bom)
00174 {
00175 unicode += ch1;
00176 unicode += ch2;
00177 unicode += readText(reader, len);
00178 }
00179 else if (bom == 1)
00180 {
00181 unicode = readText(reader, len);
00182 }
00183 else
00184 {
00185 for (index_t i = 0; i < len; i += 2)
00186 {
00187 if (!readTwoChars(reader, ch1, ch2))
00188 {
00189 break;
00190 }
00191 unicode += ch2;
00192 unicode += ch1;
00193 }
00194 }
00195 return unicode;
00196 }
00197
00198 BString io::readAllBinary(ID3_Reader& reader)
00199 {
00200 return readBinary(reader, reader.remainingBytes());
00201 }
00202
00203 BString io::readBinary(ID3_Reader& reader, size_t len)
00204 {
00205 BString binary;
00206 binary.reserve(len);
00207
00208 size_t remaining = len;
00209 const size_t SIZE = 1024;
00210 ID3_Reader::char_type buf[SIZE];
00211 while (!reader.atEnd() && remaining > 0)
00212 {
00213 size_t numRead = reader.readChars(buf, min(remaining, SIZE));
00214 remaining -= numRead;
00215 binary.append(reinterpret_cast<BString::value_type *>(buf), numRead);
00216 }
00217
00218 return binary;
00219 }
00220
00221 uint32 io::readLENumber(ID3_Reader& reader, size_t len)
00222 {
00223 uint32 val = 0;
00224 for (size_t i = 0; i < len; i++)
00225 {
00226 if (reader.atEnd())
00227 {
00228 break;
00229 }
00230 val += (static_cast<uint32>(0xFF & reader.readChar()) << (i * 8));
00231 }
00232 return val;
00233 }
00234
00235 uint32 io::readBENumber(ID3_Reader& reader, size_t len)
00236 {
00237 uint32 val = 0;
00238
00239 for (ID3_Reader::size_type i = 0; i < len && !reader.atEnd(); ++i)
00240 {
00241 val *= 256;
00242 val += static_cast<uint32>(0xFF & reader.readChar());
00243 }
00244 return val;
00245 }
00246
00247 String io::readTrailingSpaces(ID3_Reader& reader, size_t len)
00248 {
00249 io::WindowedReader wr(reader, len);
00250 String str;
00251 String spaces;
00252 str.reserve(len);
00253 spaces.reserve(len);
00254 while (!wr.atEnd())
00255 {
00256 ID3_Reader::char_type ch = wr.readChar();
00257 if (ch == '\0' || ch == ' ')
00258 {
00259 spaces += ch;
00260 }
00261 else
00262 {
00263 str += spaces + (char) ch;
00264 spaces.erase();
00265 }
00266 }
00267 return str;
00268 }
00269
00270 uint32 io::readUInt28(ID3_Reader& reader)
00271 {
00272 uint32 val = 0;
00273 const unsigned short BITSUSED = 7;
00274 const uint32 MAXVAL = MASK(BITSUSED * sizeof(uint32));
00275
00276 for (size_t i = 0; i < sizeof(uint32); ++i)
00277 {
00278 if (reader.atEnd())
00279 {
00280 break;
00281 }
00282
00283 val = (val << BITSUSED) | static_cast<uint32>(reader.readChar()) & MASK(BITSUSED);
00284 }
00285
00286
00287 return min(val, MAXVAL);
00288 }
00289
00290 size_t io::writeBENumber(ID3_Writer& writer, uint32 val, size_t len)
00291 {
00292 ID3_Writer::char_type bytes[sizeof(uint32)];
00293 ID3_Writer::size_type size = min<ID3_Reader::size_type>(len, sizeof(uint32));
00294 renderNumber(bytes, val, size);
00295 return writer.writeChars(bytes, size);
00296 }
00297
00298 size_t io::writeTrailingSpaces(ID3_Writer& writer, String buf, size_t len)
00299 {
00300 ID3_Writer::pos_type beg = writer.getCur();
00301 ID3_Writer::size_type strLen = buf.size();
00302 ID3_Writer::size_type size = min(len,strLen);
00303 writer.writeChars(buf.data(), size);
00304 for (; size < len; ++size)
00305 {
00306 writer.writeChar(' ');
00307 }
00308 return writer.getCur() - beg;
00309 }
00310
00311 size_t io::writeUInt28(ID3_Writer& writer, uint32 val)
00312 {
00313 uchar data[sizeof(uint32)];
00314 const unsigned short BITSUSED = 7;
00315 const uint32 MAXVAL = MASK(BITSUSED * sizeof(uint32));
00316 val = min(val, MAXVAL);
00317
00318
00319
00320 for (size_t i = 0; i < sizeof(uint32); ++i)
00321 {
00322
00323
00324 data[sizeof(uint32) - i - 1] = static_cast<uchar>(val & MASK(BITSUSED));
00325
00326
00327
00328 val >>= BITSUSED;
00329 }
00330
00331
00332 return writer.writeChars(data, sizeof(uint32));
00333 }
00334
00335 size_t io::writeString(ID3_Writer& writer, String data)
00336 {
00337 size_t size = writeText(writer, data);
00338 writer.writeChar('\0');
00339 return size + 1;
00340 }
00341
00342 size_t io::writeText(ID3_Writer& writer, String data)
00343 {
00344 ID3_Writer::pos_type beg = writer.getCur();
00345 writer.writeChars(data.data(), data.size());
00346 return writer.getCur() - beg;
00347 }
00348
00349 size_t io::writeUnicodeString(ID3_Writer& writer, String data, bool bom)
00350 {
00351 size_t size = writeUnicodeText(writer, data, bom);
00352 unicode_t null = NULL_UNICODE;
00353 writer.writeChars((const unsigned char*) &null, 2);
00354 return size + 2;
00355 }
00356
00357 size_t io::writeUnicodeText(ID3_Writer& writer, String data, bool bom)
00358 {
00359 ID3_Writer::pos_type beg = writer.getCur();
00360 size_t size = (data.size() / 2) * 2;
00361 if (size == 0)
00362 {
00363 return 0;
00364 }
00365 if (bom)
00366 {
00367
00368 unicode_t BOM = 0xFEFF;
00369 writer.writeChars((const unsigned char*) &BOM, 2);
00370 for (size_t i = 0; i < size; i += 2)
00371 {
00372 unicode_t ch = (data[i] << 8) | data[i+1];
00373 writer.writeChars((const unsigned char*) &ch, 2);
00374 }
00375 }
00376 return writer.getCur() - beg;
00377 }