diff --git a/.vscode/launch.json b/.vscode/launch.json index 2b552f1..d56a9f9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,9 +5,9 @@ "version": "0.2.0", "configurations": [ { - "name": "Debug", "type": "gdb", "request": "launch", + "name": "Launch Program", "target": "./bin/tests", "cwd": "${workspaceRoot}", "valuesFormatting": "parseText", diff --git a/include/gp/containers/buffer.hpp b/include/gp/containers/buffer.hpp index 6f5bfd8..07a9823 100644 --- a/include/gp/containers/buffer.hpp +++ b/include/gp/containers/buffer.hpp @@ -75,6 +75,18 @@ namespace gp{ return *(begin_elem+offset); } + constexpr const T& operator[](std::size_t offset) const + { + if constexpr (gp_config::has_buffer_bounds) + { + gp_config::assertion( + offset < size(), + "Buffer bounds infringed" + ); + } + return *(begin_elem+offset); + } + optional> at(std::size_t offset) { auto elem = begin()+offset; diff --git a/include/gp/containers/dynarray.hpp b/include/gp/containers/dynarray.hpp index 6a3dd13..9895f85 100644 --- a/include/gp/containers/dynarray.hpp +++ b/include/gp/containers/dynarray.hpp @@ -172,6 +172,11 @@ namespace gp { data[sz].clear(); } + gp::buffer as_buffer() + { + return gp::buffer{(T*)data, (T*)data+sz}; + } + ~dynarray() { auto it = data; auto end = data + size(); diff --git a/include/gp/functional/function.hpp b/include/gp/functional/function.hpp index b5eb03c..389428d 100644 --- a/include/gp/functional/function.hpp +++ b/include/gp/functional/function.hpp @@ -82,6 +82,10 @@ namespace gp{ this->condestructor(data_size <= sizeof(data_ptr) ? (char*)&data_ptr : data_ptr, reinterpret_cast(&f)); } + /*function(ret f_ptr(args...)) + : function(f_ptr, nullopt) + {}*/ + template function(func f, nullopt_t alloc_v) : alloc(alloc_v) @@ -122,10 +126,6 @@ namespace gp{ ); } - function(ret f_ptr(args...)) - : function(f_ptr, nullopt) - {} - function(function&& rhs) : alloc(rhs.alloc) , invokator(rhs.invokator) diff --git a/include/gp/system/logging_segment.hpp b/include/gp/system/logging_segment.hpp index 87e97e5..d803d22 100644 --- a/include/gp/system/logging_segment.hpp +++ b/include/gp/system/logging_segment.hpp @@ -6,6 +6,8 @@ #include "gp/functional/optional.hpp" #include +#include +#include struct segment{ int16_t priority = 0; @@ -27,10 +29,10 @@ template struct static_logging_segment : virtual_logging_segment{ gp::dynarray data; gp::optional wrap_around; - gp::function on_destruct = +[](virtual_logging_segment&){}; + //gp::function on_destruct{[](virtual_logging_segment&){}, gp::nullopt}; ~static_logging_segment() { - on_destruct(*this); + //on_destruct(*this); } segment prepare_segment(gp::buffer name, gp::buffer text, int prio = 0) { @@ -64,11 +66,15 @@ struct static_logging_segment : virtual_logging_segment{ virtual size_t push_segment(gp::buffer name, gp::buffer text, int16_t prio = 0) { auto prepared = prepare_segment(name, text, prio); + + if(data.size() == data.capacity()) { + wrap_around = 0; + } if(wrap_around.has_value()) { size_t idx = wrap_around.value(); size_t override_prio = gp::min_of(data.begin(), data.end(), [](auto v){ return v.priority; }); - while(true) { + while(prio >= override_prio) { if(data[idx].priority == override_prio) { data[idx] = prepared; break; @@ -83,15 +89,20 @@ struct static_logging_segment : virtual_logging_segment{ return data.size()-1; } } + virtual void set_segment(gp::buffer name, gp::buffer text, int16_t prio = 0) { auto prepared = prepare_segment(name, text, prio); + auto seg = get_segment(prepared.name.as_buffer()); - if(auto seg = get_segment(name); seg.has_value()) { - seg.value() = prepared; - } else { - data.push_back(prepared); + if(seg.has_value()) { + seg.value().get() = prepared; + + return; } + + push_segment(prepared.name.as_buffer(), prepared.text.as_buffer(), prepared.priority); } + virtual gp::optional> get_segment(gp::buffer name) { decltype(segment{}.name) tname; auto it = name.begin(); @@ -106,11 +117,14 @@ struct static_logging_segment : virtual_logging_segment{ return gp::reference_wrapper(elem); } } + return gp::nullopt; } + virtual size_t size() { return data.size(); } + virtual segment& get_segment_by_idx(size_t idx) { return data[idx]; } diff --git a/tests.cpp b/tests.cpp index b668725..0d3cbc7 100644 --- a/tests.cpp +++ b/tests.cpp @@ -10,7 +10,7 @@ alignas(2048) gp::array static_mapper::store; gp::buddy<> static_mapper::impl = gp::buddy<>{store.begin().data, store.size()}; -static_logging_segment<32> logger; +static_logging_segment<128> logger; void log_failure(const char* failure) { log_segment("FAILURE", failure, std::numeric_limits::max()); @@ -51,6 +51,7 @@ int main() if(value) { std::cout << std::dec << test->name << " failed with "<< value << std::endl; + print_logs(); } } catch (gp::runtime_error err) { std::cout << test->name << " failed with an exception: " << err.what() << std::endl; @@ -68,6 +69,6 @@ int main() logger.clear(); failed += (value != 0); } - std::cout << std::dec << "Runned "< name{"FIRST TEST"}; const gp::buffer text{"FIRST TEST TEXT"}; + const gp::buffer new_text{"NEW TEST TEXT"}; static_logging_segment<4> logger; + gp_config::assertion(logger.size() == 0, "new logger not empty"); + + logger.push_segment(name, text); + + gp_config::assertion(logger.size() == 1, "should be 1 after insertion"); + + logger.set_segment(name, new_text); + + gp_config::assertion(logger.size() == 1, "should still be one as key is identical"); + return res; } }; append_test dummy_rduhk786f(new logging_test{}); + + +struct logging_test2 : public test_scaffold { + logging_test2() { + name = __FILE__ ":2"; + } + + + virtual int run() { + int res = 0; + + const gp::buffer name[5]{{"TEST 1"},{"TEST 2"},{"TEST 3"},{"TEST 4"},{"TEST 5"}}; + const gp::buffer texts[5] {{"NEW TEST TEXT 1"},{"NEW TEST TEXT 2"},{"NEW TEST TEXT 3"},{"NEW TEST TEXT 4"},{"NEW TEST TEXT 5"}}; + + static_logging_segment<4> logger; + + gp_config::assertion(logger.size() == 0, "new logger not empty"); + + for(auto i : {0,1,2,3,4}) { + logger.push_segment(name[i], texts[i]); + } + + gp_config::assertion(logger.size() <= 4, "Size should be capped at 4"); + gp_config::assertion(logger.size() == 4, "Size should be 4"); + + return res; + } +}; + +append_test dummy_sghgfg6f(new logging_test2{}); + + + +struct logging_test3 : public test_scaffold { + logging_test3() { + name = __FILE__ ":3"; + } + + + virtual int run() { + int res = 0; + + const gp::buffer name[5]{{"TEST 1"},{"TEST 2"},{"TEST 3"},{"TEST 4"},{"TEST 5"}}; + const gp::buffer texts[5] {{"NEW TEST TEXT 1"},{"NEW TEST TEXT 2"},{"NEW TEST TEXT 3"},{"NEW TEST TEXT 4"},{"NEW TEST TEXT 5"}}; + + static_logging_segment<4> logger; + + gp_config::assertion(logger.size() == 0, "new logger not empty"); + + for(auto i : {0,1,2,3,4}) { + logger.set_segment(name[i], texts[i]); + log_segment("new element", name[i].begin().data); + } + + log_segment("size", std::to_string(logger.size()).c_str()); + + gp_config::assertion(logger.size() <= 4, "Size should be capped at 4"); + gp_config::assertion(logger.size() == 4, "Size should be 4"); + + return res; + } +}; + +append_test dummy_dgiudfg6f(new logging_test3{}); + + + +struct logging_test4 : public test_scaffold { + logging_test4() { + name = __FILE__ ":4"; + } + + + virtual int run() { + int res = 0; + + const gp::buffer name[5]{{"TEST 1"},{"TEST 2"},{"TEST 3"},{"TEST 4"},{"TEST 5"}}; + const gp::buffer texts[5] {{"NEW TEST TEXT 1"},{"NEW TEST TEXT 2"},{"NEW TEST TEXT 3"},{"NEW TEST TEXT 4"},{"NEW TEST TEXT 5"}}; + + static_logging_segment<4> logger; + + gp_config::assertion(logger.size() == 0, "new logger not empty"); + + for(auto i : {0,1,2,3,4}) { + logger.set_segment(name[i], texts[i]); + } + + log_segment("size", std::to_string(logger.size()).c_str()); + + gp_config::assertion(logger.size() <= 4, "Size should be capped at 4"); + gp_config::assertion(logger.size() == 4, "Size should be 4"); + + for(auto i : {0, 1, 2, 3}) { + auto v = logger.get_segment_by_idx(i); + bool same = true; + for(size_t it = 0; it < 4; it++) { + same &= name[0][it] == v.name[it]; + } + gp_config::assertion(!same, "Should not contain oldest element"); + } + + + return res; + } +}; + +append_test dummy_aertm46f(new logging_test4{}); + +struct logging_test5 : public test_scaffold { + logging_test5() { + name = __FILE__ ":5"; + } + + + virtual int run() { + int res = 0; + + const gp::buffer name[5]{{"TEST 1"},{"TEST 2"},{"TEST 3"},{"TEST 4"},{"TEST 5"}}; + const gp::buffer texts[5] {{"NEW TEST TEXT 1"},{"NEW TEST TEXT 2"},{"NEW TEST TEXT 3"},{"NEW TEST TEXT 4"},{"NEW TEST TEXT 5"}}; + const uint16_t prios[5] {1,1,0,1,1}; + + static_logging_segment<4> logger; + + gp_config::assertion(logger.size() == 0, "new logger not empty"); + + for(auto i : {0,1,2,3,4}) { + logger.set_segment(name[i], texts[i], prios[i]); + } + + log_segment("size", std::to_string(logger.size()).c_str()); + + gp_config::assertion(logger.size() <= 4, "Size should be capped at 4"); + gp_config::assertion(logger.size() == 4, "Size should be 4"); + + for(auto i : {0, 1, 2, 3}) { + auto v = logger.get_segment_by_idx(i); + log_segment("prio value", std::to_string(v.priority).c_str()); + gp_config::assertion(v.priority != 0, "Should not contain low prio element"); + } + + + return res; + } +}; + +append_test dummy_azefdhi6f(new logging_test5{}); + + + +struct logging_test6 : public test_scaffold { + logging_test6() { + name = __FILE__ ":6"; + } + + + virtual int run() { + int res = 0; + + const gp::buffer name{"FIRST TEST"}; + const gp::buffer text{"FIRST TEST TEXT"}; + const gp::buffer new_text{"NEW TEST TEXT"}; + + static_logging_segment<4> logger; + + gp_config::assertion(logger.size() == 0, "new logger not empty"); + + logger.push_segment(name, text); + + gp_config::assertion(logger.size() == 1, "should be 1 after insertion"); + + logger.set_segment(name, new_text); + + gp_config::assertion(logger.size() == 1, "should still be one as key is identical"); + + logger.clear(); + + gp_config::assertion(logger.size() == 0, "should be zero after clear"); + + return res; + } +}; + +append_test dummy_ra45645sdf(new logging_test6{}); \ No newline at end of file