DBUtils.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. /* ---------------------------------------------------------------------------
  2. Nullsoft Database Engine
  3. --------------------
  4. codename: Near Death Experience
  5. --------------------------------------------------------------------------- */
  6. /* ---------------------------------------------------------------------------
  7. All Purposes Functions
  8. --------------------------------------------------------------------------- */
  9. #include "nde.h"
  10. #include "BinaryField.h"
  11. #include "Binary32Field.h"
  12. #include "vfs.h"
  13. #include "ColumnField.h"
  14. #include "IndexField.h"
  15. #include "StringField.h"
  16. #include "FilenameField.h"
  17. #include "IntegerField.h"
  18. #include "Int64Field.h"
  19. #include "Int128Field.h"
  20. #include <stdio.h>
  21. #include <string.h>
  22. #ifdef _WIN32
  23. int (WINAPI *findNLSString)(LCID Locale, DWORD dwFindNLSStringFlags, LPCWSTR lpStringSource, int cchSource, LPCWSTR lpStringValue, int cchValue, LPINT pcchFound) = NDE_FindNLSString;
  24. #endif
  25. //---------------------------------------------------------------------------
  26. bool CompatibleFields(unsigned char oldType, unsigned char newType)
  27. {
  28. if (oldType == newType) // duh :)
  29. return true;
  30. // going from an int field to another int equivalent field is OK
  31. if ((oldType == FIELD_INTEGER || oldType == FIELD_BOOLEAN || oldType == FIELD_DATETIME || oldType == FIELD_LENGTH || oldType == FIELD_INT64) &&
  32. (newType == FIELD_INTEGER || newType == FIELD_BOOLEAN || newType == FIELD_DATETIME || newType == FIELD_LENGTH || newType == FIELD_INT64)) {
  33. return true;
  34. }
  35. // going from string to filename or filename to string is OK
  36. if ((oldType == FIELD_FILENAME && newType == FIELD_STRING)
  37. || (oldType == FIELD_STRING && newType == FIELD_FILENAME))
  38. {
  39. return true;
  40. }
  41. return false;
  42. }
  43. //---------------------------------------------------------------------------
  44. uint32_t AllocNewPos(VFILE *Handle)
  45. {
  46. Vfseek(Handle, 0, SEEK_END);
  47. return Vftell(Handle);
  48. }
  49. //---------------------------------------------------------------------------
  50. Field *TranslateObject(unsigned char Type, Table *tbl)
  51. {
  52. switch (Type)
  53. {
  54. case FIELD_COLUMN: //0
  55. return new ColumnField();
  56. case FIELD_INDEX: //1
  57. return new IndexField();
  58. case FIELD_STRING: // 3
  59. return new StringField();
  60. case FIELD_INTEGER: // 4
  61. return new IntegerField();
  62. case FIELD_BINARY: // 6
  63. return new BinaryField();
  64. case FIELD_DATETIME: // 10
  65. return new DateTimeField();
  66. case FIELD_LENGTH: // 11
  67. return new LengthField();
  68. case FIELD_FILENAME: // 12
  69. return new FilenameField();
  70. case FIELD_INT64: // 13
  71. return new Int64Field();
  72. case FIELD_BINARY32: // 14
  73. return new Binary32Field();
  74. case FIELD_INT128: // 15
  75. return new Int128Field();
  76. default:
  77. #ifdef WIN32
  78. if (!tbl->HasErrors())
  79. {
  80. //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);
  81. }
  82. #else
  83. printf("NDE Error: unknown field type encountered\n");
  84. #endif
  85. tbl->IncErrorCount();
  86. return new Field();
  87. }
  88. }
  89. //---------------------------------------------------------------------------
  90. #ifndef __ANDROID__
  91. const void *memmem(const void *a, const void *b, size_t s, size_t l)
  92. {
  93. size_t n = s - l;
  94. while (n--)
  95. {
  96. if (!memcmp(a, b, l))
  97. return a;
  98. a = (const uint8_t *)a + 1;
  99. }
  100. return NULL;
  101. }
  102. #endif
  103. #ifdef _WIN32
  104. // a faster way of doing min(wcslen(str), _len)
  105. static size_t nde_wcsnlen(const wchar_t *str, size_t _len)
  106. {
  107. size_t len = 0;
  108. while (str && *str++)
  109. {
  110. if (_len == len)
  111. return len;
  112. len++;
  113. }
  114. return len;
  115. }
  116. // len must be <= wcslen(b)
  117. static int nde_wcsnicmp(const wchar_t *a, const wchar_t *b, size_t len)
  118. {
  119. return CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, a, (int)nde_wcsnlen(a, len), b, (int)len) - 2;
  120. }
  121. /* 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. */
  122. int WINAPI NDE_FindNLSString(LCID Locale, DWORD dwFindNLSStringFlags, LPCWSTR lpStringSource, int cchSource, LPCWSTR lpStringValue, int cchValue, LPINT pcchFound)
  123. {
  124. dwFindNLSStringFlags &= ~NORM_LINGUISTIC_CASING; // remove on XP and below, not supported
  125. if (dwFindNLSStringFlags & FIND_STARTSWITH)
  126. {
  127. dwFindNLSStringFlags &= ~FIND_STARTSWITH; // clear flag
  128. size_t len = wcslen(lpStringValue);
  129. if (CompareStringW(Locale, dwFindNLSStringFlags, lpStringSource, (int)nde_wcsnlen(lpStringSource, len), lpStringValue, (int)len) == CSTR_EQUAL)
  130. return 0;
  131. else
  132. return -1;
  133. }
  134. else if (dwFindNLSStringFlags & FIND_ENDSWITH)
  135. {
  136. dwFindNLSStringFlags &= ~FIND_ENDSWITH; // clear flag
  137. int lenp = (int)wcslen(lpStringValue), lend = (int)wcslen(lpStringSource);
  138. if (lend < lenp) return -1; // too short
  139. if (CompareStringW(Locale, dwFindNLSStringFlags, lpStringSource+lend-lenp, -1, lpStringValue, -1) == CSTR_EQUAL)
  140. return 0;
  141. else
  142. return -1;
  143. }
  144. else if (dwFindNLSStringFlags & FIND_FROMSTART)
  145. {
  146. dwFindNLSStringFlags &= ~FIND_FROMSTART; // clear flag
  147. int s2len = (int)wcslen(lpStringValue);
  148. int s1len = (int)wcslen(lpStringSource);
  149. const wchar_t *p;
  150. for (p = lpStringSource;*p && s1len >= s2len;p++,s1len--)
  151. if (CompareStringW(Locale, dwFindNLSStringFlags, p, min(s1len, s2len), lpStringValue, (int)s2len) == CSTR_EQUAL)
  152. return 0;
  153. return -1;
  154. }
  155. return -1;
  156. }
  157. int nde_wcsicmp(const wchar_t *a, const wchar_t *b)
  158. {
  159. return CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE|NORM_IGNORENONSPACE, a, -1, b, -1) - 2;
  160. }
  161. bool nde_wcsbegins(const wchar_t *a, const wchar_t *b)
  162. {
  163. int index = findNLSString(LOCALE_USER_DEFAULT, FIND_STARTSWITH|NORM_LINGUISTIC_CASING|NORM_IGNORECASE|NORM_IGNORENONSPACE, a, -1, b, -1, 0);
  164. return (index != -1);
  165. }
  166. bool nde_wcsends(const wchar_t *a, const wchar_t *b)
  167. {
  168. int index = findNLSString(LOCALE_USER_DEFAULT, FIND_ENDSWITH|NORM_LINGUISTIC_CASING|NORM_IGNORECASE|NORM_IGNORENONSPACE, a, -1, b, -1, 0);
  169. return (index != -1);
  170. }
  171. bool nde_wcscontains(const wchar_t *a, const wchar_t *b)
  172. {
  173. int index = findNLSString(LOCALE_USER_DEFAULT, FIND_FROMSTART|NORM_LINGUISTIC_CASING|NORM_IGNORECASE|NORM_IGNORENONSPACE, a, -1, b, -1, 0);
  174. return index != -1;
  175. }
  176. //---------------------------------------------------------------------------
  177. int mywcsicmp(const wchar_t *a, const wchar_t *b)
  178. {
  179. if (!a && !b) return 0;
  180. if (!a && b) return 1;
  181. if (!b) return -1;
  182. int r = nde_wcsicmp(a, b);
  183. return min(max(r, -1), 1);
  184. }
  185. int mywcsicmp_fn(const wchar_t *a, const wchar_t *b)
  186. {
  187. if (!a && !b) return 0;
  188. if (!a && b) return 1;
  189. if (!b) return -1;
  190. int r = nde_wcsicmp_fn(a, b);
  191. return min(max(r, -1), 1);
  192. }
  193. int nde_wcsicmp_fn(const wchar_t *a, const wchar_t *b)
  194. {
  195. return CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, a, -1, b, -1) - 2;
  196. }
  197. bool nde_fnbegins(const wchar_t *a, const wchar_t *b)
  198. {
  199. int index = findNLSString(LOCALE_USER_DEFAULT, FIND_STARTSWITH|NORM_IGNORECASE, a, -1, b, -1, 0);
  200. return (index != -1);
  201. }
  202. bool nde_fnends(const wchar_t *a, const wchar_t *b)
  203. {
  204. int index = findNLSString(LOCALE_USER_DEFAULT, FIND_ENDSWITH|NORM_IGNORECASE, a, -1, b, -1, 0);
  205. return (index != -1);
  206. }
  207. bool nde_fncontains(const wchar_t *a, const wchar_t *b)
  208. {
  209. int index = findNLSString(LOCALE_USER_DEFAULT, FIND_FROMSTART|NORM_IGNORECASE, a, -1, b, -1, 0);
  210. return index != -1;
  211. }
  212. #endif
  213. #ifdef __ANDROID__
  214. //---------------------------------------------------------------------------
  215. // a faster way of doing min(wcslen(str), _len)
  216. size_t nde_strnlen(const char *str, size_t _len)
  217. {
  218. size_t len = 0;
  219. while (str && *str++)
  220. {
  221. if (_len == len)
  222. return len;
  223. len++;
  224. }
  225. return len;
  226. }
  227. // len must be <= strlen(b)
  228. int nde_strnicmp(const char *a, const char *b, size_t len)
  229. {
  230. return strncasecmp(a,b,len);
  231. }
  232. int nde_strnicmp_ignore(const char *a, const char *b, size_t len)
  233. {
  234. return strncasecmp(a,b,len);
  235. }
  236. char *stristr(const char *s1, const char *s2)
  237. {
  238. size_t s2len = strlen(s2);
  239. const char *p;
  240. for (p = s1;*p;p++)
  241. if (!nde_strnicmp(p, s2, s2len))
  242. return (char *)p;
  243. return NULL;
  244. }
  245. char *stristr_ignore(const char *s1, const char *s2)
  246. {
  247. size_t s2len = strlen(s2);
  248. const char *p;
  249. for (p = s1;*p;p++)
  250. if (!nde_strnicmp_ignore(p, s2, s2len))
  251. return (char *)p;
  252. return NULL;
  253. }
  254. //---------------------------------------------------------------------------
  255. int nde_stricmp(const char *a, const char *b)
  256. {
  257. return strcasecmp(a,b);
  258. }
  259. int nde_stricmp_ignore(const char *a, const char *b)
  260. {
  261. return strcasecmp(a,b); // TODO: maybe strcoll?
  262. }
  263. int mystricmp(const char *a, const char *b)
  264. {
  265. if (!a && !b) return 0;
  266. if (!a && b) return 1;
  267. if (!b) return -1;
  268. int r = nde_stricmp(a, b);
  269. return min(max(r, -1), 1);
  270. }
  271. char* mystristr(const char *a, const char *b)
  272. {
  273. return (!a || !b) ? NULL : stristr(a, b);
  274. }
  275. char* mystristr_fn(const char *a, const char *b)
  276. {
  277. return (!a || !b) ? NULL : stristr_fn(a, b);
  278. }
  279. int mystricmp_fn(const char *a, const char *b)
  280. {
  281. if (!a && !b) return 0;
  282. if (!a && b) return 1;
  283. if (!b) return -1;
  284. int r = nde_stricmp_fn(a, b);
  285. return min(max(r, -1), 1);
  286. }
  287. char *stristr_fn(const char *s1, const char *s2)
  288. {
  289. size_t s2len = strlen(s2);
  290. const char *p;
  291. for (p = s1;*p;p++)
  292. if (!nde_strnicmp_fn(p, s2, s2len))
  293. return (char *)p;
  294. return NULL;
  295. }
  296. int nde_stricmp_fn(const char *a, const char *b)
  297. {
  298. return strcasecmp(a,b);
  299. }
  300. int nde_strnicmp_fn(const char *a, const char *b, size_t len)
  301. {
  302. return strncasecmp(a,b, len);
  303. }
  304. static uint16_t swap_utf16LE(uint16_t value)
  305. {
  306. #ifdef BIG_ENDIAN
  307. return (value >> 8) | (value << 8);
  308. #else
  309. return value;
  310. #endif
  311. }
  312. static uint16_t swap_utf16BE(uint16_t value)
  313. {
  314. #ifdef LITTLE_ENDIAN
  315. return (value >> 8) | (value << 8);
  316. #else
  317. return value;
  318. #endif
  319. }
  320. static size_t utf16LE_to_ucs4_character(const uint16_t *utf16_string, size_t len, uint32_t *codepoint)
  321. {
  322. uint16_t lead = swap_utf16LE(utf16_string[0]);
  323. if (lead < 0xD800 || lead >= 0xE000)
  324. {
  325. return lead;
  326. }
  327. if (lead < 0xDC00)
  328. {
  329. if (len >= 2)
  330. {
  331. uint16_t trail = swap_utf16LE(utf16_string[1]);
  332. if (trail >= 0xDC00 && trail < 0xE000)
  333. {
  334. *codepoint = 0x10000 + ((lead - 0xD800) << 10) + (trail - 0xDC00);
  335. return 2;
  336. }
  337. }
  338. }
  339. *codepoint=0xFFFD; // invalid
  340. return 1;
  341. }
  342. static size_t utf16BE_to_ucs4_character(const uint16_t *utf16_string, size_t len, uint32_t *codepoint)
  343. {
  344. uint16_t lead = swap_utf16LE(utf16_string[0]);
  345. if (lead < 0xD800 || lead >= 0xE000)
  346. {
  347. return lead;
  348. }
  349. if (lead < 0xDC00)
  350. {
  351. if (len >= 2)
  352. {
  353. uint16_t trail = swap_utf16LE(utf16_string[1]);
  354. if (trail >= 0xDC00 && trail < 0xE000)
  355. {
  356. *codepoint = 0x10000 + ((lead - 0xD800) << 10) + (trail - 0xDC00);
  357. return 2;
  358. }
  359. }
  360. }
  361. *codepoint=0xFFFD; // invalid
  362. return 1;
  363. }
  364. static size_t ucs4count(uint32_t codepoint)
  365. {
  366. if (codepoint < 0x80)
  367. return 1;
  368. else if (codepoint < 0x800)
  369. return 2;
  370. else if (codepoint < 0x10000)
  371. return 3;
  372. else if (codepoint < 0x200000)
  373. return 4;
  374. else if (codepoint < 0x4000000)
  375. return 5;
  376. else if (codepoint <= 0x7FFFFFFF)
  377. return 6;
  378. else
  379. return 0;
  380. }
  381. static size_t ucs4_to_utf8_character(char *target, uint32_t codepoint, size_t max)
  382. {
  383. size_t count = ucs4count(codepoint);
  384. if (!count)
  385. return 0;
  386. if (count>max) return 0;
  387. if (target == 0)
  388. return count;
  389. switch (count)
  390. {
  391. case 6:
  392. target[5] = 0x80 | (codepoint & 0x3F);
  393. codepoint = codepoint >> 6;
  394. codepoint |= 0x4000000;
  395. case 5:
  396. target[4] = 0x80 | (codepoint & 0x3F);
  397. codepoint = codepoint >> 6;
  398. codepoint |= 0x200000;
  399. case 4:
  400. target[3] = 0x80 | (codepoint & 0x3F);
  401. codepoint = codepoint >> 6;
  402. codepoint |= 0x10000;
  403. case 3:
  404. target[2] = 0x80 | (codepoint & 0x3F);
  405. codepoint = codepoint >> 6;
  406. codepoint |= 0x800;
  407. case 2:
  408. target[1] = 0x80 | (codepoint & 0x3F);
  409. codepoint = codepoint >> 6;
  410. codepoint |= 0xC0;
  411. case 1:
  412. target[0] = codepoint;
  413. }
  414. return count;
  415. }
  416. size_t utf16LE_to_utf8(const uint16_t *src, size_t source_len, char *dst, size_t out_len)
  417. {
  418. uint32_t codepoint=0xFFFD;
  419. size_t position=0;
  420. size_t characters_processed=0;
  421. if (!dst) // they just want the size
  422. {
  423. while (source_len)
  424. {
  425. characters_processed = utf16LE_to_ucs4_character(src, source_len, &codepoint);
  426. if (codepoint == 0xFFFD)
  427. break;
  428. if (!codepoint)
  429. break;
  430. source_len -= characters_processed;
  431. characters_processed = ucs4count(codepoint);
  432. if (!characters_processed)
  433. break;
  434. position+=characters_processed;
  435. }
  436. return position;
  437. }
  438. while(source_len && position<out_len)
  439. {
  440. characters_processed = utf16LE_to_ucs4_character(src, source_len, &codepoint);
  441. if (codepoint == 0xFFFD)
  442. break;
  443. if (!codepoint)
  444. break;
  445. source_len -= characters_processed;
  446. characters_processed=ucs4_to_utf8_character(&dst[position], codepoint, out_len-position);
  447. if (!characters_processed)
  448. break;
  449. position+=characters_processed;
  450. }
  451. if (position<out_len)
  452. dst[position]=0;
  453. return position;
  454. }
  455. size_t utf16BE_to_utf8(const uint16_t *src, size_t source_len, char *dst, size_t out_len)
  456. {
  457. uint32_t codepoint=0xFFFD;
  458. size_t position=0;
  459. size_t characters_processed=0;
  460. if (!dst) // they just want the size
  461. {
  462. while (source_len)
  463. {
  464. characters_processed = utf16BE_to_ucs4_character(src, source_len, &codepoint);
  465. if (codepoint == 0xFFFD)
  466. break;
  467. if (!codepoint)
  468. break;
  469. source_len -= characters_processed;
  470. characters_processed = ucs4count(codepoint);
  471. if (!characters_processed)
  472. break;
  473. position+=characters_processed;
  474. }
  475. return position;
  476. }
  477. while(source_len && position<out_len)
  478. {
  479. characters_processed = utf16BE_to_ucs4_character(src, source_len, &codepoint);
  480. if (codepoint == 0xFFFD)
  481. break;
  482. if (!codepoint)
  483. break;
  484. source_len -= characters_processed;
  485. characters_processed=ucs4_to_utf8_character(&dst[position], codepoint, out_len-position);
  486. if (!characters_processed)
  487. break;
  488. position+=characters_processed;
  489. }
  490. if (position<out_len)
  491. dst[position]=0;
  492. return position;
  493. }
  494. #endif