diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/nde/DBUtils.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/nde/DBUtils.cpp')
-rw-r--r-- | Src/nde/DBUtils.cpp | 573 |
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 |