common.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. #if defined(GB_SYSTEM_UNIX)
  2. // Required for intrinsics on GCC
  3. #include <xmmintrin.h>
  4. #endif
  5. #if defined(GB_COMPILER_MSVC)
  6. #include <intrin.h>
  7. #endif
  8. #if defined(GB_SYSTEM_WINDOWS)
  9. #define NOMINMAX 1
  10. #include <windows.h>
  11. #undef NOMINMAX
  12. #endif
  13. #define GB_WINDOWS_H_INCLUDED
  14. #define GB_IMPLEMENTATION
  15. #include "gb/gb.h"
  16. #include <wchar.h>
  17. #include <stdio.h>
  18. #if defined(GB_COMPILER_MSVC)
  19. #include <psapi.h>
  20. #endif
  21. #include <math.h>
  22. #include <string.h>
  23. #include <atomic> // Because I wanted the C++11 memory order semantics, of which gb.h does not offer (because it was a C89 library)
  24. gbAllocator heap_allocator(void);
  25. #define for_array(index_, array_) for (isize index_ = 0; index_ < (array_).count; index_++)
  26. i32 next_pow2(i32 n);
  27. i64 next_pow2(i64 n);
  28. isize next_pow2_isize(isize n);
  29. void debugf(char const *fmt, ...);
  30. #include "threading.cpp"
  31. #include "unicode.cpp"
  32. #include "array.cpp"
  33. #include "queue.cpp"
  34. #include "common_memory.cpp"
  35. #include "string.cpp"
  36. #include "range_cache.cpp"
  37. int isize_cmp(isize x, isize y) {
  38. if (x < y) {
  39. return -1;
  40. } else if (x > y) {
  41. return +1;
  42. }
  43. return 0;
  44. }
  45. int u64_cmp(u64 x, u64 y) {
  46. if (x < y) {
  47. return -1;
  48. } else if (x > y) {
  49. return +1;
  50. }
  51. return 0;
  52. }
  53. int i64_cmp(i64 x, i64 y) {
  54. if (x < y) {
  55. return -1;
  56. } else if (x > y) {
  57. return +1;
  58. }
  59. return 0;
  60. }
  61. int i32_cmp(i32 x, i32 y) {
  62. if (x < y) {
  63. return -1;
  64. } else if (x > y) {
  65. return +1;
  66. }
  67. return 0;
  68. }
  69. u32 fnv32a(void const *data, isize len) {
  70. u8 const *bytes = cast(u8 const *)data;
  71. u32 h = 0x811c9dc5;
  72. for (; len >= 8; len -= 8, bytes += 8) {
  73. h = (h ^ bytes[0]) * 0x01000193;
  74. h = (h ^ bytes[1]) * 0x01000193;
  75. h = (h ^ bytes[2]) * 0x01000193;
  76. h = (h ^ bytes[3]) * 0x01000193;
  77. h = (h ^ bytes[4]) * 0x01000193;
  78. h = (h ^ bytes[5]) * 0x01000193;
  79. h = (h ^ bytes[6]) * 0x01000193;
  80. h = (h ^ bytes[7]) * 0x01000193;
  81. }
  82. while (len--) {
  83. h = (h ^ *bytes++) * 0x01000193;
  84. }
  85. return h;
  86. }
  87. u64 fnv64a(void const *data, isize len) {
  88. u8 const *bytes = cast(u8 const *)data;
  89. u64 h = 0xcbf29ce484222325ull;
  90. for (; len >= 8; len -= 8, bytes += 8) {
  91. h = (h ^ bytes[0]) * 0x100000001b3ull;
  92. h = (h ^ bytes[1]) * 0x100000001b3ull;
  93. h = (h ^ bytes[2]) * 0x100000001b3ull;
  94. h = (h ^ bytes[3]) * 0x100000001b3ull;
  95. h = (h ^ bytes[4]) * 0x100000001b3ull;
  96. h = (h ^ bytes[5]) * 0x100000001b3ull;
  97. h = (h ^ bytes[6]) * 0x100000001b3ull;
  98. h = (h ^ bytes[7]) * 0x100000001b3ull;
  99. }
  100. while (len--) {
  101. h = (h ^ *bytes++) * 0x100000001b3ull;
  102. }
  103. return h;
  104. }
  105. u64 u64_digit_value(Rune r) {
  106. switch (r) {
  107. case '0': return 0;
  108. case '1': return 1;
  109. case '2': return 2;
  110. case '3': return 3;
  111. case '4': return 4;
  112. case '5': return 5;
  113. case '6': return 6;
  114. case '7': return 7;
  115. case '8': return 8;
  116. case '9': return 9;
  117. case 'a': return 10;
  118. case 'b': return 11;
  119. case 'c': return 12;
  120. case 'd': return 13;
  121. case 'e': return 14;
  122. case 'f': return 15;
  123. case 'A': return 10;
  124. case 'B': return 11;
  125. case 'C': return 12;
  126. case 'D': return 13;
  127. case 'E': return 14;
  128. case 'F': return 15;
  129. }
  130. return 16; // NOTE(bill): Larger than highest possible
  131. }
  132. u64 u64_from_string(String string) {
  133. u64 base = 10;
  134. bool has_prefix = false;
  135. if (string.len > 2 && string[0] == '0') {
  136. switch (string[1]) {
  137. case 'b': base = 2; has_prefix = true; break;
  138. case 'o': base = 8; has_prefix = true; break;
  139. case 'd': base = 10; has_prefix = true; break;
  140. case 'z': base = 12; has_prefix = true; break;
  141. case 'x': base = 16; has_prefix = true; break;
  142. case 'h': base = 16; has_prefix = true; break;
  143. }
  144. }
  145. u8 *text = string.text;
  146. isize len = string.len;
  147. if (has_prefix) {
  148. text += 2;
  149. len -= 2;
  150. }
  151. u64 result = 0ull;
  152. for (isize i = 0; i < len; i++) {
  153. Rune r = cast(Rune)text[i];
  154. if (r == '_') {
  155. continue;
  156. }
  157. u64 v = u64_digit_value(r);
  158. if (v >= base) {
  159. break;
  160. }
  161. result *= base;
  162. result += v;
  163. }
  164. return result;
  165. }
  166. gb_global char const global_num_to_char_table[] =
  167. "0123456789"
  168. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  169. "abcdefghijklmnopqrstuvwxyz"
  170. "@$";
  171. String u64_to_string(u64 v, char *out_buf, isize out_buf_len) {
  172. char buf[32] = {0};
  173. isize i = gb_size_of(buf);
  174. u64 b = 10;
  175. while (v >= b) {
  176. buf[--i] = global_num_to_char_table[v%b];
  177. v /= b;
  178. }
  179. buf[--i] = global_num_to_char_table[v%b];
  180. isize len = gb_min(gb_size_of(buf)-i, out_buf_len);
  181. gb_memmove(out_buf, &buf[i], len);
  182. return make_string(cast(u8 *)out_buf, len);
  183. }
  184. String i64_to_string(i64 a, char *out_buf, isize out_buf_len) {
  185. char buf[32] = {0};
  186. isize i = gb_size_of(buf);
  187. bool negative = false;
  188. if (a < 0) {
  189. negative = true;
  190. a = -a;
  191. }
  192. u64 v = cast(u64)a;
  193. u64 b = 10;
  194. while (v >= b) {
  195. buf[--i] = global_num_to_char_table[v%b];
  196. v /= b;
  197. }
  198. buf[--i] = global_num_to_char_table[v%b];
  199. if (negative) {
  200. buf[--i] = '-';
  201. }
  202. isize len = gb_min(gb_size_of(buf)-i, out_buf_len);
  203. gb_memmove(out_buf, &buf[i], len);
  204. return make_string(cast(u8 *)out_buf, len);
  205. }
  206. gb_global i64 const signed_integer_mins[] = {
  207. 0,
  208. -128ll,
  209. -32768ll,
  210. 0,
  211. -2147483648ll,
  212. 0,
  213. 0,
  214. 0,
  215. (-9223372036854775807ll - 1ll),
  216. };
  217. gb_global i64 const signed_integer_maxs[] = {
  218. 0,
  219. 127ll,
  220. 32767ll,
  221. 0,
  222. 2147483647ll,
  223. 0,
  224. 0,
  225. 0,
  226. 9223372036854775807ll,
  227. };
  228. gb_global u64 const unsigned_integer_maxs[] = {
  229. 0,
  230. 255ull,
  231. 65535ull,
  232. 0,
  233. 4294967295ull,
  234. 0,
  235. 0,
  236. 0,
  237. 18446744073709551615ull,
  238. };
  239. bool add_overflow_u64(u64 x, u64 y, u64 *result) {
  240. *result = x + y;
  241. return *result < x || *result < y;
  242. }
  243. bool sub_overflow_u64(u64 x, u64 y, u64 *result) {
  244. *result = x - y;
  245. return *result > x;
  246. }
  247. void mul_overflow_u64(u64 x, u64 y, u64 *lo, u64 *hi) {
  248. #if defined(GB_COMPILER_MSVC) && defined(GB_ARCH_64_BIT)
  249. *lo = _umul128(x, y, hi);
  250. #else
  251. // URL(bill): https://stackoverflow.com/questions/25095741/how-can-i-multiply-64-bit-operands-and-get-128-bit-result-portably#25096197
  252. u64 u1, v1, w1, t, w3, k;
  253. u1 = (x & 0xffffffff);
  254. v1 = (y & 0xffffffff);
  255. t = (u1 * v1);
  256. w3 = (t & 0xffffffff);
  257. k = (t >> 32);
  258. x >>= 32;
  259. t = (x * v1) + k;
  260. k = (t & 0xffffffff);
  261. w1 = (t >> 32);
  262. y >>= 32;
  263. t = (u1 * y) + k;
  264. k = (t >> 32);
  265. *hi = (x * y) + w1 + k;
  266. *lo = (t << 32) + w3;
  267. #endif
  268. }
  269. gb_global String global_module_path = {0};
  270. gb_global bool global_module_path_set = false;
  271. #include "ptr_map.cpp"
  272. #include "ptr_set.cpp"
  273. #include "string_map.cpp"
  274. #include "string_set.cpp"
  275. #include "priority_queue.cpp"
  276. #include "thread_pool.cpp"
  277. struct StringIntern {
  278. StringIntern *next;
  279. isize len;
  280. char str[1];
  281. };
  282. PtrMap<uintptr, StringIntern *> string_intern_map = {}; // Key: u64
  283. gb_global Arena string_intern_arena = {};
  284. char const *string_intern(char const *text, isize len) {
  285. u64 hash = gb_fnv64a(text, len);
  286. uintptr key = cast(uintptr)(hash ? hash : 1);
  287. StringIntern **found = map_get(&string_intern_map, key);
  288. if (found) {
  289. for (StringIntern *it = *found; it != nullptr; it = it->next) {
  290. if (it->len == len && gb_strncmp(it->str, (char *)text, len) == 0) {
  291. return it->str;
  292. }
  293. }
  294. }
  295. StringIntern *new_intern = cast(StringIntern *)arena_alloc(&string_intern_arena, gb_offset_of(StringIntern, str) + len + 1, gb_align_of(StringIntern));
  296. new_intern->len = len;
  297. new_intern->next = found ? *found : nullptr;
  298. gb_memmove(new_intern->str, text, len);
  299. new_intern->str[len] = 0;
  300. map_set(&string_intern_map, key, new_intern);
  301. return new_intern->str;
  302. }
  303. char const *string_intern(String const &string) {
  304. return string_intern(cast(char const *)string.text, string.len);
  305. }
  306. void init_string_interner(void) {
  307. map_init(&string_intern_map, heap_allocator());
  308. }
  309. i32 next_pow2(i32 n) {
  310. if (n <= 0) {
  311. return 0;
  312. }
  313. n--;
  314. n |= n >> 1;
  315. n |= n >> 2;
  316. n |= n >> 4;
  317. n |= n >> 8;
  318. n |= n >> 16;
  319. n++;
  320. return n;
  321. }
  322. i64 next_pow2(i64 n) {
  323. if (n <= 0) {
  324. return 0;
  325. }
  326. n--;
  327. n |= n >> 1;
  328. n |= n >> 2;
  329. n |= n >> 4;
  330. n |= n >> 8;
  331. n |= n >> 16;
  332. n |= n >> 32;
  333. n++;
  334. return n;
  335. }
  336. isize next_pow2_isize(isize n) {
  337. if (n <= 0) {
  338. return 0;
  339. }
  340. n--;
  341. n |= n >> 1;
  342. n |= n >> 2;
  343. n |= n >> 4;
  344. n |= n >> 8;
  345. n |= n >> 16;
  346. #if defined(GB_ARCH_64_BIT)
  347. n |= n >> 32;
  348. #endif
  349. n++;
  350. return n;
  351. }
  352. u32 next_pow2_u32(u32 n) {
  353. if (n == 0) {
  354. return 0;
  355. }
  356. n--;
  357. n |= n >> 1;
  358. n |= n >> 2;
  359. n |= n >> 4;
  360. n |= n >> 8;
  361. n |= n >> 16;
  362. n++;
  363. return n;
  364. }
  365. i32 bit_set_count(u32 x) {
  366. x -= ((x >> 1) & 0x55555555);
  367. x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
  368. x = (((x >> 4) + x) & 0x0f0f0f0f);
  369. x += (x >> 8);
  370. x += (x >> 16);
  371. return cast(i32)(x & 0x0000003f);
  372. }
  373. i64 bit_set_count(u64 x) {
  374. u32 a = *(cast(u32 *)&x);
  375. u32 b = *(cast(u32 *)&x + 1);
  376. return bit_set_count(a) + bit_set_count(b);
  377. }
  378. u32 floor_log2(u32 x) {
  379. x |= x >> 1;
  380. x |= x >> 2;
  381. x |= x >> 4;
  382. x |= x >> 8;
  383. x |= x >> 16;
  384. return cast(u32)(bit_set_count(x) - 1);
  385. }
  386. u64 floor_log2(u64 x) {
  387. x |= x >> 1;
  388. x |= x >> 2;
  389. x |= x >> 4;
  390. x |= x >> 8;
  391. x |= x >> 16;
  392. x |= x >> 32;
  393. return cast(u64)(bit_set_count(x) - 1);
  394. }
  395. u32 ceil_log2(u32 x) {
  396. i32 y = cast(i32)(x & (x-1));
  397. y |= -y;
  398. y >>= 32-1;
  399. x |= x >> 1;
  400. x |= x >> 2;
  401. x |= x >> 4;
  402. x |= x >> 8;
  403. x |= x >> 16;
  404. return cast(u32)(bit_set_count(x) - 1 - y);
  405. }
  406. u64 ceil_log2(u64 x) {
  407. i64 y = cast(i64)(x & (x-1));
  408. y |= -y;
  409. y >>= 64-1;
  410. x |= x >> 1;
  411. x |= x >> 2;
  412. x |= x >> 4;
  413. x |= x >> 8;
  414. x |= x >> 16;
  415. x |= x >> 32;
  416. return cast(u64)(bit_set_count(x) - 1 - y);
  417. }
  418. u32 prev_pow2(u32 n) {
  419. if (n == 0) {
  420. return 0;
  421. }
  422. n |= n >> 1;
  423. n |= n >> 2;
  424. n |= n >> 4;
  425. n |= n >> 8;
  426. n |= n >> 16;
  427. return n - (n >> 1);
  428. }
  429. i32 prev_pow2(i32 n) {
  430. if (n <= 0) {
  431. return 0;
  432. }
  433. n |= n >> 1;
  434. n |= n >> 2;
  435. n |= n >> 4;
  436. n |= n >> 8;
  437. n |= n >> 16;
  438. return n - (n >> 1);
  439. }
  440. i64 prev_pow2(i64 n) {
  441. if (n <= 0) {
  442. return 0;
  443. }
  444. n |= n >> 1;
  445. n |= n >> 2;
  446. n |= n >> 4;
  447. n |= n >> 8;
  448. n |= n >> 16;
  449. n |= n >> 32;
  450. return n - (n >> 1);
  451. }
  452. u16 f32_to_f16(f32 value) {
  453. union { u32 i; f32 f; } v;
  454. i32 i, s, e, m;
  455. v.f = value;
  456. i = (i32)v.i;
  457. s = (i >> 16) & 0x00008000;
  458. e = ((i >> 23) & 0x000000ff) - (127 - 15);
  459. m = i & 0x007fffff;
  460. if (e <= 0) {
  461. if (e < -10) return cast(u16)s;
  462. m = (m | 0x00800000) >> (1 - e);
  463. if (m & 0x00001000)
  464. m += 0x00002000;
  465. return cast(u16)(s | (m >> 13));
  466. } else if (e == 0xff - (127 - 15)) {
  467. if (m == 0) {
  468. return cast(u16)(s | 0x7c00); /* NOTE(bill): infinity */
  469. } else {
  470. /* NOTE(bill): NAN */
  471. m >>= 13;
  472. return cast(u16)(s | 0x7c00 | m | (m == 0));
  473. }
  474. } else {
  475. if (m & 0x00001000) {
  476. m += 0x00002000;
  477. if (m & 0x00800000) {
  478. m = 0;
  479. e += 1;
  480. }
  481. }
  482. if (e > 30) {
  483. float volatile f = 1e12f;
  484. int j;
  485. for (j = 0; j < 10; j++) {
  486. f *= f; /* NOTE(bill): Cause overflow */
  487. }
  488. return cast(u16)(s | 0x7c00);
  489. }
  490. return cast(u16)(s | (e << 10) | (m >> 13));
  491. }
  492. }
  493. f32 f16_to_f32(u16 value) {
  494. typedef union { u32 u; f32 f; } fp32;
  495. fp32 v;
  496. fp32 magic = {(254u - 15u) << 23};
  497. fp32 inf_or_nan = {(127u + 16u) << 23};
  498. v.u = (value & 0x7fffu) << 13;
  499. v.f *= magic.f;
  500. if (v.f >= inf_or_nan.f) {
  501. v.u |= 255u << 23;
  502. }
  503. v.u |= (value & 0x8000u) << 16;
  504. return v.f;
  505. }
  506. f64 gb_sqrt(f64 x) {
  507. return sqrt(x);
  508. }
  509. // Doubly Linked Lists
  510. #define DLIST_SET(curr_element, next_element) do { \
  511. (curr_element)->next = (next_element); \
  512. (curr_element)->next->prev = (curr_element); \
  513. (curr_element) = (curr_element)->next; \
  514. } while (0)
  515. #define DLIST_APPEND(root_element, curr_element, next_element) do { \
  516. if ((root_element) == nullptr) { \
  517. (root_element) = (curr_element) = (next_element); \
  518. } else { \
  519. DLIST_SET(curr_element, next_element); \
  520. } \
  521. } while (0)
  522. #if defined(GB_SYSTEM_WINDOWS)
  523. wchar_t **command_line_to_wargv(wchar_t *cmd_line, int *_argc) {
  524. u32 i, j;
  525. u32 len = cast(u32)string16_len(cmd_line);
  526. i = ((len+2)/2)*gb_size_of(void *) + gb_size_of(void *);
  527. wchar_t **argv = cast(wchar_t **)GlobalAlloc(GMEM_FIXED, i + (len+2)*gb_size_of(wchar_t));
  528. wchar_t *_argv = cast(wchar_t *)((cast(u8 *)argv)+i);
  529. u32 argc = 0;
  530. argv[argc] = _argv;
  531. bool in_quote = false;
  532. bool in_text = false;
  533. bool in_space = true;
  534. i = 0;
  535. j = 0;
  536. for (;;) {
  537. wchar_t a = cmd_line[i];
  538. if (a == 0) {
  539. break;
  540. }
  541. if (in_quote) {
  542. if (a == '\"') {
  543. in_quote = false;
  544. } else {
  545. _argv[j++] = a;
  546. }
  547. } else {
  548. switch (a) {
  549. case '\"':
  550. in_quote = true;
  551. in_text = true;
  552. if (in_space) argv[argc++] = _argv+j;
  553. in_space = false;
  554. break;
  555. case ' ':
  556. case '\t':
  557. case '\n':
  558. case '\r':
  559. if (in_text) _argv[j++] = '\0';
  560. in_text = false;
  561. in_space = true;
  562. break;
  563. default:
  564. in_text = true;
  565. if (in_space) argv[argc++] = _argv+j;
  566. _argv[j++] = a;
  567. in_space = false;
  568. break;
  569. }
  570. }
  571. i++;
  572. }
  573. _argv[j] = '\0';
  574. argv[argc] = nullptr;
  575. if (_argc) *_argc = argc;
  576. return argv;
  577. }
  578. #endif
  579. #include "path.cpp"
  580. struct LoadedFile {
  581. void *handle;
  582. void const *data;
  583. i32 size;
  584. };
  585. enum LoadedFileError {
  586. LoadedFile_None,
  587. LoadedFile_Empty,
  588. LoadedFile_FileTooLarge,
  589. LoadedFile_Invalid,
  590. LoadedFile_NotExists,
  591. LoadedFile_Permission,
  592. LoadedFile_COUNT,
  593. };
  594. LoadedFileError load_file_32(char const *fullpath, LoadedFile *memory_mapped_file, bool copy_file_contents) {
  595. LoadedFileError err = LoadedFile_None;
  596. if (!copy_file_contents) {
  597. #if defined(GB_SYSTEM_WINDOWS)
  598. isize w_len = 0;
  599. wchar_t *w_str = gb__alloc_utf8_to_ucs2(temporary_allocator(), fullpath, &w_len);
  600. if (w_str == nullptr) {
  601. return LoadedFile_Invalid;
  602. }
  603. i64 file_size = 0;
  604. LARGE_INTEGER li_file_size = {};
  605. HANDLE handle = nullptr;
  606. HANDLE file_mapping = nullptr;
  607. void *file_data = nullptr;
  608. handle = CreateFileW(w_str, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  609. if (handle == INVALID_HANDLE_VALUE) {
  610. handle = nullptr;
  611. goto window_handle_file_error;
  612. }
  613. li_file_size = {};
  614. if (!GetFileSizeEx(handle, &li_file_size)) {
  615. goto window_handle_file_error;
  616. }
  617. file_size = cast(i64)li_file_size.QuadPart;
  618. if (file_size > I32_MAX) {
  619. CloseHandle(handle);
  620. return LoadedFile_FileTooLarge;
  621. }
  622. if (file_size == 0) {
  623. CloseHandle(handle);
  624. err = LoadedFile_Empty;
  625. memory_mapped_file->handle = nullptr;
  626. memory_mapped_file->data = nullptr;
  627. memory_mapped_file->size = 0;
  628. return err;
  629. }
  630. file_mapping = CreateFileMappingW(handle, nullptr, PAGE_READONLY, 0, 0, nullptr);
  631. CloseHandle(handle);
  632. file_data = MapViewOfFileEx(file_mapping, FILE_MAP_READ, 0, 0, 0/*file_size*/, nullptr/*base address*/);
  633. memory_mapped_file->handle = cast(void *)file_mapping;
  634. memory_mapped_file->data = file_data;
  635. memory_mapped_file->size = cast(i32)file_size;
  636. return err;
  637. window_handle_file_error:;
  638. {
  639. DWORD handle_err = GetLastError();
  640. CloseHandle(handle);
  641. err = LoadedFile_Invalid;
  642. switch (handle_err) {
  643. case ERROR_FILE_NOT_FOUND:
  644. case ERROR_PATH_NOT_FOUND:
  645. case ERROR_INVALID_DRIVE:
  646. err = LoadedFile_NotExists;
  647. break;
  648. case ERROR_ACCESS_DENIED:
  649. case ERROR_INVALID_ACCESS:
  650. err = LoadedFile_Permission;
  651. break;
  652. }
  653. return err;
  654. }
  655. #endif
  656. }
  657. gbFileContents fc = gb_file_read_contents(permanent_allocator(), true, fullpath);
  658. if (fc.size > I32_MAX) {
  659. err = LoadedFile_FileTooLarge;
  660. gb_file_free_contents(&fc);
  661. } else if (fc.data != nullptr) {
  662. memory_mapped_file->handle = nullptr;
  663. memory_mapped_file->data = fc.data;
  664. memory_mapped_file->size = cast(i32)fc.size;
  665. } else {
  666. gbFile f = {};
  667. gbFileError file_err = gb_file_open(&f, fullpath);
  668. defer (gb_file_close(&f));
  669. switch (file_err) {
  670. case gbFileError_Invalid: err = LoadedFile_Invalid; break;
  671. case gbFileError_NotExists: err = LoadedFile_NotExists; break;
  672. case gbFileError_Permission: err = LoadedFile_Permission; break;
  673. }
  674. if (err == LoadedFile_None && gb_file_size(&f) == 0) {
  675. err = LoadedFile_Empty;
  676. }
  677. }
  678. return err;
  679. }
  680. #define USE_DAMERAU_LEVENSHTEIN 1
  681. isize levenstein_distance_case_insensitive(String const &a, String const &b) {
  682. isize w = b.len+1;
  683. isize h = a.len+1;
  684. isize *matrix = gb_alloc_array(temporary_allocator(), isize, w*h);
  685. for (isize i = 0; i <= a.len; i++) {
  686. matrix[i*w + 0] = i;
  687. }
  688. for (isize i = 0; i <= b.len; i++) {
  689. matrix[0*w + i] = i;
  690. }
  691. for (isize i = 1; i <= a.len; i++) {
  692. char a_c = gb_char_to_lower(cast(char)a.text[i-1]);
  693. for (isize j = 1; j <= b.len; j++) {
  694. char b_c = gb_char_to_lower(cast(char)b.text[j-1]);
  695. if (a_c == b_c) {
  696. matrix[i*w + j] = matrix[(i-1)*w + j-1];
  697. } else {
  698. isize remove = matrix[(i-1)*w + j] + 1;
  699. isize insert = matrix[i*w + j-1] + 1;
  700. isize substitute = matrix[(i-1)*w + j-1] + 1;
  701. isize minimum = remove;
  702. if (insert < minimum) {
  703. minimum = insert;
  704. }
  705. if (substitute < minimum) {
  706. minimum = substitute;
  707. }
  708. // Damerau-Levenshtein (transposition extension)
  709. #if USE_DAMERAU_LEVENSHTEIN
  710. if (i > 1 && j > 1) {
  711. isize transpose = matrix[(i-2)*w + j-2] + 1;
  712. if (transpose < minimum) {
  713. minimum = transpose;
  714. }
  715. }
  716. #endif
  717. matrix[i*w + j] = minimum;
  718. }
  719. }
  720. }
  721. return matrix[a.len*w + b.len];
  722. }
  723. struct DistanceAndTarget {
  724. isize distance;
  725. String target;
  726. };
  727. struct DidYouMeanAnswers {
  728. Array<DistanceAndTarget> distances;
  729. String key;
  730. };
  731. enum {MAX_SMALLEST_DID_YOU_MEAN_DISTANCE = 3-USE_DAMERAU_LEVENSHTEIN};
  732. DidYouMeanAnswers did_you_mean_make(gbAllocator allocator, isize cap, String const &key) {
  733. DidYouMeanAnswers d = {};
  734. array_init(&d.distances, allocator, 0, cap);
  735. d.key = key;
  736. return d;
  737. }
  738. void did_you_mean_destroy(DidYouMeanAnswers *d) {
  739. array_free(&d->distances);
  740. }
  741. void did_you_mean_append(DidYouMeanAnswers *d, String const &target) {
  742. if (target.len == 0 || target == "_") {
  743. return;
  744. }
  745. DistanceAndTarget dat = {};
  746. dat.target = target;
  747. dat.distance = levenstein_distance_case_insensitive(d->key, target);
  748. array_add(&d->distances, dat);
  749. }
  750. Slice<DistanceAndTarget> did_you_mean_results(DidYouMeanAnswers *d) {
  751. gb_sort_array(d->distances.data, d->distances.count, gb_isize_cmp(gb_offset_of(DistanceAndTarget, distance)));
  752. isize count = 0;
  753. for (isize i = 0; i < d->distances.count; i++) {
  754. isize distance = d->distances[i].distance;
  755. if (distance > MAX_SMALLEST_DID_YOU_MEAN_DISTANCE) {
  756. break;
  757. }
  758. count += 1;
  759. }
  760. return slice_array(d->distances, 0, count);
  761. }