mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-11-15 03:15:05 -05:00
292 lines
6.3 KiB
C++
292 lines
6.3 KiB
C++
/* ---------------------------------------------------------------------------
|
|
Nullsoft Database Engine
|
|
--------------------
|
|
codename: Near Death Experience
|
|
--------------------------------------------------------------------------- */
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
|
|
StringField Class
|
|
Android (linux) specific version
|
|
|
|
Field data layout:
|
|
[2 bytes] string length (bytes)
|
|
[length bytes] String data. UTF-16 data will start with a BOM
|
|
|
|
--------------------------------------------------------------------------- */
|
|
|
|
#include "../nde.h"
|
|
#include "StringField.h"
|
|
|
|
//---------------------------------------------------------------------------
|
|
StringField::StringField(const char *Str, int strkind)
|
|
{
|
|
InitField();
|
|
Type = FIELD_STRING;
|
|
if (Str)
|
|
{
|
|
if (strkind == STRING_IS_WCHAR)
|
|
String = ndestring_wcsdup(Str);
|
|
else
|
|
{
|
|
String = const_cast<char *>(Str);
|
|
ndestring_retain(String);
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void StringField::InitField(void)
|
|
{
|
|
Type = FIELD_STRING;
|
|
// String = NULL;
|
|
String = NULL;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
StringField::StringField()
|
|
{
|
|
InitField();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
StringField::~StringField()
|
|
{
|
|
ndestring_release(String);
|
|
String=0;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
void StringField::ReadTypedData(const uint8_t *data, size_t len)
|
|
{
|
|
size_t pos=0;
|
|
unsigned short c;
|
|
|
|
CHECK_SHORT(len);
|
|
c = GET_SHORT();
|
|
pos+=2;
|
|
if (c)
|
|
{
|
|
bool unicode=false;
|
|
bool utf16BE=false;
|
|
if (c >= 2 // enough room for BOM
|
|
&& (c & 1) == 0) // can't be unicode if it's not an even multiple of 2
|
|
{
|
|
uint16_t BOM=GET_SHORT();
|
|
if (BOM == 0xFEFF)
|
|
{
|
|
pos+=2;
|
|
c-=2;
|
|
unicode=true;
|
|
}
|
|
else if (BOM == 0xFFFE)
|
|
{
|
|
pos+=2;
|
|
c-=2;
|
|
unicode=true;
|
|
utf16BE=true;
|
|
}
|
|
}
|
|
|
|
CHECK_BIN(len, c);
|
|
if (unicode)
|
|
{
|
|
ndestring_release(String);
|
|
if (utf16BE)
|
|
{
|
|
size_t bytes = utf16BE_to_utf8((uint16_t *)(data+pos), c>>1, 0, 0);
|
|
String = ndestring_malloc(bytes+1);
|
|
utf16BE_to_utf8((uint16_t *)(data+pos), c>>1, String, bytes);
|
|
String[bytes]=0;
|
|
}
|
|
else
|
|
{
|
|
size_t bytes = utf16LE_to_utf8((uint16_t *)(data+pos), c>>1, 0, 0);
|
|
String = ndestring_malloc(bytes+1);
|
|
utf16LE_to_utf8((uint16_t *)(data+pos), c>>1, String, bytes);
|
|
String[bytes]=0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// TODO: check for utf-8 byte marker
|
|
String = ndestring_malloc(c+1);
|
|
GET_BINARY((uint8_t *)String, data, c, pos);
|
|
String[c]=0;
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void StringField::WriteTypedData(uint8_t *data, size_t len)
|
|
{
|
|
int pos=0;
|
|
|
|
if (String)
|
|
{
|
|
unsigned short c = (unsigned short)strlen(String);
|
|
// write size
|
|
CHECK_SHORT(len);
|
|
PUT_SHORT(c); pos+=2;
|
|
|
|
// write string
|
|
CHECK_BIN(len, c);
|
|
PUT_BINARY(data, (uint8_t *)String, c, pos);
|
|
}
|
|
else
|
|
{
|
|
CHECK_SHORT(len);
|
|
PUT_SHORT(0); pos+=2;
|
|
}
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
char *StringField::GetString(void)
|
|
{
|
|
return String;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void StringField::SetString(const char *Str)
|
|
{
|
|
if (!Str) return;
|
|
|
|
ndestring_release(String);
|
|
String = NULL;
|
|
String = ndestring_wcsdup(Str);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void StringField::SetNDEString(char *Str)
|
|
{
|
|
if (!Str) return;
|
|
|
|
// copy and then release, just in case we're copying into ourselves
|
|
char *oldStr = String;
|
|
String = Str;
|
|
ndestring_retain(String);
|
|
ndestring_release(oldStr);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
size_t StringField::GetDataSize(void)
|
|
{
|
|
if (String)
|
|
{
|
|
return strlen(String) + 2;
|
|
}
|
|
else
|
|
{
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
int StringField::Compare(Field *Entry)
|
|
{
|
|
if (!Entry) return -1;
|
|
if (Entry->GetType() != GetType()) return 0;
|
|
return mystricmp(GetString(), ((StringField*)Entry)->GetString());
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
int StringField::Starts(Field *Entry)
|
|
{
|
|
if (!Entry) return -1;
|
|
if (Entry->GetType() != GetType()) return 0;
|
|
return (mystristr(GetString(), ((StringField*)Entry)->GetString()) == GetString());
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
int StringField::Contains(Field *Entry)
|
|
{
|
|
if (!Entry) return -1;
|
|
if (Entry->GetType() != GetType()) return 0;
|
|
return (mystristr(GetString(), ((StringField*)Entry)->GetString()) != NULL);
|
|
}
|
|
|
|
Field *StringField::Clone(Table *pTable)
|
|
{
|
|
StringField *clone = new StringField(String, STRING_IS_NDESTRING);
|
|
clone->Pos = FIELD_CLONE;
|
|
clone->ID = ID;
|
|
clone->MaxSizeOnDisk = GetDataSize();
|
|
return clone;
|
|
}
|
|
|
|
bool StringField::ApplyFilter(Field *Data, int op)
|
|
{
|
|
// TODO: maybe do this?
|
|
|
|
if (op == FILTER_ISEMPTY || op == FILTER_ISNOTEMPTY)
|
|
{
|
|
bool r = (op == FILTER_ISEMPTY);
|
|
if (!String)
|
|
return r;
|
|
|
|
if (String && String[0] == 0)
|
|
return r;
|
|
|
|
return !r;
|
|
}
|
|
//
|
|
bool r;
|
|
StringField *compField = (StringField *)Data;
|
|
|
|
const char *p = compField->GetString();
|
|
const char *d = GetString();
|
|
if (!p)
|
|
p = "";
|
|
if (!d)
|
|
d = "";
|
|
|
|
switch (op)
|
|
{
|
|
case FILTER_EQUALS:
|
|
r = !nde_stricmp(d, p);
|
|
break;
|
|
case FILTER_NOTEQUALS:
|
|
r = !!nde_stricmp(d, p);
|
|
break;
|
|
case FILTER_CONTAINS:
|
|
r = (NULL != stristr_ignore(d, p));
|
|
break;
|
|
case FILTER_NOTCONTAINS:
|
|
r = (NULL == stristr_ignore(d, p));
|
|
break;
|
|
case FILTER_ABOVE:
|
|
r = (bool)(nde_stricmp(d, p) > 0);
|
|
break;
|
|
case FILTER_ABOVEOREQUAL:
|
|
r = (bool)(nde_stricmp(d, p) >= 0);
|
|
break;
|
|
case FILTER_BELOW:
|
|
r = (bool)(nde_stricmp(d, p) < 0);
|
|
break;
|
|
case FILTER_BELOWOREQUAL:
|
|
r = (bool)(nde_stricmp(d, p) <= 0);
|
|
break;
|
|
case FILTER_BEGINS:
|
|
r = (bool)(nde_strnicmp(d, p, strlen(p)) == 0);
|
|
break;
|
|
case FILTER_ENDS:
|
|
{
|
|
size_t lenp = strlen(p), lend = strlen(d);
|
|
if (lend < lenp) return 0; // too short
|
|
r = (bool)(nde_stricmp((d + lend) - lenp, p) == 0);
|
|
}
|
|
break;
|
|
case FILTER_LIKE:
|
|
r = (bool)(nde_stricmp(d, p) == 0);
|
|
break;
|
|
case FILTER_BEGINSLIKE:
|
|
r = (bool)(nde_strnicmp_ignore(d, p, strlen(p)) == 0);
|
|
break;
|
|
default:
|
|
r = true;
|
|
break;
|
|
}
|
|
return r;
|
|
}
|
|
|