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