20#define __DCL_TRACE1_N __DCL_TRACE1
21#define __DCL_TRACE2_N __DCL_TRACE2
22#define __DCL_TRACE3_N __DCL_TRACE3
23#define __DCL_TRACE4_N __DCL_TRACE4
25#define __DCL_TRACE1_N(fmt, arg)
26#define __DCL_TRACE2_N(fmt, arg1, arg2)
27#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
28#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
41 : __header{
'\0', }, __data(
NULL), __fsbits(0)
52 for (
size_t i = 0; i <
__frames.size(); i++) {
57uint32_t ID3v2::word7(
const char* _bytes,
size_t _n)
60 const char* end = _bytes + _n;
61 while (_bytes < end) {
62 r =
r << 7 | (0x7f & *_bytes++);
67uint32_t ID3v2::word8(
const char* _bytes,
size_t _n)
70 const char* end = _bytes + _n;
71 while (_bytes < end) {
82 while (_begin < _end) {
83 if (!(isupper(*_begin) || isdigit(*_begin))) {
92 const char* _begin,
const char* _end,
bool _debug)
102 const char* p = _begin;
104 while (p + __6_or_10 < _end && *p !=
'\0') {
107 uint32_t size = ID3v2::word8(p + __3_or_4, __3_or_4);
111 p += size + __6_or_10;
122 if (p > _end || (p < _end && *p !=
'\0')) {
138 while (p + __6_or_10 < _end && *p !=
'\0') {
141 uint32_t size = ID3v2::word7(p + __3_or_4, __3_or_4);
145 p += size + __6_or_10;
156 if (p > _end || (p < _end && *p !=
'\0')) {
172bool ID3v2::read(
File& _file,
const char _header[10])
175 if (_header ==
NULL) {
188 __DCL_TRACE1_N(L
"[%ls]\n", String::tryString(_header, 10).data());
189 if (!(_header[0] ==
'I' && _header[1] ==
'D' && _header[2] ==
'3'
193 && _header[6] < 0x80 && _header[7] < 0x80
194 && _header[8] < 0x80 && _header[9] < 0x80)) {
199 __size = word7(&_header[6], 4);
211 const char* _begin =
__data;
212 const char* _end = _begin +
n;
231 size_t __6_or_10 = 6;
236 while ((_begin + __6_or_10 < _end) && *_begin !=
'\0') {
237 if (
'A' <= *_begin && *_begin <=
'Z') {
238 ID3v2Frame* frame =
new ID3v2Frame(*
this);
239 _begin += frame->
read(_begin, _end);
244 catch (Exception* e) {
246 __DCL_TRACE1_N(L
"[%ls]\n", String::tryString(_begin, _end - _begin, 80).data());
265 return String::format(L
""
266 "%ls version[%d] revision[%d] flags[%x] size[%d] fsbits[%d]",
267 ID3().data(), version(), revision(), flags(), size(), fsbits()
278 uint32_t
r = word7(&_begin[0], 4);
279 __DCL_TRACE1(L
"Number of flag bytes [%d]\n", (
int)_begin[4]);
294String ID3v2Frame::decode(
296 const char* _mbs,
size_t _nmbs
304 Latin1Decoder decoder;
305 r = decoder.
decode(_mbs, _nmbs);
309 if (_nmbs == 2 && (
byte_t)*_mbs == 0xFF) {
322 r = decoder.
decode(_mbs, _nmbs);
326 if (_nmbs == 2 && (
byte_t)*_mbs == 0xFE) {
331 r = decoder.
decode(_mbs, _nmbs);
336 r = decoder.decode(_mbs, _nmbs);
341 catch (Exception* _e) {
343 _nmbs, String::tryString(_mbs, _nmbs).data());
353 if (_encoding == 1 || _encoding == 2) {
355 while ((*_psz++ | *_psz++) &&
r < _max) {
358 return r < _max ?
r: _max;
363 while (*_psz++ &&
r < _max) {
373 return _encoding == 1 || _encoding == 2 ? _n + 2 : _n + 1;
379 return (_lang[0] ==
'X' && _lang[1] ==
'X' && _lang[2] ==
'X') ||
380 (islower(_lang[0]) && islower(_lang[1]) && islower(_lang[2]));
385 size_t __6_OR_10__ =
__tag.version() == 2 ? 6 : 10;
389 char FIRST = *_begin;
390 if (
__tag.version() == 2) {
402#define __IF_ENCODING__ \
403 if (_begin < _end) { \
404 __encoding = *_begin++; \
406#define __IF_LANGUAGE__ \
407 if (_begin + 3 < _end && __valid_language_code(_begin)) { \
408 __url = AsciiDecoder::decode(_begin, 3).trim(); \
411#define __IF_DESCRIPTION__ \
412 if (_begin < _end) { \
413 size_t n = __decode_length__(__encoding, _begin, _end - _begin); \
414 __description = decode(__encoding, _begin, n).trim(); \
415 _begin += __skip_length__(__encoding, n); \
418 if (_begin < _end) { \
419 size_t n = __decode_length__(__encoding, _begin, _end - _begin); \
420 __text = decode(__encoding, _begin, n).trim(); \
421 _begin += __skip_length__(__encoding, n); \
424 if (_begin < _end) { \
425 size_t n = ByteString::length(_begin, _end - _begin); \
426 __url = decode(0, _begin, n).trim(); \
430 if (_begin < _end) { \
431 __type = *_begin++; \
433#define __IF_BINARY__ \
434 if (_begin < _end) { \
435 __binary.assign(_begin, _end - _begin); \
438 _begin += __6_OR_10__;
463 if (
__id == L
"AENC") {
467 else if (
__id == L
"APIC") {
468 uint32_t dataLength = 0;
470 dataLength =
word(_begin, 4);
474 dataLength, String::tryString(_begin,
__size, 40).data());
481 dataLength > 0 ? dataLength : _end - _begin);
491 if (
__id == L
"COMM" ||
__id == L
"COM") {
497 else if (
__id == L
"CRA") {
508 if (
__id == L
"GEOB" ||
__id == L
"GEO") {
522 if (
__id == L
"PIC") {
532 else if (
__id == L
"PRIV") {
545 if (
__id.compare(L
"IPL", 3) != 0) {
553 if (
__id.compare(L
"TXX", 3) == 0) {
561 if (
__id.compare(L
"UFI", 3) == 0) {
565 size_t n = _end - _begin;
576 if (
__id == L
"USLT" ||
__id == L
"ULT") {
583 if (
__id.compare(L
"WXX", 3)) {
593 return __size + __6_OR_10__;
598 StringBuilder sb(
__id);
599 sb.format(L
" size[%d] flags[%x] encoding[%d] type[%d]",
601 if (!
__url.isEmpty()) {
602 sb.format(L
" url[%ls]",
__url.data());
608 sb.format(L
" text[%ls]",
__text.data());
611 sb.format(L
" binary[%zd][%ls]",
__binary.length(),
612 String::tryString(
__binary, 40).data());
#define __DCL_TRACE1_N(fmt, arg)
#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
bool __valid_language_code(const char _lang[3])
bool __IS_UPPER(const char *_begin, const char *_end)
size_t __skip_length__(char _encoding, size_t _n)
#define __IF_DESCRIPTION__
size_t __decode_length__(char _encoding, const char *_psz, size_t _max)
int __find_frame_size_bits(char _version, const char *_begin, const char *_end, bool _debug)
#define Extended_header(flags)
#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
#define __DCL_TRACE0(psz)
#define __DCL_TRACE1(fmt, arg1)
#define __DCL_ASSERT_PARAM(expr)
#define __DCL_TRACE3(fmt, arg1, arg2, arg3)
#define __DCL_ASSERT(expr)
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
#define __DCL_TRACE2(fmt, arg1, arg2)
void CharsetConvertException *size_t n
static String decode(const char *_mbs, size_t _mbslen=(size_t) -1)
String toStringAll() const
off_t seek(off_t _offset, int _whence) __DCL_THROWS1(IOException *)
virtual size_t read(void *_buf, size_t _n) __DCL_THROWS1(IOException *)
const String & path() const
ID3v2Frame(const ID3v2 &_tag)
uint32_t word(const char *_bytes, size_t _n)
virtual String toString() const
size_t read(const char *_begin, const char *_end)
size_t skipExtendedHeader(const char *_begin, const char *_end) const
static String decode(const char *_mbs, size_t _nmbs=(size_t) -1)
virtual String toString() const
size_t __MIN(size_t x, size_t y)