diff --git a/array.hpp b/array.hpp index b32ede6..3ca712f 100644 --- a/array.hpp +++ b/array.hpp @@ -62,10 +62,6 @@ struct Array { ARRAY_ASSERT(index >= 0 && index < len); return data[index]; } - T &operator[](long long index) { - ARRAY_ASSERT(index >= 0 && index < len); - return data[index]; - } bool is_first(T &item) { return &item == first(); } bool is_last(T &item) { return &item == last(); } @@ -81,7 +77,7 @@ struct Array { return (int)offset; } - void add(T item) { + void add(const T &item) { try_growing(); data[len++] = item; } @@ -222,7 +218,7 @@ struct Array { len = cap = 0; } - Array exact_copy(ARRAY_Allocator allocator) { + Array copy(ARRAY_Allocator allocator) { Array result = {}; result.allocator = allocator; result.reserve(cap); @@ -234,7 +230,7 @@ struct Array { Array tight_copy(ARRAY_Allocator allocator) { Array result = {}; - ARRAY_ALLOCATOR_CODE(result.allocator = allocator;) + result.allocator = allocator; result.reserve(len); ARRAY_MemoryMove(result.data, data, sizeof(T) * len); diff --git a/build.bat b/build.bat index 9847a6e..4ba1e83 100644 --- a/build.bat +++ b/build.bat @@ -14,6 +14,13 @@ set RELEASE_LINE=%RELEASE% %WRN% %COMMON% -link -incremental:no %LINK_RELEASE% mkdir build cd build + +cl.exe -Fe:test_table.exe ../test/test_table.cpp %DEBUG_LINE% +if %errorlevel% neq 0 exit /b %errorlevel% +test_table.exe +if %errorlevel% neq 0 exit /b %errorlevel% + + cl.exe -Fe:test_array.exe ../test/test_array.cpp %DEBUG_LINE% if %errorlevel% neq 0 exit /b %errorlevel% test_array.exe diff --git a/core.h b/core.h index 61d0a5b..24fb898 100644 --- a/core.h +++ b/core.h @@ -16,6 +16,8 @@ #include "defer.hpp" #define TABLE_ASSERT IO_Assert #define TABLE_ALLOCATOR_TYPE M_Allocator + #define TABLE_ALLOCATE(allocator, size) M_Alloc(allocator, size) + #define TABLE_DEALLOCATE(allocator, p) M_Dealloc(allocator, p) #define TABLE_SET_DEFAULT_ALLOCATOR \ if (!allocator.p) allocator = M_GetSystemAllocator(); #include "table.hpp" diff --git a/table.hpp b/table.hpp index 19b0538..4683322 100644 --- a/table.hpp +++ b/table.hpp @@ -57,6 +57,7 @@ TABLE_PRIVATE_FUNCTION uint64_t TABLE__HashBytes(void *data, unsigned size) { #endif #define TABLE__WRAP_AROUND_POWER_OF_2(x, pow2) (((x) & ((pow2)-1llu))) +#define TABLE__IS_POW2(x) (((x) & ((x)-1)) == 0) TABLE_PRIVATE_FUNCTION int TABLE_CStringLen(char *str) { int i = 0; @@ -79,11 +80,24 @@ struct Table { size_t len, cap; Entry *values; + static const size_t max_load_factor = 80; + static const size_t min_load_factor = 50; + static const size_t significant_distance = 8; + + // load factor calculation was rearranged + // to get rid of division: + //> 100 * len / cap = load_factor + //> len * 100 = load_factor * cap + inline bool reached_load_factor(size_t lfactor) { + return (len + 1) * 100 >= lfactor * cap; + } + inline bool is_empty(Entry *entry) { return entry->hash == 0; } inline bool is_occupied(Entry *entry) { return entry->hash != 0; } void reserve(size_t size) { TABLE_ASSERT(size > cap && "New size is smaller then original size"); + TABLE_ASSERT(TABLE__IS_POW2(size)); TABLE_SET_DEFAULT_ALLOCATOR; Entry *old_values = values; @@ -132,14 +146,6 @@ struct Table { TABLE_ASSERT(!"Invalid codepath"); } - // load factor calculation was rearranged - // to get rid of division: - //> 100 * len / cap = load_factor - //> len * 100 = load_factor * cap - inline bool reached_load_factor(size_t lfactor) { - return (len + 1) * 100 >= lfactor * cap; - } - void insert(uint64_t key, const Value &value) { if (reached_load_factor(max_load_factor)) { if (cap == 0) cap = 16; // 32 cause cap*2 @@ -189,6 +195,7 @@ struct Table { Entry *entry = get_table_entry(key); entry->hash = 0; entry->distance = 0; + len -= 1; } Value *get(uint64_t key) { @@ -218,12 +225,9 @@ struct Table { } void dealloc() { - COR_DEALLOCATE(allocator, values); + TABLE_DEALLOCATE(allocator, values); len = 0; cap = 0; values = 0; } - static const size_t max_load_factor = 80; - static const size_t min_load_factor = 50; - static const size_t significant_distance = 8; }; \ No newline at end of file diff --git a/test/test_array.cpp b/test/test_array.cpp index 9cc9297..83f1d32 100644 --- a/test/test_array.cpp +++ b/test/test_array.cpp @@ -112,11 +112,27 @@ void TestReverseLoop() { array.dealloc(); } +void TestCopy() { + MA_Scratch scratch; + auto a = GenArray(); + auto b = a.tight_copy(scratch); + auto c = a.copy(scratch); + + int i = 0; + For(b) IO_Assert(it == i++); + i = 0; + For(c) IO_Assert(it == i++); + + IO_Assert(b.cap == b.len && b.len == a.len); + IO_Assert(a.len == c.len && a.cap == c.cap); +} + int main() { TestExclusiveArenaBackedArray(); TestRemoveForLoop(); TestBasic(); TestReverseLoop(); + TestCopy(); return 0; } \ No newline at end of file diff --git a/test/test_table.cpp b/test/test_table.cpp new file mode 100644 index 0000000..9ae6d22 --- /dev/null +++ b/test/test_table.cpp @@ -0,0 +1,43 @@ +#include "../core.c" + +void TestSimpleInsertAndIntegrity() { + MA_Scratch scratch; + Table table = {scratch}; + table.reserve(64); + + for (uint64_t i = 0; i < 10000; i += 1) { + table.insert(i, i); + } + for (uint64_t i = 0; i < 10000; i += 1) { + uint64_t *v = table.get(i); + IO_Assert(*v == i); + } + IO_Assert(table.len == 10000); + IO_Assert(table.cap > table.len); + IO_Assert(MA_IS_POW2(table.cap)); + table.remove(32); + table.reset(); + table.dealloc(); +} + +void TestStrings() { + struct Data { + int a[32]; + int i; + }; + + Table table = {}; + table.puts("1", Data{{}, 1}); + table.puts("2", Data{{}, 2}); + table.puts("3", Data{{}, 3}); + + IO_Assert(table.gets("1")->i == 1); + IO_Assert(table.gets("2")->i == 2); + IO_Assert(table.gets("3")->i == 3); +} + +int main() { + TestSimpleInsertAndIntegrity(); + TestStrings(); + return 0; +} \ No newline at end of file