298 lines
6.8 KiB
C++
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;
|
|
}
|
|
|