123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- // The authors have released ID3Lib as Public Domain (PD) and claim no copyright,
- // patent or other intellectual property protection in this work. This means that
- // it may be modified, redistributed and used in commercial and non-commercial
- // software and hardware without restrictions. ID3Lib is distributed on an "AS IS"
- // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- //
- // The ID3Lib authors encourage improvements and optimisations to be sent to the
- // ID3Lib coordinator, currently Dirk Mahoney ([email protected]). Approved
- // submissions may be altered, and will be included and released under these terms.
- //
- // Mon Nov 23 18:34:01 1998
- // improved/optimized/whatever 10/30/00 JF
- // improved/optimized/whatEVER jan-08-2006 benski
- #include <wchar.h>
- #include <string.h>
- #include <stdlib.h>
- #include "id3_field.h"
- #include <windows.h>
- #include "../Plugins/Input/in_mp3/config.h" // TODO: cut
- #include "id3_misc_support.h"
- // this function is another way of using Set()
- #if 0
- ID3_Field &ID3_Field::operator=(wchar_t *string)
- {
- Set(string);
- return *this;
- }
- #endif
- // this is Set()
- void ID3_Field::SetUnicode(const wchar_t *string)
- {
- luint bytesUsed = lstrlenW(string);
- // we can simply increment the
- // bytesUsed count here because
- // we just pilfer the NULL which is
- // present in the string which was
- // passed to us
- if (flags & ID3FF_NULL)
- bytesUsed++;
- // doubling the bytesUsed because
- // Unicode is twice the size of ASCII
- bytesUsed *= sizeof (wchar_t);
- Set ((uchar *) string, bytesUsed);
- type = ID3FTY_UNICODESTRING;
- hasChanged = true;
- }
- void ID3_Field::AddUnicode(const wchar_t *string)
- {
- if (!data)
- SetUnicode(string);
- else
- {
- wchar_t *temp;
- luint newLen;
- lsint nullOffset = 0;
- // if there is a NULL in this string, set this offset
- // so that we ignore it in string size calculations
- if (flags & ID3FF_NULL)
- nullOffset = -1;
- // +1 is for the NULL at the end and the
- // other +1 is for the list divider
- newLen = 1 + (size / sizeof (wchar_t)) + lstrlenW(string) + 1 + nullOffset;
- // I use the value 1 as a divider because then I
- // can change it to either a '/' or a NULL at render
- // time. This allows easy use of these functions
- // for text lists or in the IPLS frame
- if (temp = (wchar_t*)calloc(newLen, sizeof(wchar_t)))
- {
- lstrcpyW(temp, (wchar_t *) data);
- temp[(size / sizeof (wchar_t)) + nullOffset] = L'\001';
- lstrcpyW (&temp[(size / sizeof (wchar_t)) + 1 + nullOffset], string);
- SetUnicode(temp);
- free(temp);
- }
- else
- ID3_THROW (ID3E_NoMemory);
- }
- return;
- }
- // this is Get()
- luint ID3_Field::GetUnicode(wchar_t *buffer, luint maxChars, luint itemNum)
- {
- luint charsUsed = 0;
- // check to see if there is a string in the frame
- // to copy before we even try
- if (data)
- {
- lsint nullOffset = 0;
- if (flags & ID3FF_NULL)
- nullOffset = -1;
- // first we must find which element
- // is being sought to make sure it
- // exists before we try to get it
- if (itemNum <= GetNumTextItems() && itemNum > 0)
- {
- wchar_t *source = (wchar_t *) data;
- luint posn = 0;
- luint sourceLen = 0;
- luint curItemNum = 1;
- luint mx= (size / sizeof (wchar_t)) + nullOffset;
- // now we find that element and set the souvre pointer
- while (posn<mx && curItemNum < itemNum)
- {
- while (posn<mx && *source != L'\001' && *source != L'\0')
- {
- source++;
- posn++;
- }
- source++;
- posn++;
- curItemNum++;
- }
- if(posn>=mx) return 0;
- // now that we are positioned at the first character
- // of the string we want, find the end of it
- while (posn<mx && source[sourceLen] != L'\001' && source[sourceLen] != L'\0')
- {
- sourceLen++;
- posn++;
- }
- if (maxChars) // JF
- {
- // we subtract 1 here so we have
- // room for the NULL terminator
- //maxChars--; // CT
- if (buffer)
- {
- luint actualChars = MIN (maxChars-1, sourceLen);
- wcsncpy (buffer, source, actualChars);
- buffer[actualChars] = L'\0';
- charsUsed = actualChars;
- }
- else
- ID3_THROW (ID3E_NoBuffer);
- }
- }
- }
- return charsUsed;
- }
-
- luint ID3_Field::GetNumTextItems (void)
- {
- luint numItems = 0;
- if (data)
- {
- luint posn = 0;
- numItems++;
- while (posn < size)
- if (data[posn++] == L'\001')
- numItems++;
- }
- return numItems;
- }
- luint ID3_Field::ParseUnicodeString (uchar *buffer, luint posn, luint buffSize)
- {
- luint bytesUsed = 0;
- wchar_t *temp = NULL;
- if (fixedLength != -1)
- bytesUsed = fixedLength;
- else
- {
- if (flags & ID3FF_NULL)
- while ((posn + bytesUsed) < buffSize &&
- ! (buffer[posn + bytesUsed] == 0 && buffer[posn + bytesUsed + 1] == 0))
- bytesUsed += 2;
- else
- bytesUsed = buffSize - posn;
- }
- if (bytesUsed > 0x8ffff)
- {
- hasChanged = false;
- return 0;
- }
- if (bytesUsed)
- {
- if (temp = (wchar_t*)calloc(((bytesUsed / sizeof (wchar_t)) + 1), sizeof(wchar_t)))
- {
- luint loc = 0;
- memcpy (temp, &buffer[posn], bytesUsed);
- temp[bytesUsed / sizeof (wchar_t)] = 0;
- // if there is a BOM, skip past it and check to see if we
- // need to swap the byte order around
- if (temp[0] == 0xFEFF || temp[0] == 0xFFFE)
- {
- loc++;
- // if we need to swap the byte order
- if (temp[0] != 0xFEFF)
- {
- int mylen=(int) lstrlenW(temp);
- for (int i = loc; i < mylen; i++)
- temp[i] = ((temp[i] >> 8) & 0xFF) | (((temp[i]) & 0xFF) << 8);
- }
- }
- SetUnicode(&temp[loc]);
- free(temp);
- }
- else
- ID3_THROW (ID3E_NoMemory);
- }
- if (flags & ID3FF_NULL)
- bytesUsed += 2;
- hasChanged = false;
- return bytesUsed;
- }
- luint ID3_Field::RenderUnicodeString(uchar *buffer)
- {
- luint bytesUsed = 0;
- bytesUsed = BinSize();
- if (data && size && bytesUsed >= sizeof (wchar_t))
- {
- wchar_t *ourString = (wchar_t *) &buffer[sizeof(wchar_t)];
- // we render at sizeof (wchar_t) bytes into the buffer
- // because we make room for the Unicode BOM
- memcpy (&buffer[sizeof (wchar_t)], (uchar *) data, bytesUsed - sizeof (wchar_t));
- // now we convert the internal dividers to what they
- // are supposed to be
- size_t numChars = bytesUsed / sizeof (wchar_t);
- for (size_t i = 0; i != numChars-1; i++)
- if (ourString[i] == 1)
- {
- wchar_t sub = L'/';
- if (flags & ID3FF_NULLDIVIDE)
- sub = L'\0';
- ourString[i] = sub;
- }
- }
- if (bytesUsed)
- {
- // render the BOM
- wchar_t *BOM = (wchar_t *) buffer;
- BOM[0] = 0xFEFF;
- }
- if (bytesUsed == 2 && (flags & ID3FF_NULL))
- buffer[0] = buffer[1] = 0;
- hasChanged = false;
- return bytesUsed;
- }
- luint ID3_Field::RenderUTF8String(uchar *buffer)
- {
- luint bytesUsed = 0;
- buffer[0] = 0;
- bytesUsed = BinSize();
- if (data && size)
- {
- luint i;
- ID3_UnicodeToUTF8( (char*)buffer, (const wchar_t *) data, bytesUsed, bytesUsed);
- for (i = 0;i < bytesUsed; i++)
- {
- if (buffer[i] == 1)
- {
- char sub = '/';
- if (flags & ID3FF_NULLDIVIDE)
- sub = '\0';
- buffer[i] = sub;
- }
- }
- }
- if (bytesUsed == 1 && flags & ID3FF_NULL)
- buffer[0] = 0;
- hasChanged = false;
- return bytesUsed;
- }
|