winamp/Src/nde/osx/StringField.cpp
2024-09-24 14:54:57 +02:00

298 lines
6.8 KiB
C++

/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
StringField Class
Mac OS X (CFStringRef) implementation
--------------------------------------------------------------------------- */
#include "../nde.h"
#include "StringField.h"
//---------------------------------------------------------------------------
StringField::StringField(CFStringRef Str)
{
InitField();
Type = FIELD_STRING;
if (Str)
{
SetNDEString(Str);
}
}
//---------------------------------------------------------------------------
void StringField::InitField(void)
{
Type = FIELD_STRING;
String=0;
}
//---------------------------------------------------------------------------
StringField::StringField()
{
InitField();
}
//---------------------------------------------------------------------------
StringField::~StringField()
{
if (String)
CFRelease(String);
}
//---------------------------------------------------------------------------
void StringField::ReadTypedData(const uint8_t *data, size_t len)
{
unsigned short c;
CHECK_SHORT(len);
c = (unsigned short)(data[0]|(data[1]<<8));
data+=2;
if (c)
{
bool unicode=false;
if (c >= 2 // enough room for BOM
&& (c % 2) == 0) // can't be unicode if it's not an even multiple of 2
{
wchar_t BOM=0;
memcpy(&BOM, data, 2);
if (BOM == 0xFEFF || BOM == 0xFFFE)
{
unicode=true;
}
}
CHECK_BIN(len, c);
if (unicode)
{
if (String)
CFRelease(String);
String = CFStringCreateWithBytes(kCFAllocatorDefault, data, c, kCFStringEncodingUTF16, true);
}
else
{
if (String)
CFRelease(String);
String = CFStringCreateWithBytes(kCFAllocatorDefault, data, c, kCFStringEncodingWindowsLatin1, false);
}
}
}
//---------------------------------------------------------------------------
void StringField::WriteTypedData(uint8_t *data, size_t len)
{
int pos=0;
CHECK_SHORT(len);
if (String)
{
CFIndex lengthRequired=0;
CFStringGetBytes(String, CFRangeMake(0, CFStringGetLength(String)), kCFStringEncodingUTF16, 0, true, NULL, 0, &lengthRequired);
CHECK_BIN(len, lengthRequired+2);
PUT_SHORT(lengthRequired); pos+=2;
CFStringGetBytes(String, CFRangeMake(0, CFStringGetLength(String)), kCFStringEncodingUTF16, 0, true, data+pos, lengthRequired, 0);
}
else
{
PUT_SHORT(0);
}
}
CFStringRef StringField::GetString()
{
return String;
}
void StringField::SetNDEString(CFStringRef Str)
{
if (!Str)
return;
CFStringRef old = String;
String = (CFStringRef)CFRetain(Str);
CFRelease(old);
}
//---------------------------------------------------------------------------
size_t StringField::GetDataSize(void)
{
if (String)
{
CFIndex lengthRequired=0;
CFStringGetBytes(String, CFRangeMake(0, CFStringGetLength(String)), kCFStringEncodingUTF16, 0, true, NULL, 0, &lengthRequired);
return lengthRequired+2;
}
else
return 2;
}
//---------------------------------------------------------------------------
int StringField::Compare(Field *Entry)
{
if (!Entry) return -1;
if (Entry->GetType() != GetType()) return 0;
CFStringRef compareString = ((StringField*)Entry)->GetString();
if (!String && !compareString) return 0;
if (!String && compareString) return 1;
if (!compareString) return -1;
return CFStringCompare(String, compareString, kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareDiacriticInsensitive);
}
//---------------------------------------------------------------------------
int StringField::Starts(Field *Entry)
{
if (!Entry) return -1;
if (Entry->GetType() != GetType()) return 0;
CFStringRef compareString = ((StringField*)Entry)->GetString();
if (!String || !compareString) return 0;
CFRange findRange = CFStringFind(String, compareString, kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareAnchored|kCFCompareDiacriticInsensitive);
if (findRange.location == kCFNotFound)
return 0;
return findRange.location == 0;
}
//---------------------------------------------------------------------------
int StringField::Contains(Field *Entry)
{
if (!Entry) return -1;
if (Entry->GetType() != GetType()) return 0;
CFStringRef compareString = ((StringField*)Entry)->GetString();
if (!String || !compareString) return 0;
CFRange findRange = CFStringFind(String, compareString, kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareDiacriticInsensitive);
return findRange.location != kCFNotFound;
}
Field *StringField::Clone(Table *pTable)
{
StringField *clone = new StringField(String);
clone->Pos = FIELD_CLONE;
clone->ID = ID;
clone->MaxSizeOnDisk = GetDataSize();
return clone;
}
//---------------------------------------------------------------------------
bool StringField::ApplyFilter(Field *Data, int op)
{
if (op == FILTER_ISEMPTY || op == FILTER_ISNOTEMPTY)
{
bool r = (op == FILTER_ISEMPTY);
if (!String)
return r;
if (CFStringGetLength(String) == 0)
return r;
return !r;
}
//
bool r;
StringField *compField = (StringField *)Data;
switch (op)
{
case FILTER_EQUALS:
r = !Compare(Data);
break;
case FILTER_NOTEQUALS:
r = !!Compare(Data);
break;
case FILTER_CONTAINS:
r = !!Contains(Data);
break;
case FILTER_NOTCONTAINS:
r = !Contains(Data);
break;
case FILTER_ABOVE:
r = (bool)(Compare(Data) > 0);
break;
case FILTER_ABOVEOREQUAL:
r = (bool)(Compare(compField) >= 0);
break;
case FILTER_BELOW:
r = (bool)(Compare(compField) < 0);
break;
case FILTER_BELOWOREQUAL:
r = (bool)(Compare(compField) <= 0);
break;
case FILTER_BEGINS:
r = !!Starts(compField);
break;
case FILTER_ENDS:
{
CFStringRef compareString = ((StringField*)Data)->GetString();
if (!String || !compareString) return 0;
CFRange findRange = CFStringFind(String, compareString, kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareAnchored|kCFCompareBackwards);
if (findRange.location == kCFNotFound)
r=0;
else
r = findRange.location != 0;
}
break;
case FILTER_LIKE:
/* TODO
if (compField->optimized_the)
p = compField->optimized_the;
else
{
SKIP_THE_AND_WHITESPACEW(p);
compField->optimized_the = p;
}
if (optimized_the)
d = optimized_the;
else
{
SKIP_THE_AND_WHITESPACEW(d);
optimized_the=d;
}
r = (bool)(nde_wcsicmp(d, p) == 0);
*/
r = !!Compare(compField);
break;
case FILTER_BEGINSLIKE:
/*
if (compField->optimized_the)
p = compField->optimized_the;
else
{
SKIP_THE_AND_WHITESPACEW(p);
compField->optimized_the = p;
}
if (optimized_the)
d = optimized_the;
else
{
SKIP_THE_AND_WHITESPACEW(d);
optimized_the=d;
}
r = (bool)(nde_wcsnicmp(d, p, wcslen(p)) == 0);
*/
r = !!Starts(compField);
break;
default:
r = true;
break;
}
return r;
}