common.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. #define GB_IMPLEMENTATION
  2. #include "gb/gb.h"
  3. gbAllocator heap_allocator(void) {
  4. return gb_heap_allocator();
  5. }
  6. #include "string.cpp"
  7. #include "array.cpp"
  8. gb_global String global_module_path = {};
  9. gb_global b32 global_module_path_set = false;
  10. String get_module_dir() {
  11. if (global_module_path_set) {
  12. return global_module_path;
  13. }
  14. Array<wchar_t> path_buf;
  15. array_init(&path_buf, heap_allocator(), 300);
  16. defer (array_free(&path_buf));
  17. array_resize(&path_buf, 300);
  18. isize len = 0;
  19. for (;;) {
  20. len = GetModuleFileNameW(NULL, &path_buf[0], path_buf.count);
  21. if (len == 0) {
  22. return make_string(NULL, 0);
  23. }
  24. if (len < path_buf.count) {
  25. break;
  26. }
  27. array_resize(&path_buf, 2*path_buf.count + 300);
  28. }
  29. gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
  30. defer (gb_temp_arena_memory_end(tmp));
  31. wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
  32. GetModuleFileNameW(NULL, text, len);
  33. String path = string16_to_string(heap_allocator(), make_string16(text, len));
  34. for (isize i = path.len-1; i >= 0; i--) {
  35. u8 c = path.text[i];
  36. if (c == '/' || c == '\\') {
  37. break;
  38. }
  39. path.len--;
  40. }
  41. global_module_path = path;
  42. global_module_path_set = true;
  43. return path;
  44. }
  45. String path_to_fullpath(gbAllocator a, String s) {
  46. gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
  47. defer (gb_temp_arena_memory_end(tmp));
  48. String16 string16 = string_to_string16(string_buffer_allocator, s);
  49. DWORD len = GetFullPathNameW(string16.text, 0, NULL, NULL);
  50. if (len == 0) {
  51. return make_string(NULL, 0);
  52. }
  53. wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
  54. GetFullPathNameW(string16.text, len, text, NULL);
  55. text[len] = 0;
  56. return string16_to_string(a, make_string16(text, len));
  57. }
  58. struct BlockTimer {
  59. u64 start;
  60. u64 finish;
  61. char *msg;
  62. BlockTimer(char *msg) : msg(msg) {
  63. start = gb_utc_time_now();
  64. }
  65. ~BlockTimer() {
  66. finish = gb_utc_time_now();
  67. gb_printf_err("%llu us\n", finish-start);
  68. }
  69. };
  70. // Hasing
  71. enum HashKeyKind {
  72. HashKey_Default,
  73. HashKey_String,
  74. HashKey_Pointer,
  75. };
  76. struct HashKey {
  77. HashKeyKind kind;
  78. u64 key;
  79. union {
  80. String string; // if String, s.len > 0
  81. void * ptr;
  82. };
  83. };
  84. gb_inline HashKey hashing_proc(void const *data, isize len) {
  85. HashKey h = {};
  86. h.kind = HashKey_Default;
  87. // h.key = gb_murmur64(data, len);
  88. h.key = gb_fnv64a(data, len);
  89. return h;
  90. }
  91. gb_inline HashKey hash_string(String s) {
  92. HashKey h = hashing_proc(s.text, s.len);
  93. h.kind = HashKey_String;
  94. h.string = s;
  95. return h;
  96. }
  97. gb_inline HashKey hash_pointer(void *ptr) {
  98. HashKey h = {};
  99. h.key = cast(u64)cast(uintptr)ptr;
  100. h.ptr = ptr;
  101. h.kind = HashKey_Default;
  102. return h;
  103. }
  104. b32 hash_key_equal(HashKey a, HashKey b) {
  105. if (a.key == b.key) {
  106. // NOTE(bill): If two string's hashes collide, compare the strings themselves
  107. if (a.kind == HashKey_String) {
  108. if (b.kind == HashKey_String) {
  109. return a.string == b.string;
  110. }
  111. return false;
  112. }
  113. return true;
  114. }
  115. return false;
  116. }
  117. i64 next_pow2(i64 n) {
  118. if (n <= 0) {
  119. return 0;
  120. }
  121. n--;
  122. n |= n >> 1;
  123. n |= n >> 2;
  124. n |= n >> 4;
  125. n |= n >> 8;
  126. n |= n >> 16;
  127. n |= n >> 32;
  128. n++;
  129. return n;
  130. }
  131. i64 prev_pow2(i64 n) {
  132. if (n <= 0) {
  133. return 0;
  134. }
  135. n |= n >> 1;
  136. n |= n >> 2;
  137. n |= n >> 4;
  138. n |= n >> 8;
  139. n |= n >> 16;
  140. n |= n >> 32;
  141. return n - (n >> 1);
  142. }
  143. i16 f32_to_f16(f32 value) {
  144. union { u32 i; f32 f; } v;
  145. i32 i, s, e, m;
  146. v.f = value;
  147. i = (i32)v.i;
  148. s = (i >> 16) & 0x00008000;
  149. e = ((i >> 23) & 0x000000ff) - (127 - 15);
  150. m = i & 0x007fffff;
  151. if (e <= 0) {
  152. if (e < -10) return cast(i16)s;
  153. m = (m | 0x00800000) >> (1 - e);
  154. if (m & 0x00001000)
  155. m += 0x00002000;
  156. return cast(i16)(s | (m >> 13));
  157. } else if (e == 0xff - (127 - 15)) {
  158. if (m == 0) {
  159. return cast(i16)(s | 0x7c00); /* NOTE(bill): infinity */
  160. } else {
  161. /* NOTE(bill): NAN */
  162. m >>= 13;
  163. return cast(i16)(s | 0x7c00 | m | (m == 0));
  164. }
  165. } else {
  166. if (m & 0x00001000) {
  167. m += 0x00002000;
  168. if (m & 0x00800000) {
  169. m = 0;
  170. e += 1;
  171. }
  172. }
  173. if (e > 30) {
  174. float volatile f = 1e12f;
  175. int j;
  176. for (j = 0; j < 10; j++)
  177. f *= f; /* NOTE(bill): Cause overflow */
  178. return cast(i16)(s | 0x7c00);
  179. }
  180. return cast(i16)(s | (e << 10) | (m >> 13));
  181. }
  182. }
  183. #define for_array(index_, array_) for (isize index_ = 0; index_ < (array_).count; index_++)
  184. // Doubly Linked Lists
  185. #define DLIST_SET(curr_element, next_element) do { \
  186. (curr_element)->next = (next_element); \
  187. (curr_element)->next->prev = (curr_element); \
  188. (curr_element) = (curr_element)->next; \
  189. } while (0)
  190. #define DLIST_APPEND(root_element, curr_element, next_element) do { \
  191. if ((root_element) == NULL) { \
  192. (root_element) = (curr_element) = (next_element); \
  193. } else { \
  194. DLIST_SET(curr_element, next_element); \
  195. } \
  196. } while (0)
  197. ////////////////////////////////////////////////////////////////
  198. //
  199. // Generic Data Structures
  200. //
  201. ////////////////////////////////////////////////////////////////
  202. struct MapFindResult {
  203. isize hash_index;
  204. isize entry_prev;
  205. isize entry_index;
  206. };
  207. template <typename T>
  208. struct MapEntry {
  209. HashKey key;
  210. isize next;
  211. T value;
  212. };
  213. template <typename T>
  214. struct Map {
  215. Array<isize> hashes;
  216. Array<MapEntry<T> > entries;
  217. };
  218. template <typename T> void map_init (Map<T> *h, gbAllocator a);
  219. template <typename T> void map_init_with_reserve(Map<T> *h, gbAllocator a, isize capacity);
  220. template <typename T> void map_destroy (Map<T> *h);
  221. template <typename T> T * map_get (Map<T> *h, HashKey key);
  222. template <typename T> void map_set (Map<T> *h, HashKey key, T value);
  223. template <typename T> void map_remove (Map<T> *h, HashKey key);
  224. template <typename T> void map_clear (Map<T> *h);
  225. template <typename T> void map_grow (Map<T> *h);
  226. template <typename T> void map_rehash (Map<T> *h, isize new_count);
  227. template <typename T> MapEntry<T> *multi_map_find_first(Map<T> *h, HashKey key);
  228. template <typename T> MapEntry<T> *multi_map_find_next (Map<T> *h, MapEntry<T> *e);
  229. template <typename T> isize multi_map_count (Map<T> *h, HashKey key);
  230. template <typename T> void multi_map_get_all (Map<T> *h, HashKey key, T *items);
  231. template <typename T> void multi_map_insert (Map<T> *h, HashKey key, T value);
  232. template <typename T> void multi_map_remove (Map<T> *h, HashKey key, MapEntry<T> *e);
  233. template <typename T> void multi_map_remove_all(Map<T> *h, HashKey key);
  234. template <typename T>
  235. gb_inline void map_init(Map<T> *h, gbAllocator a) {
  236. array_init(&h->hashes, a);
  237. array_init(&h->entries, a);
  238. }
  239. template <typename T>
  240. gb_inline void map_init_with_reserve(Map<T> *h, gbAllocator a, isize capacity) {
  241. array_init(&h->hashes, a, capacity);
  242. array_init(&h->entries, a, capacity);
  243. }
  244. template <typename T>
  245. gb_inline void map_destroy(Map<T> *h) {
  246. array_free(&h->entries);
  247. array_free(&h->hashes);
  248. }
  249. template <typename T>
  250. gb_internal isize map__add_entry(Map<T> *h, HashKey key) {
  251. MapEntry<T> e = {};
  252. e.key = key;
  253. e.next = -1;
  254. array_add(&h->entries, e);
  255. return h->entries.count-1;
  256. }
  257. template <typename T>
  258. gb_internal MapFindResult map__find(Map<T> *h, HashKey key) {
  259. MapFindResult fr = {-1, -1, -1};
  260. if (h->hashes.count > 0) {
  261. fr.hash_index = key.key % h->hashes.count;
  262. fr.entry_index = h->hashes[fr.hash_index];
  263. while (fr.entry_index >= 0) {
  264. if (hash_key_equal(h->entries[fr.entry_index].key, key)) {
  265. return fr;
  266. }
  267. fr.entry_prev = fr.entry_index;
  268. fr.entry_index = h->entries[fr.entry_index].next;
  269. }
  270. }
  271. return fr;
  272. }
  273. template <typename T>
  274. gb_internal MapFindResult map__find(Map<T> *h, MapEntry<T> *e) {
  275. MapFindResult fr = {-1, -1, -1};
  276. if (h->hashes.count > 0) {
  277. fr.hash_index = e->key.key % h->hashes.count;
  278. fr.entry_index = h->hashes[fr.hash_index];
  279. while (fr.entry_index >= 0) {
  280. if (&h->entries[fr.entry_index] == e) {
  281. return fr;
  282. }
  283. fr.entry_prev = fr.entry_index;
  284. fr.entry_index = h->entries[fr.entry_index].next;
  285. }
  286. }
  287. return fr;
  288. }
  289. template <typename T>
  290. gb_internal b32 map__full(Map<T> *h) {
  291. return 0.75f * h->hashes.count <= h->entries.count;
  292. }
  293. template <typename T>
  294. gb_inline void map_grow(Map<T> *h) {
  295. isize new_count = GB_ARRAY_GROW_FORMULA(h->entries.count);
  296. map_rehash(h, new_count);
  297. }
  298. template <typename T>
  299. void map_rehash(Map<T> *h, isize new_count) {
  300. isize i, j;
  301. Map<T> nh = {};
  302. map_init(&nh, h->hashes.allocator);
  303. array_resize(&nh.hashes, new_count);
  304. array_reserve(&nh.entries, h->entries.count);
  305. for (i = 0; i < new_count; i++) {
  306. nh.hashes[i] = -1;
  307. }
  308. for (i = 0; i < h->entries.count; i++) {
  309. MapEntry<T> *e = &h->entries[i];
  310. MapFindResult fr;
  311. if (nh.hashes.count == 0) {
  312. map_grow(&nh);
  313. }
  314. fr = map__find(&nh, e->key);
  315. j = map__add_entry(&nh, e->key);
  316. if (fr.entry_prev < 0) {
  317. nh.hashes[fr.hash_index] = j;
  318. } else {
  319. nh.entries[fr.entry_prev].next = j;
  320. }
  321. nh.entries[j].next = fr.entry_index;
  322. nh.entries[j].value = e->value;
  323. if (map__full(&nh)) {
  324. map_grow(&nh);
  325. }
  326. }
  327. map_destroy(h);
  328. *h = nh;
  329. }
  330. template <typename T>
  331. gb_inline T *map_get(Map<T> *h, HashKey key) {
  332. isize index = map__find(h, key).entry_index;
  333. if (index >= 0)
  334. return &h->entries[index].value;
  335. return NULL;
  336. }
  337. template <typename T>
  338. void map_set(Map<T> *h, HashKey key, T value) {
  339. isize index;
  340. MapFindResult fr;
  341. if (h->hashes.count == 0)
  342. map_grow(h);
  343. fr = map__find(h, key);
  344. if (fr.entry_index >= 0) {
  345. index = fr.entry_index;
  346. } else {
  347. index = map__add_entry(h, key);
  348. if (fr.entry_prev >= 0) {
  349. h->entries[fr.entry_prev].next = index;
  350. } else {
  351. h->hashes[fr.hash_index] = index;
  352. }
  353. }
  354. h->entries[index].value = value;
  355. if (map__full(h))
  356. map_grow(h);
  357. }
  358. template <typename T>
  359. void map__erase(Map<T> *h, MapFindResult fr) {
  360. if (fr.entry_prev < 0) {
  361. h->hashes[fr.hash_index] = h->entries[fr.entry_index].next;
  362. } else {
  363. h->entries[fr.entry_prev].next = h->entries[fr.entry_index].next;
  364. }
  365. if (fr.entry_index == h->entries.count-1) {
  366. array_pop(&h->entries);
  367. return;
  368. }
  369. h->entries[fr.entry_index] = h->entries[h->entries.count-1];
  370. MapFindResult last = map__find(h, h->entries[fr.entry_index].key);
  371. if (last.entry_prev >= 0) {
  372. h->entries[last.entry_prev].next = fr.entry_index;
  373. } else {
  374. h->hashes[last.hash_index] = fr.entry_index;
  375. }
  376. }
  377. template <typename T>
  378. void map_remove(Map<T> *h, HashKey key) {
  379. MapFindResult fr = map__find(h, key);
  380. if (fr.entry_index >= 0) {
  381. map__erase(h, fr);
  382. }
  383. }
  384. template <typename T>
  385. gb_inline void map_clear(Map<T> *h) {
  386. gb_array_clear(h->hashes);
  387. gb_array_clear(h->entries);
  388. }
  389. template <typename T>
  390. MapEntry<T> *multi_map_find_first(Map<T> *h, HashKey key) {
  391. isize i = map__find(h, key).entry_index;
  392. if (i < 0) {
  393. return NULL;
  394. }
  395. return &h->entries[i];
  396. }
  397. template <typename T>
  398. MapEntry<T> *multi_map_find_next(Map<T> *h, MapEntry<T> *e) {
  399. isize i = e->next;
  400. while (i >= 0) {
  401. if (hash_key_equal(h->entries[i].key, e->key)) {
  402. return &h->entries[i];
  403. }
  404. i = h->entries[i].next;
  405. }
  406. return NULL;
  407. }
  408. template <typename T>
  409. isize multi_map_count(Map<T> *h, HashKey key) {
  410. isize count = 0;
  411. auto *e = multi_map_find_first(h, key);
  412. while (e != NULL) {
  413. count++;
  414. e = multi_map_find_next(h, e);
  415. }
  416. return count;
  417. }
  418. template <typename T>
  419. void multi_map_get_all(Map<T> *h, HashKey key, T *items) {
  420. isize i = 0;
  421. auto *e = multi_map_find_first(h, key);
  422. while (e != NULL) {
  423. items[i++] = e->value;
  424. e = multi_map_find_next(h, e);
  425. }
  426. }
  427. template <typename T>
  428. void multi_map_insert(Map<T> *h, HashKey key, T value) {
  429. if (h->hashes.count == 0) {
  430. map_grow(h);
  431. }
  432. MapFindResult fr = map__find(h, key);
  433. isize i = map__add_entry(h, key);
  434. if (fr.entry_prev < 0) {
  435. h->hashes[fr.hash_index] = i;
  436. } else {
  437. h->entries[fr.entry_prev].next = i;
  438. }
  439. h->entries[i].next = fr.entry_index;
  440. h->entries[i].value = value;
  441. if (map__full(h)) {
  442. map_grow(h);
  443. }
  444. }
  445. template <typename T>
  446. void multi_map_remove(Map<T> *h, HashKey key, MapEntry<T> *e) {
  447. MapFindResult fr = map__find(h, e);
  448. if (fr.entry_index >= 0) {
  449. map__erase(h, fr);
  450. }
  451. }
  452. template <typename T>
  453. void multi_map_remove_all(Map<T> *h, HashKey key) {
  454. while (map_get(h, key) != NULL) {
  455. map_remove(h, key);
  456. }
  457. }