/* --------------------------------------------------------------------------- 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; }