| @@ -16,19 +16,26 @@ struct Array_List { | |||||
| length = initial_capacity; | length = initial_capacity; | ||||
| } | } | ||||
| static Array_List<type> create_from(std::initializer_list<type> l) { | |||||
| Array_List<type> ret; | |||||
| ret.alloc_from(l); | |||||
| return ret; | |||||
| } | |||||
| void alloc_from(std::initializer_list<type> l) { | void alloc_from(std::initializer_list<type> l) { | ||||
| length = max(l.size(), 1); // alloc at least one | length = max(l.size(), 1); // alloc at least one | ||||
| data = (type*)malloc(length * sizeof(type)); | data = (type*)malloc(length * sizeof(type)); | ||||
| count = 0; | count = 0; | ||||
| // TODO(Felix): Use memcpy here | |||||
| for (type t : l) { | for (type t : l) { | ||||
| data[count++] = t; | data[count++] = t; | ||||
| } | } | ||||
| } | } | ||||
| void extend(std::initializer_list<type> l) { | void extend(std::initializer_list<type> l) { | ||||
| reserve(l.size()); | reserve(l.size()); | ||||
| // TODO(Felix): Use memcpy here | |||||
| for (type e : l) { | for (type e : l) { | ||||
| append(e); | append(e); | ||||
| } | } | ||||
| @@ -50,12 +57,23 @@ struct Array_List { | |||||
| ret.count = count; | ret.count = count; | ||||
| ret.data = (type*)malloc(length * sizeof(type)); | ret.data = (type*)malloc(length * sizeof(type)); | ||||
| // TODO(Felix): Maybe use memcpy here | |||||
| for (u32 i = 0; i < count; ++i) { | for (u32 i = 0; i < count; ++i) { | ||||
| ret.data[i] = data[i]; | ret.data[i] = data[i]; | ||||
| } | } | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| void copy_values_from(Array_List<type> other) { | |||||
| // clear the array | |||||
| count = 0; | |||||
| // make sure we have allocated enough | |||||
| reserve(other.count); | |||||
| // copy stuff | |||||
| count = other.count; | |||||
| memcpy(data, other.data, sizeof(type) * other.count); | |||||
| } | |||||
| type* begin() { | type* begin() { | ||||
| return data; | return data; | ||||
| } | } | ||||
| @@ -139,7 +157,7 @@ struct Array_List { | |||||
| _merge(left, middle, right); | _merge(left, middle, right); | ||||
| } | } | ||||
| u32 sorted_find(type elem, s32 left=-1, s32 right=-1) { | |||||
| s32 sorted_find(type elem, s32 left=-1, s32 right=-1) { | |||||
| if (left == -1) { | if (left == -1) { | ||||
| return sorted_find(elem, 0, count - 1); | return sorted_find(elem, 0, count - 1); | ||||
| } else if (left == right) { | } else if (left == right) { | ||||
| @@ -2,7 +2,7 @@ | |||||
| #include "types.hpp" | #include "types.hpp" | ||||
| template <typename type> | template <typename type> | ||||
| class Bucket_Allocator { | |||||
| struct Bucket_Allocator { | |||||
| u32 next_index_in_latest_bucket; | u32 next_index_in_latest_bucket; | ||||
| u32 next_bucket_index; | u32 next_bucket_index; | ||||
| u32 bucket_count; | u32 bucket_count; | ||||
| @@ -12,8 +12,6 @@ class Bucket_Allocator { | |||||
| type** buckets; | type** buckets; | ||||
| void expand() { | void expand() { | ||||
| // printf("realloc time\n"); | |||||
| // realloc time | |||||
| buckets = (type**)realloc(buckets, bucket_count * 2 * sizeof(type*)); | buckets = (type**)realloc(buckets, bucket_count * 2 * sizeof(type*)); | ||||
| bucket_count *= 2; | bucket_count *= 2; | ||||
| } | } | ||||
| @@ -34,8 +32,7 @@ class Bucket_Allocator { | |||||
| } | } | ||||
| } | } | ||||
| public: | |||||
| void alloc(u32 bucket_size = 16, u32 initial_bucket_count = 8) { | |||||
| void alloc(u32 bucket_size = 16, u32 initial_bucket_count = 8) { | |||||
| this->free_list.alloc(); | this->free_list.alloc(); | ||||
| this->bucket_size = bucket_size; | this->bucket_size = bucket_size; | ||||
| next_index_in_latest_bucket = 0; | next_index_in_latest_bucket = 0; | ||||
| @@ -76,6 +73,7 @@ public: | |||||
| template <typename lambda> | template <typename lambda> | ||||
| void for_each(lambda p) { | void for_each(lambda p) { | ||||
| free_list.sort(); | free_list.sort(); | ||||
| type* val; | type* val; | ||||
| for (u32 i = 0; i < next_bucket_index; ++i) { | for (u32 i = 0; i < next_bucket_index; ++i) { | ||||
| for (u32 j = 0; j < bucket_size; ++j) { | for (u32 j = 0; j < bucket_size; ++j) { | ||||
| @@ -1,10 +1,11 @@ | |||||
| @echo off | @echo off | ||||
| mkdir bin | |||||
| rmdir bin /s /q 2>NUL | |||||
| mkdir bin 2>NUL | |||||
| set EXE_RAW=test | set EXE_RAW=test | ||||
| set BINDIR_RAW=bin | set BINDIR_RAW=bin | ||||
| set SRC=test.cpp | |||||
| set SRC=main.cpp | |||||
| set EXE_WIN=%EXE_RAW%.exe | set EXE_WIN=%EXE_RAW%.exe | ||||
| set EXE_LINUX=%EXE_RAW% | set EXE_LINUX=%EXE_RAW% | ||||
| @@ -21,15 +22,15 @@ echo g++: | |||||
| g++ -std=c++17 %SRC% -o %BINDIR_WIN%\g++_%EXE_WIN% | g++ -std=c++17 %SRC% -o %BINDIR_WIN%\g++_%EXE_WIN% | ||||
| %BINDIR_WIN%\g++_%EXE_WIN% | %BINDIR_WIN%\g++_%EXE_WIN% | ||||
| REM echo. | |||||
| REM echo cl: | |||||
| REM cl %SRC% /std:c++latest /nologo /Zi /Fd: %BINDIR_WIN%\cl_%EXE_WIN%.pdb /Fo: %BINDIR_WIN%\ /Fe: %BINDIR_WIN%\cl_%EXE_WIN% /wd4090 | |||||
| REM %BINDIR_WIN%\cl_%EXE_WIN% | |||||
| echo. | |||||
| echo cl: | |||||
| cl %SRC% /std:c++latest /nologo /Zi /Fd: %BINDIR_WIN%\cl_%EXE_WIN%.pdb /Fo: %BINDIR_WIN%\ /Fe: %BINDIR_WIN%\cl_%EXE_WIN% /wd4090 1>NUL | |||||
| %BINDIR_WIN%\cl_%EXE_WIN% | |||||
| REM echo. | |||||
| REM echo bash_clang: | |||||
| REM bash -c "clang -std=c++17 %SRC% -o %BINDIR_LINUX%/bash_clang_%EXE_LINUX% && %BINDIR_LINUX%/bash_clang_%EXE_LINUX%" | |||||
| echo. | |||||
| echo bash_clang: | |||||
| bash -c "clang++ --std=c++17 %SRC% -o %BINDIR_LINUX%/bash_clang_%EXE_LINUX% && %BINDIR_LINUX%/bash_clang_%EXE_LINUX%" | |||||
| echo. | echo. | ||||
| echo bash_g++: | echo bash_g++: | ||||
| bash -c "g++ -std=c++17 %SRC% -o %BINDIR_LINUX%/bash_g++_%EXE_LINUX% && %BINDIR_LINUX%/bash_g++_%EXE_LINUX%" | |||||
| bash -c "g++ --std=c++17 %SRC% -o %BINDIR_LINUX%/bash_g++_%EXE_LINUX% && %BINDIR_LINUX%/bash_g++_%EXE_LINUX%" | |||||
| @@ -1,5 +1,6 @@ | |||||
| #pragma once | #pragma once | ||||
| #include "stdio.h" | #include "stdio.h" | ||||
| #include "math.h" | #include "math.h" | ||||
| #include "stdarg.h" | #include "stdarg.h" | ||||
| #include "stdlib.h" | #include "stdlib.h" | ||||
| @@ -53,11 +54,14 @@ auto create_error(const char* c_func_name, const char* c_file_name, | |||||
| #define create_generic_error(...) \ | #define create_generic_error(...) \ | ||||
| __create_error("generic", __VA_ARGS__) | __create_error("generic", __VA_ARGS__) | ||||
| #define assert(condition, ...) \ | |||||
| #ifdef assert | |||||
| #undef assert | |||||
| #endif | |||||
| #define assert(condition, ...) \ | |||||
| do { \ | do { \ | ||||
| if (!(condition)) { \ | if (!(condition)) { \ | ||||
| char* msg; \ | char* msg; \ | ||||
| print_to_string(&msg, __VA_ARGS__); \ | |||||
| print_to_string(&msg, __VA_ARGS__); \ | |||||
| create_assertion_error("Assertion-error: %s\n" \ | create_assertion_error("Assertion-error: %s\n" \ | ||||
| " condition: %s\n" \ | " condition: %s\n" \ | ||||
| " in: %s:%d", \ | " in: %s:%d", \ | ||||
| @@ -0,0 +1,452 @@ | |||||
| #define _CRT_SECURE_NO_WARNINGS | |||||
| #include <stdio.h> | |||||
| #include <string.h> | |||||
| #include "./types.hpp" | |||||
| u32 hm_hash(u32 u); | |||||
| inline bool hm_objects_match(u32 a, u32 b); | |||||
| struct Key; | |||||
| u32 hm_hash(Key u); | |||||
| inline bool hm_objects_match(Key a, Key b); | |||||
| #define ZoneScoped | |||||
| #define ZoneScopedN(name) | |||||
| #include "./print.hpp" | |||||
| #include "./testing.hpp" | |||||
| #include "./bucket_allocator.hpp" | |||||
| #include "./error.hpp" | |||||
| #include "./hooks.hpp" | |||||
| #include "./hashmap.hpp" | |||||
| #include "./error.hpp" | |||||
| u32 hm_hash(u32 u) { | |||||
| return ((u64)u * 2654435761) % 4294967296; | |||||
| } | |||||
| inline bool hm_objects_match(u32 a, u32 b) { | |||||
| return a == b; | |||||
| } | |||||
| struct Key { | |||||
| int x; | |||||
| int y; | |||||
| int z; | |||||
| }; | |||||
| u32 hm_hash(Key u) { | |||||
| return ((u.y ^ (u.x << 1)) >> 1) ^ u.z; | |||||
| } | |||||
| inline bool hm_objects_match(Key a, Key b) { | |||||
| return a.x == b.x | |||||
| && a.y == b.y | |||||
| && a.z == b.z; | |||||
| } | |||||
| auto print_dots(FILE* f) -> u32 { | |||||
| return print_to_file(f, "..."); | |||||
| } | |||||
| proc is_sorted = [](Array_List<s32> list) -> bool { | |||||
| for (u32 i = 0; i < list.count - 1; ++i) { | |||||
| if (list.data[i] > list.data[i+1]) | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| }; | |||||
| proc is_sorted_vp = [](Array_List<void*> list) -> bool { | |||||
| for (u32 i = 0; i < list.count - 1; ++i) { | |||||
| if (list.data[i] > list.data[i+1]) | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| }; | |||||
| auto test_printer() -> void { | |||||
| u32 arr[] = {1,2,3,4,1,1,3}; | |||||
| f32 f_arr[] = {1.1,2.1,3.2}; | |||||
| register_printer("dots", print_dots, Printer_Function_Type::_void); | |||||
| u32 u1 = -1; | |||||
| u64 u2 = -1; | |||||
| char* str; | |||||
| print_to_string(&str, " - %{dots[5]} %{->} <> %{->,2}\n", &u1, &arr, nullptr); | |||||
| print("---> %{->char}", str); | |||||
| print(" - %{dots[3]}\n"); | |||||
| print(" - %{u32} %{u64}\n", u1, u2); | |||||
| print(" - %{u32} %{u32} %{u32}\n", 2, 5, 7); | |||||
| print(" - %{f32} %{f32} %{f32}\n", 2.0, 5.0, 7.0); | |||||
| print(" - %{u32} %{bool} %{->char}\n", 2, true, "hello"); | |||||
| print(" - %{f32[3]}\n", f_arr); | |||||
| print(" - %{f32,3}\n", 44.9, 55.1, 66.2); | |||||
| print(" - %{u32[5]}\n", arr); | |||||
| print(" - %{u32[*]}\n", arr, 4); | |||||
| print(" - %{u32,5}\n", 1,2,3,4,1,2); | |||||
| print(" - %{unknown%d}\n", 1); | |||||
| print(" - %{s32,3}\n", -1,200,-300); | |||||
| print(" - %{->} <> %{->,2}\n", &u1, &arr, nullptr); | |||||
| print("%{->char}%{->char}%{->char}", | |||||
| true ? "general " : "", | |||||
| false ? "validation " : "", | |||||
| false ? "performance " : ""); | |||||
| // print("%{->char}%{->char}\n\n", "hallo",""); | |||||
| } | |||||
| auto test_hm() -> void { | |||||
| Hash_Map<u32, u32> h1; | |||||
| h1.alloc(); | |||||
| defer { h1.dealloc(); }; | |||||
| h1.set_object(1, 2); | |||||
| h1.set_object(2, 4); | |||||
| h1.set_object(3, 6); | |||||
| h1.set_object(4, 8); | |||||
| assert(h1.key_exists(1), "key shoud exist"); | |||||
| assert(h1.key_exists(2), "key shoud exist"); | |||||
| assert(h1.key_exists(3), "key shoud exist"); | |||||
| assert(h1.key_exists(4), "key shoud exist"); | |||||
| assert(!h1.key_exists(5), "key shoud not exist"); | |||||
| assert(h1.get_object(1) == 2, "value should be correct"); | |||||
| assert(h1.get_object(2) == 4, "value should be correct"); | |||||
| assert(h1.get_object(3) == 6, "value should be correct"); | |||||
| assert(h1.get_object(4) == 8, "value should be correct"); | |||||
| Hash_Map<Key, u32> h2; | |||||
| h2.alloc(); | |||||
| defer { h2.dealloc(); }; | |||||
| h2.set_object({.x = 1, .y = 2, .z = 3}, 1); | |||||
| h2.set_object({.x = 3, .y = 3, .z = 3}, 3); | |||||
| assert(h2.key_exists({.x = 1, .y = 2, .z = 3}), "key shoud exist"); | |||||
| assert(h2.key_exists({.x = 3, .y = 3, .z = 3}), "key shoud exist"); | |||||
| assert(h2.get_object({.x = 1, .y = 2, .z = 3}) == 1, "value should be correct"); | |||||
| assert(h2.get_object({.x = 3, .y = 3, .z = 3}) == 3, "value should be correct"); | |||||
| h2.for_each([] (Key k, u32 v, u32 i) { | |||||
| print("%{s32} %{u32} %{u32}\n", k.x, v, i); | |||||
| }); | |||||
| } | |||||
| proc test_array_lists_adding_and_removing() -> testresult { | |||||
| // test adding and removing | |||||
| Array_List<s32> list; | |||||
| list.alloc(); | |||||
| defer { | |||||
| list.dealloc(); | |||||
| }; | |||||
| list.append(1); | |||||
| list.append(2); | |||||
| list.append(3); | |||||
| list.append(4); | |||||
| assert_equal_int(list.count, 4); | |||||
| list.remove_index(0); | |||||
| assert_equal_int(list.count, 3); | |||||
| assert_equal_int(list[0], 4); | |||||
| assert_equal_int(list[1], 2); | |||||
| assert_equal_int(list[2], 3); | |||||
| list.remove_index(2); | |||||
| assert_equal_int(list.count, 2); | |||||
| assert_equal_int(list[0], 4); | |||||
| assert_equal_int(list[1], 2); | |||||
| return pass; | |||||
| } | |||||
| proc test_array_lists_sorting() -> testresult { | |||||
| // | |||||
| // | |||||
| // Test simple numbers | |||||
| // | |||||
| // | |||||
| Array_List<s32> list; | |||||
| list.alloc(); | |||||
| defer { | |||||
| list.dealloc(); | |||||
| }; | |||||
| list.append(1); | |||||
| list.append(2); | |||||
| list.append(3); | |||||
| list.append(4); | |||||
| list.sort(); | |||||
| assert_equal_int(is_sorted(list), true); | |||||
| list.append(4); | |||||
| list.append(2); | |||||
| list.append(1); | |||||
| assert_equal_int(is_sorted(list), false); | |||||
| list.sort(); | |||||
| assert_equal_int(is_sorted(list), true); | |||||
| list.clear(); | |||||
| list.extend({ | |||||
| 8023, 7529, 2392, 7110, | |||||
| 3259, 2484, 9695, 2199, | |||||
| 6729, 9009, 8429, 7208}); | |||||
| assert_equal_int(is_sorted(list), false); | |||||
| list.sort(); | |||||
| assert_equal_int(is_sorted(list), true); | |||||
| // | |||||
| // | |||||
| // Test adding and removing | |||||
| // | |||||
| // | |||||
| Array_List<s32> list1; | |||||
| list1.alloc(); | |||||
| defer { | |||||
| list1.dealloc(); | |||||
| }; | |||||
| list1.append(1); | |||||
| list1.append(2); | |||||
| list1.append(3); | |||||
| list1.append(4); | |||||
| list1.sort(); | |||||
| assert_equal_int(list1.count, 4); | |||||
| assert_equal_int(list1[0], 1); | |||||
| assert_equal_int(list1[1], 2); | |||||
| assert_equal_int(list1[2], 3); | |||||
| assert_equal_int(list1[3], 4); | |||||
| assert_equal_int(is_sorted(list1), true); | |||||
| list1.append(0); | |||||
| list1.append(5); | |||||
| assert_equal_int(list1.count, 6); | |||||
| list1.sort(); | |||||
| assert_equal_int(list1[0], 0); | |||||
| assert_equal_int(list1[1], 1); | |||||
| assert_equal_int(list1[2], 2); | |||||
| assert_equal_int(list1[3], 3); | |||||
| assert_equal_int(list1[4], 4); | |||||
| assert_equal_int(list1[5], 5); | |||||
| assert_equal_int(is_sorted(list1), true); | |||||
| // | |||||
| // | |||||
| // | |||||
| // | |||||
| // pointer list | |||||
| Array_List<void*> al; | |||||
| al.alloc(); | |||||
| defer { | |||||
| al.dealloc(); | |||||
| }; | |||||
| al.append((void*)0x1703102F100); | |||||
| al.append((void*)0x1703102F1D8); | |||||
| al.append((void*)0x1703102F148); | |||||
| al.append((void*)0x1703102F190); | |||||
| al.append((void*)0x1703102F190); | |||||
| al.append((void*)0x1703102F1D8); | |||||
| assert_equal_int(is_sorted_vp(al), false); | |||||
| al.sort(); | |||||
| assert_equal_int(is_sorted_vp(al), true); | |||||
| assert_not_equal_int(al.sorted_find((void*)0x1703102F100), -1); | |||||
| assert_not_equal_int(al.sorted_find((void*)0x1703102F1D8), -1); | |||||
| assert_not_equal_int(al.sorted_find((void*)0x1703102F148), -1); | |||||
| assert_not_equal_int(al.sorted_find((void*)0x1703102F190), -1); | |||||
| assert_not_equal_int(al.sorted_find((void*)0x1703102F190), -1); | |||||
| assert_not_equal_int(al.sorted_find((void*)0x1703102F1D8), -1); | |||||
| return pass; | |||||
| } | |||||
| proc test_array_lists_searching() -> testresult { | |||||
| Array_List<s32> list1; | |||||
| list1.alloc(); | |||||
| defer { | |||||
| list1.dealloc(); | |||||
| }; | |||||
| list1.append(1); | |||||
| list1.append(2); | |||||
| list1.append(3); | |||||
| list1.append(4); | |||||
| s32 index = list1.sorted_find(3); | |||||
| assert_equal_int(index, 2); | |||||
| index = list1.sorted_find(1); | |||||
| assert_equal_int(index, 0); | |||||
| index = list1.sorted_find(5); | |||||
| assert_equal_int(index, -1); | |||||
| return pass; | |||||
| } | |||||
| proc test_bucket_allocator() -> testresult { | |||||
| Bucket_Allocator<s32> ba; | |||||
| ba.alloc(); | |||||
| defer { | |||||
| ba.dealloc(); | |||||
| }; | |||||
| s32* s1 = ba.allocate(); | |||||
| s32* s2 = ba.allocate(); | |||||
| s32* s3 = ba.allocate(); | |||||
| s32* s4 = ba.allocate(); | |||||
| s32* s5 = ba.allocate(); | |||||
| *s1 = 1; | |||||
| *s2 = 2; | |||||
| *s3 = 3; | |||||
| *s4 = 4; | |||||
| *s5 = 5; | |||||
| s32 wrong_answers = 0; | |||||
| s32 counter = 1; | |||||
| ba.for_each([&](s32* s) -> void { | |||||
| if(counter != *s) | |||||
| ++wrong_answers; | |||||
| ++counter; | |||||
| }); | |||||
| assert_equal_int(wrong_answers, 0); | |||||
| Bucket_Allocator<s32> ba2; | |||||
| ba2.alloc(); | |||||
| defer { | |||||
| ba2.dealloc(); | |||||
| }; | |||||
| s1 = ba2.allocate(); | |||||
| s2 = ba2.allocate(); | |||||
| s3 = ba2.allocate(); | |||||
| s32* s3_copy = ba2.allocate(); | |||||
| s32* s3_copy2 = ba2.allocate(); | |||||
| s32* s3_copy3 = ba2.allocate(); | |||||
| *s3_copy = 3; | |||||
| ba2.free_object(s3_copy); | |||||
| s4 = ba2.allocate(); | |||||
| ba2.free_object(s3_copy2); | |||||
| s5 = ba2.allocate(); | |||||
| ba2.free_object(s3_copy3); | |||||
| *s1 = 1; | |||||
| *s2 = 2; | |||||
| *s3 = 3; | |||||
| *s4 = 4; | |||||
| *s5 = 5; | |||||
| wrong_answers = 0; | |||||
| counter = 1; | |||||
| ba2.for_each([&](s32* s) -> void { | |||||
| if(counter != *s) | |||||
| ++wrong_answers; | |||||
| ++counter; | |||||
| }); | |||||
| assert_equal_int(wrong_answers, 0); | |||||
| return pass; | |||||
| } | |||||
| auto test_array_list_sort_many() -> testresult { | |||||
| Array_List<s32> list; | |||||
| list.alloc(); | |||||
| defer { | |||||
| list.dealloc(); | |||||
| }; | |||||
| for (int i = 0; i < 10000; ++i) { | |||||
| list.append(rand()); | |||||
| } | |||||
| assert_equal_int(is_sorted(list), false); | |||||
| list.sort(); | |||||
| assert_equal_int(is_sorted(list), true); | |||||
| for (int i = 0; i < 10000; ++i) { | |||||
| assert_not_equal_int(list.sorted_find(list.data[i]), -1); | |||||
| } | |||||
| list.clear(); | |||||
| for (int i = 0; i < 1111; ++i) { | |||||
| list.append(rand()); | |||||
| } | |||||
| assert_equal_int(is_sorted(list), false); | |||||
| list.sort(); | |||||
| assert_equal_int(is_sorted(list), true); | |||||
| for (int i = 0; i < 1111; ++i) { | |||||
| assert_not_equal_int(list.sorted_find(list.data[i]), -1); | |||||
| } | |||||
| list.clear(); | |||||
| for (int i = 0; i < 3331; ++i) { | |||||
| list.append(rand()); | |||||
| } | |||||
| assert_equal_int(is_sorted(list), false); | |||||
| list.sort(); | |||||
| assert_equal_int(is_sorted(list), true); | |||||
| for (int i = 0; i < 3331; ++i) { | |||||
| assert_not_equal_int(list.sorted_find(list.data[i]), -1); | |||||
| } | |||||
| return pass; | |||||
| } | |||||
| s32 main(s32, char**) { | |||||
| init_printer(); | |||||
| testresult result; | |||||
| invoke_test(test_array_lists_adding_and_removing); | |||||
| invoke_test(test_array_lists_sorting); | |||||
| invoke_test(test_array_lists_searching); | |||||
| invoke_test(test_array_list_sort_many); | |||||
| invoke_test(test_bucket_allocator); | |||||
| return 0; | |||||
| } | |||||
| @@ -6,11 +6,11 @@ | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include "platform.hpp" | |||||
| #ifdef FTB_WINDOWS | #ifdef FTB_WINDOWS | ||||
| #include <Windows.h> | #include <Windows.h> | ||||
| #endif | #endif | ||||
| #include "platform.hpp" | |||||
| #include "hashmap.hpp" | #include "hashmap.hpp" | ||||
| #include "hooks.hpp" | #include "hooks.hpp" | ||||
| @@ -443,7 +443,6 @@ auto print_Str(FILE* f, String* str) -> s32 { | |||||
| auto print_str_line(FILE* f, char* str) -> s32 { | auto print_str_line(FILE* f, char* str) -> s32 { | ||||
| u32 length = 0; | u32 length = 0; | ||||
| char* str_cpy = str; | |||||
| while (str[length] != '\0') { | while (str[length] != '\0') { | ||||
| if (str[length] == '\n') | if (str[length] == '\n') | ||||
| break; | break; | ||||
| @@ -1,138 +0,0 @@ | |||||
| #define _CRT_SECURE_NO_WARNINGS | |||||
| #include <stdio.h> | |||||
| #include <string.h> | |||||
| #include "./types.hpp" | |||||
| u32 hm_hash(u32 u); | |||||
| inline bool hm_objects_match(u32 a, u32 b); | |||||
| struct Key; | |||||
| u32 hm_hash(Key u); | |||||
| inline bool hm_objects_match(Key a, Key b); | |||||
| #define ZoneScoped | |||||
| #define ZoneScopedN(name) | |||||
| #include "./error.hpp" | |||||
| #include "./hooks.hpp" | |||||
| #include "./hashmap.hpp" | |||||
| #include "./error.hpp" | |||||
| #include "./print.hpp" | |||||
| u32 hm_hash(u32 u) { | |||||
| return ((u64)u * 2654435761) % 4294967296; | |||||
| } | |||||
| inline bool hm_objects_match(u32 a, u32 b) { | |||||
| return a == b; | |||||
| } | |||||
| struct Key { | |||||
| int x; | |||||
| int y; | |||||
| int z; | |||||
| }; | |||||
| u32 hm_hash(Key u) { | |||||
| return ((u.y ^ (u.x << 1)) >> 1) ^ u.z; | |||||
| } | |||||
| inline bool hm_objects_match(Key a, Key b) { | |||||
| return a.x == b.x | |||||
| && a.y == b.y | |||||
| && a.z == b.z; | |||||
| } | |||||
| auto print_dots(FILE* f) -> u32 { | |||||
| return print_to_file(f, "..."); | |||||
| } | |||||
| auto test_printer() -> void { | |||||
| u32 arr[] = {1,2,3,4,1,1,3}; | |||||
| f32 f_arr[] = {1.1,2.1,3.2}; | |||||
| register_printer("dots", print_dots, Printer_Function_Type::_void); | |||||
| u32 u1 = -1; | |||||
| u64 u2 = -1; | |||||
| char* str; | |||||
| print_to_string(&str, " - %{dots[5]} %{->} <> %{->,2}\n", &u1, &arr, nullptr); | |||||
| print("---> %{->char}", str); | |||||
| print(" - %{dots[3]}\n"); | |||||
| print(" - %{u32} %{u64}\n", u1, u2); | |||||
| print(" - %{u32} %{u32} %{u32}\n", 2, 5, 7); | |||||
| print(" - %{f32} %{f32} %{f32}\n", 2.0, 5.0, 7.0); | |||||
| print(" - %{u32} %{bool} %{->char}\n", 2, true, "hello"); | |||||
| print(" - %{f32[3]}\n", f_arr); | |||||
| print(" - %{f32,3}\n", 44.9, 55.1, 66.2); | |||||
| print(" - %{u32[5]}\n", arr); | |||||
| print(" - %{u32[*]}\n", arr, 4); | |||||
| print(" - %{u32,5}\n", 1,2,3,4,1,2); | |||||
| print(" - %{unknown%d}\n", 1); | |||||
| print(" - %{s32,3}\n", -1,200,-300); | |||||
| print(" - %{->} <> %{->,2}\n", &u1, &arr, nullptr); | |||||
| print("%{->char}%{->char}%{->char}", | |||||
| true ? "general " : "", | |||||
| false ? "validation " : "", | |||||
| false ? "performance " : ""); | |||||
| // print("%{->char}%{->char}\n\n", "hallo",""); | |||||
| } | |||||
| auto test_hm() -> void { | |||||
| Hash_Map<u32, u32> h1; | |||||
| h1.alloc(); | |||||
| defer { h1.dealloc(); }; | |||||
| h1.set_object(1, 2); | |||||
| h1.set_object(2, 4); | |||||
| h1.set_object(3, 6); | |||||
| h1.set_object(4, 8); | |||||
| assert(h1.key_exists(1), "key shoud exist"); | |||||
| assert(h1.key_exists(2), "key shoud exist"); | |||||
| assert(h1.key_exists(3), "key shoud exist"); | |||||
| assert(h1.key_exists(4), "key shoud exist"); | |||||
| assert(!h1.key_exists(5), "key shoud not exist"); | |||||
| assert(h1.get_object(1) == 2, "value should be correct"); | |||||
| assert(h1.get_object(2) == 4, "value should be correct"); | |||||
| assert(h1.get_object(3) == 6, "value should be correct"); | |||||
| assert(h1.get_object(4) == 8, "value should be correct"); | |||||
| Hash_Map<Key, u32> h2; | |||||
| h2.alloc(); | |||||
| defer { h2.dealloc(); }; | |||||
| h2.set_object({.x = 1, .y = 2, .z = 3}, 1); | |||||
| h2.set_object({.x = 3, .y = 3, .z = 3}, 3); | |||||
| assert(h2.key_exists({.x = 1, .y = 2, .z = 3}), "key shoud exist"); | |||||
| assert(h2.key_exists({.x = 3, .y = 3, .z = 3}), "key shoud exist"); | |||||
| assert(h2.get_object({.x = 1, .y = 2, .z = 3}) == 1, "value should be correct"); | |||||
| assert(h2.get_object({.x = 3, .y = 3, .z = 3}) == 3, "value should be correct"); | |||||
| h2.for_each([] (Key k, u32 v, u32 i) { | |||||
| print("%{s32} %{u32} %{u32}\n", k.x, v, i); | |||||
| }); | |||||
| } | |||||
| s32 main(s32 argc, char* argv[]) { | |||||
| init_printer(); | |||||
| test_hm(); | |||||
| print("done."); | |||||
| return 0; | |||||
| } | |||||
| @@ -2,7 +2,7 @@ | |||||
| typedef s32 testresult; | typedef s32 testresult; | ||||
| #define epsilon 2.2204460492503131E-16 | |||||
| #define float_epsilon 2.2204460492503131E-16 | |||||
| #define pass 1 | #define pass 1 | ||||
| #define fail 0 | #define fail 0 | ||||
| @@ -57,13 +57,13 @@ typedef s32 testresult; | |||||
| } \ | } \ | ||||
| #define assert_equal_f64(variable, value) \ | #define assert_equal_f64(variable, value) \ | ||||
| if (fabsl((f64)variable - (f64)value) > epsilon) { \ | |||||
| if (fabsl((f64)variable - (f64)value) > float_epsilon) { \ | |||||
| print_assert_equal_fail(variable, value, f64, "%{f64}"); \ | print_assert_equal_fail(variable, value, f64, "%{f64}"); \ | ||||
| return fail; \ | return fail; \ | ||||
| } | } | ||||
| #define assert_not_equal_f64(variable, value) \ | #define assert_not_equal_f64(variable, value) \ | ||||
| if (fabsl((f64)variable - (f64)value) <= epsilon) { \ | |||||
| if (fabsl((f64)variable - (f64)value) <= float_epsilon) { \ | |||||
| print_assert_not_equal_fail(variable, value, f64, "%{f64}"); \ | print_assert_not_equal_fail(variable, value, f64, "%{f64}"); \ | ||||
| return fail; \ | return fail; \ | ||||
| } | } | ||||