aboutsummaryrefslogtreecommitdiff
path: root/Src/nde/android/StringField.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/nde/android/StringField.cpp')
-rw-r--r--Src/nde/android/StringField.cpp292
1 files changed, 292 insertions, 0 deletions
diff --git a/Src/nde/android/StringField.cpp b/Src/nde/android/StringField.cpp
new file mode 100644
index 00000000..dd5c7101
--- /dev/null
+++ b/Src/nde/android/StringField.cpp
@@ -0,0 +1,292 @@
+/* ---------------------------------------------------------------------------
+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;
+}
+