123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- #include "frame_utils.h"
- #include "foundation/error.h"
- #include "nsid3v2/nsid3v2.h"
- #if defined(_WIN32) && !defined(strcasecmp)
- #define strcasecmp _stricmp
- #else
- #include <string.h>
- #endif
- int ParseDescription(const char *&str, size_t &data_len, size_t &str_cch)
- {
- str_cch=0;
- while (data_len && str[str_cch])
- {
- data_len--;
- str_cch++;
- }
- if (!data_len)
- return NErr_Error;
- data_len--;
- return NErr_Success;
- }
- int ParseDescription(const wchar_t *&str, size_t &data_len, size_t &str_cch, uint8_t &str_encoding)
- {
- str_cch=0;
- if (data_len > 2 && str[0] == 0xFFFE)
- {
- str_encoding=2;
- str++;
- str-=3;
- }
- else if (data_len > 2 && str[0] == 0xFEFF)
- {
- str_encoding=1;
- str++;
- data_len-=3;
- }
- else
- {
- data_len--;
- }
- while (data_len > 1 && str[str_cch])
- {
- data_len-=2;
- str_cch++;
- }
- if (!data_len)
- return NErr_Error;
- data_len-=2;
- return NErr_Success;
- }
- static void ParseBOM(bytereader_t reader, uint8_t *encoding, const uint8_t default_encoding)
- {
- if (bytereader_size(reader) >= 2)
- {
- uint16_t bom = bytereader_show_u16_le(reader);
- if (bom == 0xFFFE)
- {
- bytereader_advance(reader, 2);
- *encoding=2;
- }
- else if (bom == 0xFEFF)
- {
- bytereader_advance(reader, 2);
- *encoding=1;
- }
- else
- {
- *encoding=default_encoding;
- }
- }
- else
- {
- *encoding=default_encoding;
- }
- }
- int ParseNullTerminatedString(bytereader_t reader, uint8_t encoding, ParsedString &parsed)
- {
- switch(encoding)
- {
- case 0: // ISO-8859-1
- if (bytereader_size(reader) == 0)
- return NErr_Insufficient;
- parsed.encoding = 0;
- parsed.data = bytereader_pointer(reader);
- parsed.byte_length = 0;
- while (bytereader_size(reader) && bytereader_read_u8(reader))
- parsed.byte_length++;
- return NErr_Success;
- case 1: // UTF-16
- if (bytereader_size(reader) < 2)
- return NErr_Insufficient;
- parsed.byte_length = 0;
- ParseBOM(reader, &parsed.encoding, 1);
- parsed.data = bytereader_pointer(reader);
- while (bytereader_size(reader) && bytereader_read_u16_le(reader))
- parsed.byte_length+=2;
- return NErr_Success;
- case 2: // UTF-16BE
- if (bytereader_size(reader) < 2)
- return NErr_Insufficient;
- parsed.byte_length = 0;
- ParseBOM(reader, &parsed.encoding, 2);
- parsed.data = bytereader_pointer(reader);
- while (bytereader_size(reader) && bytereader_read_u16_le(reader))
- parsed.byte_length+=2;
- return NErr_Success;
- case 3: // UTF-8
- if (bytereader_size(reader) == 0)
- return NErr_Insufficient;
- parsed.encoding = 3;
- parsed.data = bytereader_pointer(reader);
- parsed.byte_length = 0;
- size_t start = bytereader_size(reader);
- #if 0 // TODO
- /* check for UTF-8 BOM and skip it */
- if (bytereader_size(reader) > 3 && bytereader_read_u8(reader) == 0xEF && bytereader_read_u8(reader) == 0xBB && bytereader_read_u8(reader) == 0xBF)
- {
- parsed.data = bytereader_pointer(reader);
- parsed.byte_length = bytereader_size(reader);
- }
- else
- {
- /* no BOM but skip however far we read into the string */
- size_t offset = start - bytereader_size(reader);
- parsed.data = (const uint8_t *)parsed.data + offset;
- parsed.byte_length -= offset;
- }
- #endif
- /* finish it up */
- while (bytereader_size(reader) && bytereader_read_u8(reader))
- parsed.byte_length++;
- return NErr_Success;
- }
- return NErr_Unknown;
- }
- int ParseFrameTerminatedString(bytereader_t reader, uint8_t encoding, ParsedString &parsed)
- {
- switch(encoding)
- {
- case 0: // ISO-8859-1
- parsed.encoding = 0;
- parsed.data = bytereader_pointer(reader);
- parsed.byte_length = bytereader_size(reader);
- return NErr_Success;
- case 1: // UTF-16
- if ((bytereader_size(reader) & 1) == 1)
- return NErr_Error;
- ParseBOM(reader, &parsed.encoding, 1);
- parsed.data = bytereader_pointer(reader);
- parsed.byte_length = bytereader_size(reader);
- return NErr_Success;
- case 2: // UTF-16BE
- if ((bytereader_size(reader) & 1) == 1)
- return NErr_Error;
- ParseBOM(reader, &parsed.encoding, 2);
- parsed.data = bytereader_pointer(reader);
- parsed.byte_length = bytereader_size(reader);
- return NErr_Success;
- case 3: // UTF-8
- parsed.encoding = 3;
- parsed.data = bytereader_pointer(reader);
- parsed.byte_length = bytereader_size(reader);
- if (bytereader_size(reader) > 3 && bytereader_read_u8(reader) == 0xEF && bytereader_read_u8(reader) == 0xBB && bytereader_read_u8(reader) == 0xBF)
- {
- parsed.data = bytereader_pointer(reader);
- parsed.byte_length = bytereader_size(reader);
- }
- return NErr_Success;
- }
- return NErr_Error;
- }
- int NXStringCreateFromParsedString(nx_string_t *value, ParsedString &parsed, int text_flags)
- {
- switch(parsed.encoding)
- {
- case 0: // ISO-8859-1
- if (parsed.byte_length == 0)
- return NXStringCreateEmpty(value);
- if (text_flags & NSID3V2_TEXT_SYSTEM)
- return NXStringCreateWithBytes(value, parsed.data, parsed.byte_length, nx_charset_system);
- else
- return NXStringCreateWithBytes(value, parsed.data, parsed.byte_length, nx_charset_latin1);
- case 1: // UTF-16
- if (parsed.byte_length < 2)
- return NXStringCreateEmpty(value);
- return NXStringCreateWithBytes(value, parsed.data, parsed.byte_length, nx_charset_utf16le);
- case 2: // UTF-16BE
- if (parsed.byte_length < 2)
- return NXStringCreateEmpty(value);
- return NXStringCreateWithBytes(value, parsed.data, parsed.byte_length, nx_charset_utf16be);
- case 3: // UTF-8
- if (parsed.byte_length == 0)
- return NXStringCreateEmpty(value);
- return NXStringCreateWithBytes(value, parsed.data, parsed.byte_length, nx_charset_utf8);
- default:
- return NErr_Unknown;
- }
-
- }
- bool DescriptionMatches(const ParsedString &parsed, const char *description, int text_flags)
- {
- // see if our description matches
- switch(parsed.encoding)
- {
- case 0: // ISO-8859-1
- return !strcasecmp(description, (const char *)parsed.data);
- case 1:
- {
- bytereader_value_t utf16;
- bytereader_init(&utf16, parsed.data, parsed.byte_length);
-
- while (*description && bytereader_size(&utf16))
- {
- if ((*description++ & ~0x20) != (bytereader_read_u16_le(&utf16) & ~0x20))
- return false;
- }
- if (*description == 0 && bytereader_size(&utf16) == 0)
- return true;
- else
- return false;
- }
- case 2:
- {
- bytereader_value_t utf16;
- bytereader_init(&utf16, parsed.data, parsed.byte_length);
-
- while (*description && bytereader_size(&utf16))
- {
- if ((*description++ & ~0x20) != (bytereader_read_u16_be(&utf16) & ~0x20))
- return false;
- }
- if (*description == 0 && bytereader_size(&utf16) == 0)
- return true;
- else
- return false;
- }
- case 3:
- return !strcasecmp(description, (const char *)parsed.data);
- }
- return false;
- }
|