| 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 0ID3_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;}
 |