123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573 |
- /* ---------------------------------------------------------------------------
- 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
|