| @@ -2,3 +2,4 @@ | |||
| *.report | |||
| /ftb | |||
| vgcore.* | |||
| tests/ftb | |||
| @@ -1,9 +1,82 @@ | |||
| #pragma once | |||
| #include <stdlib.h> | |||
| #include <initializer_list> | |||
| #ifdef FTB_INTERNAL_DEBUG | |||
| # include <stdio.h> | |||
| #endif | |||
| #include "types.hpp" | |||
| #include "macros.hpp" | |||
| template <typename type> | |||
| 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<type> create_from(std::initializer_list<type> l) { | |||
| Stack_Array_List<type> ret(l.size()); | |||
| for (type t : l) { | |||
| ret.data[ret.count++] = t; | |||
| } | |||
| return ret; | |||
| } | |||
| void extend(std::initializer_list<type> 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 <typename type> | |||
| struct Array_List { | |||
| type* data; | |||
| @@ -180,24 +253,64 @@ struct Array_List { | |||
| template <typename type> | |||
| struct Auto_Array_List : public Array_List<type> { | |||
| 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<type> l) { | |||
| this->alloc(l.size()); | |||
| for (type e : l) { | |||
| this->append(e); | |||
| } | |||
| } | |||
| Auto_Array_List(std::initializer_list<type> l) { | |||
| this->alloc(l.size()); | |||
| for (type e : l) { | |||
| this->append(e); | |||
| } | |||
| } | |||
| ~Auto_Array_List() { | |||
| free(this->data); | |||
| this->data = nullptr; | |||
| } | |||
| }; | |||
| template <typename type> | |||
| struct Queue { | |||
| Array_List<type> 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(); | |||
| } | |||
| }; | |||
| @@ -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 | |||
| @@ -146,6 +146,128 @@ auto test_hm() -> void { | |||
| }); | |||
| } | |||
| proc test_stack_array_lists() -> testresult { | |||
| Stack_Array_List<int> 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<int> 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; | |||
| } | |||