aboutsummaryrefslogtreecommitdiff
path: root/Src/nde/DBUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/nde/DBUtils.cpp')
-rw-r--r--Src/nde/DBUtils.cpp573
1 files changed, 573 insertions, 0 deletions
diff --git a/Src/nde/DBUtils.cpp b/Src/nde/DBUtils.cpp
new file mode 100644
index 00000000..93958a2c
--- /dev/null
+++ b/Src/nde/DBUtils.cpp
@@ -0,0 +1,573 @@
+/* ---------------------------------------------------------------------------
+ Nullsoft Database Engine
+ --------------------
+ codename: Near Death Experience
+--------------------------------------------------------------------------- */
+
+/* ---------------------------------------------------------------------------
+
+ All Purposes Functions
+
+--------------------------------------------------------------------------- */
+
+#include "nde.h"
+#include "BinaryField.h"
+#include "Binary32Field.h"
+#include "vfs.h"
+#include "ColumnField.h"
+#include "IndexField.h"
+#include "StringField.h"
+#include "FilenameField.h"
+#include "IntegerField.h"
+#include "Int64Field.h"
+#include "Int128Field.h"
+#include <stdio.h>
+#include <string.h>
+
+#ifdef _WIN32
+int (WINAPI *findNLSString)(LCID Locale, DWORD dwFindNLSStringFlags, LPCWSTR lpStringSource, int cchSource, LPCWSTR lpStringValue, int cchValue, LPINT pcchFound) = NDE_FindNLSString;
+#endif
+
+//---------------------------------------------------------------------------
+bool CompatibleFields(unsigned char oldType, unsigned char newType)
+{
+ if (oldType == newType) // duh :)
+ return true;
+ // going from an int field to another int equivalent field is OK
+ if ((oldType == FIELD_INTEGER || oldType == FIELD_BOOLEAN || oldType == FIELD_DATETIME || oldType == FIELD_LENGTH || oldType == FIELD_INT64) &&
+ (newType == FIELD_INTEGER || newType == FIELD_BOOLEAN || newType == FIELD_DATETIME || newType == FIELD_LENGTH || newType == FIELD_INT64)) {
+ return true;
+ }
+
+ // going from string to filename or filename to string is OK
+ if ((oldType == FIELD_FILENAME && newType == FIELD_STRING)
+ || (oldType == FIELD_STRING && newType == FIELD_FILENAME))
+ {
+ return true;
+ }
+ return false;
+}
+
+//---------------------------------------------------------------------------
+uint32_t AllocNewPos(VFILE *Handle)
+{
+ Vfseek(Handle, 0, SEEK_END);
+ return Vftell(Handle);
+}
+
+//---------------------------------------------------------------------------
+Field *TranslateObject(unsigned char Type, Table *tbl)
+{
+ switch (Type)
+ {
+ case FIELD_COLUMN: //0
+ return new ColumnField();
+ case FIELD_INDEX: //1
+ return new IndexField();
+ case FIELD_STRING: // 3
+ return new StringField();
+ case FIELD_INTEGER: // 4
+ return new IntegerField();
+ case FIELD_BINARY: // 6
+ return new BinaryField();
+ case FIELD_DATETIME: // 10
+ return new DateTimeField();
+ case FIELD_LENGTH: // 11
+ return new LengthField();
+ case FIELD_FILENAME: // 12
+ return new FilenameField();
+ case FIELD_INT64: // 13
+ return new Int64Field();
+ case FIELD_BINARY32: // 14
+ return new Binary32Field();
+ case FIELD_INT128: // 15
+ return new Int128Field();
+ default:
+#ifdef WIN32
+ if (!tbl->HasErrors())
+ {
+ //MessageBox(plugin.hwndParent, "Your database has been corrupted!\n\nWinamp will try to continue, but some of the library metadata may be lost :(", "Database Error", 0);
+ }
+#else
+ printf("NDE Error: unknown field type encountered\n");
+#endif
+ tbl->IncErrorCount();
+ return new Field();
+ }
+}
+
+
+//---------------------------------------------------------------------------
+#ifndef __ANDROID__
+const void *memmem(const void *a, const void *b, size_t s, size_t l)
+{
+ size_t n = s - l;
+ while (n--)
+ {
+ if (!memcmp(a, b, l))
+ return a;
+ a = (const uint8_t *)a + 1;
+ }
+ return NULL;
+}
+#endif
+
+#ifdef _WIN32
+// a faster way of doing min(wcslen(str), _len)
+static size_t nde_wcsnlen(const wchar_t *str, size_t _len)
+{
+ size_t len = 0;
+ while (str && *str++)
+ {
+ if (_len == len)
+ return len;
+ len++;
+ }
+ return len;
+}
+
+// len must be <= wcslen(b)
+static int nde_wcsnicmp(const wchar_t *a, const wchar_t *b, size_t len)
+{
+ return CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, a, (int)nde_wcsnlen(a, len), b, (int)len) - 2;
+}
+
+/* this is a VERY LIMITED emulation of the vista only function. it ONLY supports the ways we're currently call it. it's also slow. */
+int WINAPI NDE_FindNLSString(LCID Locale, DWORD dwFindNLSStringFlags, LPCWSTR lpStringSource, int cchSource, LPCWSTR lpStringValue, int cchValue, LPINT pcchFound)
+{
+ dwFindNLSStringFlags &= ~NORM_LINGUISTIC_CASING; // remove on XP and below, not supported
+ if (dwFindNLSStringFlags & FIND_STARTSWITH)
+ {
+ dwFindNLSStringFlags &= ~FIND_STARTSWITH; // clear flag
+ size_t len = wcslen(lpStringValue);
+ if (CompareStringW(Locale, dwFindNLSStringFlags, lpStringSource, (int)nde_wcsnlen(lpStringSource, len), lpStringValue, (int)len) == CSTR_EQUAL)
+ return 0;
+ else
+ return -1;
+ }
+ else if (dwFindNLSStringFlags & FIND_ENDSWITH)
+ {
+ dwFindNLSStringFlags &= ~FIND_ENDSWITH; // clear flag
+ int lenp = (int)wcslen(lpStringValue), lend = (int)wcslen(lpStringSource);
+ if (lend < lenp) return -1; // too short
+ if (CompareStringW(Locale, dwFindNLSStringFlags, lpStringSource+lend-lenp, -1, lpStringValue, -1) == CSTR_EQUAL)
+ return 0;
+ else
+ return -1;
+ }
+ else if (dwFindNLSStringFlags & FIND_FROMSTART)
+ {
+ dwFindNLSStringFlags &= ~FIND_FROMSTART; // clear flag
+ int s2len = (int)wcslen(lpStringValue);
+ int s1len = (int)wcslen(lpStringSource);
+ const wchar_t *p;
+ for (p = lpStringSource;*p && s1len >= s2len;p++,s1len--)
+ if (CompareStringW(Locale, dwFindNLSStringFlags, p, min(s1len, s2len), lpStringValue, (int)s2len) == CSTR_EQUAL)
+ return 0;
+ return -1;
+ }
+
+ return -1;
+}
+
+int nde_wcsicmp(const wchar_t *a, const wchar_t *b)
+{
+ return CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE|NORM_IGNORENONSPACE, a, -1, b, -1) - 2;
+}
+
+bool nde_wcsbegins(const wchar_t *a, const wchar_t *b)
+{
+ int index = findNLSString(LOCALE_USER_DEFAULT, FIND_STARTSWITH|NORM_LINGUISTIC_CASING|NORM_IGNORECASE|NORM_IGNORENONSPACE, a, -1, b, -1, 0);
+ return (index != -1);
+}
+
+bool nde_wcsends(const wchar_t *a, const wchar_t *b)
+{
+ int index = findNLSString(LOCALE_USER_DEFAULT, FIND_ENDSWITH|NORM_LINGUISTIC_CASING|NORM_IGNORECASE|NORM_IGNORENONSPACE, a, -1, b, -1, 0);
+ return (index != -1);
+}
+
+bool nde_wcscontains(const wchar_t *a, const wchar_t *b)
+{
+ int index = findNLSString(LOCALE_USER_DEFAULT, FIND_FROMSTART|NORM_LINGUISTIC_CASING|NORM_IGNORECASE|NORM_IGNORENONSPACE, a, -1, b, -1, 0);
+ return index != -1;
+}
+
+//---------------------------------------------------------------------------
+
+int mywcsicmp(const wchar_t *a, const wchar_t *b)
+{
+ if (!a && !b) return 0;
+ if (!a && b) return 1;
+ if (!b) return -1;
+ int r = nde_wcsicmp(a, b);
+ return min(max(r, -1), 1);
+}
+
+int mywcsicmp_fn(const wchar_t *a, const wchar_t *b)
+{
+ if (!a && !b) return 0;
+ if (!a && b) return 1;
+ if (!b) return -1;
+ int r = nde_wcsicmp_fn(a, b);
+ return min(max(r, -1), 1);
+}
+
+int nde_wcsicmp_fn(const wchar_t *a, const wchar_t *b)
+{
+ return CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, a, -1, b, -1) - 2;
+}
+
+bool nde_fnbegins(const wchar_t *a, const wchar_t *b)
+{
+ int index = findNLSString(LOCALE_USER_DEFAULT, FIND_STARTSWITH|NORM_IGNORECASE, a, -1, b, -1, 0);
+ return (index != -1);
+}
+
+bool nde_fnends(const wchar_t *a, const wchar_t *b)
+{
+ int index = findNLSString(LOCALE_USER_DEFAULT, FIND_ENDSWITH|NORM_IGNORECASE, a, -1, b, -1, 0);
+ return (index != -1);
+}
+
+bool nde_fncontains(const wchar_t *a, const wchar_t *b)
+{
+ int index = findNLSString(LOCALE_USER_DEFAULT, FIND_FROMSTART|NORM_IGNORECASE, a, -1, b, -1, 0);
+ return index != -1;
+}
+
+#endif
+
+#ifdef __ANDROID__
+
+//---------------------------------------------------------------------------
+// a faster way of doing min(wcslen(str), _len)
+size_t nde_strnlen(const char *str, size_t _len)
+{
+ size_t len = 0;
+ while (str && *str++)
+ {
+ if (_len == len)
+ return len;
+ len++;
+ }
+ return len;
+}
+
+// len must be <= strlen(b)
+int nde_strnicmp(const char *a, const char *b, size_t len)
+{
+ return strncasecmp(a,b,len);
+}
+
+int nde_strnicmp_ignore(const char *a, const char *b, size_t len)
+{
+ return strncasecmp(a,b,len);
+}
+
+char *stristr(const char *s1, const char *s2)
+{
+ size_t s2len = strlen(s2);
+ const char *p;
+ for (p = s1;*p;p++)
+ if (!nde_strnicmp(p, s2, s2len))
+ return (char *)p;
+ return NULL;
+}
+
+char *stristr_ignore(const char *s1, const char *s2)
+{
+ size_t s2len = strlen(s2);
+ const char *p;
+ for (p = s1;*p;p++)
+ if (!nde_strnicmp_ignore(p, s2, s2len))
+ return (char *)p;
+ return NULL;
+}
+
+//---------------------------------------------------------------------------
+
+int nde_stricmp(const char *a, const char *b)
+{
+ return strcasecmp(a,b);
+}
+
+int nde_stricmp_ignore(const char *a, const char *b)
+{
+ return strcasecmp(a,b); // TODO: maybe strcoll?
+}
+
+int mystricmp(const char *a, const char *b)
+{
+ if (!a && !b) return 0;
+ if (!a && b) return 1;
+ if (!b) return -1;
+ int r = nde_stricmp(a, b);
+ return min(max(r, -1), 1);
+}
+
+char* mystristr(const char *a, const char *b)
+{
+ return (!a || !b) ? NULL : stristr(a, b);
+}
+
+char* mystristr_fn(const char *a, const char *b)
+{
+ return (!a || !b) ? NULL : stristr_fn(a, b);
+}
+
+int mystricmp_fn(const char *a, const char *b)
+{
+ if (!a && !b) return 0;
+ if (!a && b) return 1;
+ if (!b) return -1;
+ int r = nde_stricmp_fn(a, b);
+ return min(max(r, -1), 1);
+}
+
+char *stristr_fn(const char *s1, const char *s2)
+{
+ size_t s2len = strlen(s2);
+ const char *p;
+ for (p = s1;*p;p++)
+ if (!nde_strnicmp_fn(p, s2, s2len))
+ return (char *)p;
+ return NULL;
+}
+
+int nde_stricmp_fn(const char *a, const char *b)
+{
+ return strcasecmp(a,b);
+}
+
+int nde_strnicmp_fn(const char *a, const char *b, size_t len)
+{
+ return strncasecmp(a,b, len);
+
+}
+
+static uint16_t swap_utf16LE(uint16_t value)
+{
+#ifdef BIG_ENDIAN
+ return (value >> 8) | (value << 8);
+#else
+ return value;
+#endif
+}
+
+static uint16_t swap_utf16BE(uint16_t value)
+{
+#ifdef LITTLE_ENDIAN
+ return (value >> 8) | (value << 8);
+#else
+ return value;
+#endif
+}
+
+static size_t utf16LE_to_ucs4_character(const uint16_t *utf16_string, size_t len, uint32_t *codepoint)
+{
+ uint16_t lead = swap_utf16LE(utf16_string[0]);
+ if (lead < 0xD800 || lead >= 0xE000)
+ {
+ return lead;
+ }
+
+ if (lead < 0xDC00)
+ {
+ if (len >= 2)
+ {
+ uint16_t trail = swap_utf16LE(utf16_string[1]);
+ if (trail >= 0xDC00 && trail < 0xE000)
+ {
+ *codepoint = 0x10000 + ((lead - 0xD800) << 10) + (trail - 0xDC00);
+ return 2;
+ }
+ }
+ }
+
+ *codepoint=0xFFFD; // invalid
+ return 1;
+}
+
+static size_t utf16BE_to_ucs4_character(const uint16_t *utf16_string, size_t len, uint32_t *codepoint)
+{
+ uint16_t lead = swap_utf16LE(utf16_string[0]);
+ if (lead < 0xD800 || lead >= 0xE000)
+ {
+ return lead;
+ }
+
+ if (lead < 0xDC00)
+ {
+ if (len >= 2)
+ {
+ uint16_t trail = swap_utf16LE(utf16_string[1]);
+ if (trail >= 0xDC00 && trail < 0xE000)
+ {
+ *codepoint = 0x10000 + ((lead - 0xD800) << 10) + (trail - 0xDC00);
+ return 2;
+ }
+ }
+ }
+
+ *codepoint=0xFFFD; // invalid
+ return 1;
+}
+
+static size_t ucs4count(uint32_t codepoint)
+{
+ if (codepoint < 0x80)
+ return 1;
+ else if (codepoint < 0x800)
+ return 2;
+ else if (codepoint < 0x10000)
+ return 3;
+ else if (codepoint < 0x200000)
+ return 4;
+ else if (codepoint < 0x4000000)
+ return 5;
+ else if (codepoint <= 0x7FFFFFFF)
+ return 6;
+ else
+ return 0;
+}
+
+static size_t ucs4_to_utf8_character(char *target, uint32_t codepoint, size_t max)
+{
+ size_t count = ucs4count(codepoint);
+
+ if (!count)
+ return 0;
+
+ if (count>max) return 0;
+
+ if (target == 0)
+ return count;
+
+ switch (count)
+ {
+ case 6:
+ target[5] = 0x80 | (codepoint & 0x3F);
+ codepoint = codepoint >> 6;
+ codepoint |= 0x4000000;
+ case 5:
+ target[4] = 0x80 | (codepoint & 0x3F);
+ codepoint = codepoint >> 6;
+ codepoint |= 0x200000;
+ case 4:
+ target[3] = 0x80 | (codepoint & 0x3F);
+ codepoint = codepoint >> 6;
+ codepoint |= 0x10000;
+ case 3:
+ target[2] = 0x80 | (codepoint & 0x3F);
+ codepoint = codepoint >> 6;
+ codepoint |= 0x800;
+ case 2:
+ target[1] = 0x80 | (codepoint & 0x3F);
+ codepoint = codepoint >> 6;
+ codepoint |= 0xC0;
+ case 1:
+ target[0] = codepoint;
+ }
+
+ return count;
+}
+
+size_t utf16LE_to_utf8(const uint16_t *src, size_t source_len, char *dst, size_t out_len)
+{
+ uint32_t codepoint=0xFFFD;
+ size_t position=0;
+ size_t characters_processed=0;
+
+ if (!dst) // they just want the size
+ {
+ while (source_len)
+ {
+ characters_processed = utf16LE_to_ucs4_character(src, source_len, &codepoint);
+ if (codepoint == 0xFFFD)
+ break;
+
+ if (!codepoint)
+ break;
+
+ source_len -= characters_processed;
+
+ characters_processed = ucs4count(codepoint);
+ if (!characters_processed)
+ break;
+
+ position+=characters_processed;
+ }
+ return position;
+ }
+
+ while(source_len && position<out_len)
+ {
+ characters_processed = utf16LE_to_ucs4_character(src, source_len, &codepoint);
+ if (codepoint == 0xFFFD)
+ break;
+
+ if (!codepoint)
+ break;
+
+ source_len -= characters_processed;
+
+ characters_processed=ucs4_to_utf8_character(&dst[position], codepoint, out_len-position);
+ if (!characters_processed)
+ break;
+ position+=characters_processed;
+ }
+ if (position<out_len)
+ dst[position]=0;
+ return position;
+}
+
+size_t utf16BE_to_utf8(const uint16_t *src, size_t source_len, char *dst, size_t out_len)
+{
+ uint32_t codepoint=0xFFFD;
+ size_t position=0;
+ size_t characters_processed=0;
+
+ if (!dst) // they just want the size
+ {
+ while (source_len)
+ {
+ characters_processed = utf16BE_to_ucs4_character(src, source_len, &codepoint);
+ if (codepoint == 0xFFFD)
+ break;
+
+ if (!codepoint)
+ break;
+
+ source_len -= characters_processed;
+
+ characters_processed = ucs4count(codepoint);
+ if (!characters_processed)
+ break;
+
+ position+=characters_processed;
+ }
+ return position;
+ }
+
+ while(source_len && position<out_len)
+ {
+ characters_processed = utf16BE_to_ucs4_character(src, source_len, &codepoint);
+ if (codepoint == 0xFFFD)
+ break;
+
+ if (!codepoint)
+ break;
+
+ source_len -= characters_processed;
+
+ characters_processed=ucs4_to_utf8_character(&dst[position], codepoint, out_len-position);
+ if (!characters_processed)
+ break;
+ position+=characters_processed;
+ }
+ if (position<out_len)
+ dst[position]=0;
+ return position;
+}
+#endif \ No newline at end of file