diff --git a/.gitignore b/.gitignore index 290dfbd..aa15254 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.report /ftb vgcore.* +tests/ftb diff --git a/arraylist.hpp b/arraylist.hpp index 1950a41..297d31a 100644 --- a/arraylist.hpp +++ b/arraylist.hpp @@ -1,9 +1,82 @@ #pragma once #include #include + +#ifdef FTB_INTERNAL_DEBUG +# include +#endif + #include "types.hpp" #include "macros.hpp" +template +struct Stack_Array_List { + type* data; + u32 length; + u32 count; + + Stack_Array_List(u32 length) { + data = (type*)alloca(length); +#ifdef FTB_INTERNAL_DEBUG + if (data == nullptr) { + fprintf(stderr, "ERROR: alloca did return nullptr \n"); + } +#endif + this->length = length; + this->count = 0; + } + + static Stack_Array_List create_from(std::initializer_list l) { + Stack_Array_List ret(l.size()); + + for (type t : l) { + ret.data[ret.count++] = t; + } + return ret; + } + + void extend(std::initializer_list l) { + for (type e : l) { + append(e); + } + } + + void clear() { + count = 0; + } + + type* begin() { + return data; + } + + type* end() { + return data+(count); + } + + void remove_index(u32 index) { +#ifdef FTB_INTERNAL_DEBUG + if (index >= count) + fprintf(stderr, "ERROR: removing index that is not in use\n"); +#endif + data[index] = data[--count]; + } + + void append(type element) { +#ifdef FTB_INTERNAL_DEBUG + if (count == length) { + fprintf(stderr, "ERROR: Stack_Array_List is full!\n"); + } +#endif + data[count] = element; + count++; + } + + type& operator[](u32 index) { + return data[index]; + } + +}; + template struct Array_List { type* data; @@ -180,24 +253,64 @@ struct Array_List { template struct Auto_Array_List : public Array_List { + Auto_Array_List(u32 length) { + this->alloc(length); + } - Auto_Array_List(u32 length) { - this->alloc(length); - } + Auto_Array_List() { + this->alloc(16); + } - Auto_Array_List() { - this->alloc(16); + Auto_Array_List(std::initializer_list l) { + this->alloc(l.size()); + for (type e : l) { + this->append(e); } + } - Auto_Array_List(std::initializer_list l) { - this->alloc(l.size()); - for (type e : l) { - this->append(e); - } - } + ~Auto_Array_List() { + free(this->data); + this->data = nullptr; + } +}; + +template +struct Queue { + Array_List arr_list; + u32 next_index; + + void alloc(u32 initial_capacity = 16) { + next_index = 0; + arr_list.alloc(initial_capacity); + } - ~Auto_Array_List() { - free(this->data); - this->data = nullptr; + void dealloc() { + arr_list.dealloc(); + } + + void push_back(type e) { + arr_list.append(e); + } + + type get_next() { +#ifdef FTB_INTERNAL_DEBUG + if (next_index >= arr_list.length) { + fprintf(stderr, "ERROR: Out of bounds access in queue\n"); } +#endif + return arr_list.data[next_index++]; + } + + bool is_empty() { + return next_index == arr_list.count; + } + + int get_count() { + return arr_list.count - next_index; + } + + void clear() { + next_index = 0; + arr_list.clear(); + } }; diff --git a/tests/build.sh b/tests/build.sh index 5037ef5..59910a1 100755 --- a/tests/build.sh +++ b/tests/build.sh @@ -5,12 +5,12 @@ pushd $SCRIPTPATH > /dev/null # _DEBUG # time g++ -fpermissive src/main.cpp -g -o ./bin/slime --std=c++17 || exit 1 time clang++ -D_DEBUG -D_PROFILING -fpermissive main.cpp -g -o ./ftb --std=c++17 || exit 1 -time clang++ -D_DEBUG -D_PROFILING -fpermissive cpu_info.cpp -g -o ./cpu_info --std=c++17 || exit 1 +# time clang++ -D_DEBUG -D_PROFILING -fpermissive cpu_info.cpp -g -o ./cpu_info --std=c++17 || exit 1 echo "" # time valgrind --leak-check=full ./ftb time ./ftb -time ./cpu_info +# time ./cpu_info popd > /dev/null unset TIMEFORMAT diff --git a/tests/ftb b/tests/ftb deleted file mode 100755 index 205d22b..0000000 Binary files a/tests/ftb and /dev/null differ diff --git a/tests/main.cpp b/tests/main.cpp index fc0ffaa..3407d89 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -146,6 +146,128 @@ auto test_hm() -> void { }); } +proc test_stack_array_lists() -> testresult { + Stack_Array_List list(20); + + assert_equal_int(list.count, 0); + assert_equal_int(list.length, 20); + assert(list.data != NULL, "list should have some data allocated"); + + // test sum of empty list + int sum = 0; + int iter = 0; + for (auto e : list) { + sum += e; + iter++; + } + assert_equal_int(sum, 0); + assert_equal_int(iter, 0); + + // append some elements + list.append(1); + list.append(2); + list.append(3); + list.append(4); + + assert_equal_int(list.count, 4); + assert_equal_int(list.length, 20); + + // test sum again + sum = 0; + iter = 0; + for (auto e : list) { + sum += e; + iter++; + } + assert_equal_int(sum, 10); + assert_equal_int(iter, 4); + + // bracketed access + list[0] = 11; + list[1] = 3; + list[2] = 2; + list.append(5); + + // test sum again + sum = 0; + iter = 0; + for (auto e : list) { + sum += e; + ++iter; + } + assert_equal_int(sum, 25); + assert_equal_int(iter, 5); + + // assert memory correct + assert_equal_int(list.data[0], 11); + assert_equal_int(list.data[1], 3); + assert_equal_int(list.data[2], 2); + assert_equal_int(list.data[3], 4); + assert_equal_int(list.data[4], 5); + + // removing some indices + list.remove_index(4); + + // test sum again + sum = 0; + iter = 0; + for (auto e : list) { + sum += e; + ++iter; + } + assert_equal_int(sum, 20); + assert_equal_int(iter, 4); + + // removing some indices + list.remove_index(1); + list.remove_index(0); + + // test sum again + sum = 0; + iter = 0; + for (auto e : list) { + sum += e; + ++iter; + } + + assert_equal_int(sum, 6); + assert_equal_int(iter, 2); + + return pass; +} + +proc test_queue() -> testresult { + Queue q; + q.alloc(4); + + assert(q.is_empty(), "queue should start empty"); + assert_equal_int(q.get_count(), 0); + + q.push_back(1); + q.push_back(2); + q.push_back(3); + + assert_equal_int(q.get_count(), 3); + + assert_equal_int(q.get_next(), 1); + assert_equal_int(q.get_count(), 2); + assert(!q.is_empty(), "should not be empty"); + + assert_equal_int(q.get_next(), 2); + assert_equal_int(q.get_count(), 1); + q.push_back(4); + assert_equal_int(q.get_count(), 2); + + assert_equal_int(q.get_next(), 3); + assert_equal_int(q.get_count(), 1); + assert(!q.is_empty(), "should not be empty"); + + assert_equal_int(q.get_next(), 4); + assert(q.is_empty(), "should be empty"); + assert_equal_int(q.get_count(), 0); + + return pass; +} proc test_array_lists_adding_and_removing() -> testresult { // test adding and removing @@ -446,7 +568,9 @@ s32 main(s32, char**) { invoke_test(test_array_lists_sorting); invoke_test(test_array_lists_searching); invoke_test(test_array_list_sort_many); + invoke_test(test_stack_array_lists); invoke_test(test_bucket_allocator); + invoke_test(test_queue); return 0; }