|
|
- #pragma once
-
- #include "gp/algorithms/min_of.hpp"
- #include "gp/containers/dynarray.hpp"
- #include "gp/containers/vector.hpp"
- #include "gp/functional/optional.hpp"
-
- #include <stdint.h>
- #include <string>
- #include <sstream>
-
- struct segment{
- int16_t priority = 0;
- gp::dynarray<char, 32> name;
- gp::dynarray<char, gp_config::limits::loggers_segment_size> text;
- };
-
- struct virtual_logging_segment{
- virtual size_t push_segment(gp::buffer<char> name, gp::buffer<char> text, int16_t prio = 0) = 0;
- virtual void set_segment(gp::buffer<char> name, gp::buffer<char> text, int16_t prio = 0) = 0;
- virtual gp::optional<gp::reference_wrapper<segment>> get_segment(gp::buffer<char> name) = 0;
- virtual size_t size() = 0;
- virtual segment& get_segment_by_idx(size_t) = 0;
- virtual void clear() = 0;
- };
-
-
- template<size_t capacity>
- struct static_logging_segment : virtual_logging_segment{
- gp::dynarray<segment, capacity> data;
- gp::optional<size_t> wrap_around;
- //gp::function<void(virtual_logging_segment&)> on_destruct{[](virtual_logging_segment&){}, gp::nullopt};
-
- ~static_logging_segment() {
- //on_destruct(*this);
- }
-
- segment prepare_segment(gp::buffer<char> name, gp::buffer<char> text, int prio = 0) {
- segment prepared;
- prepared.priority = prio;
- {
- auto it = name.begin();
- auto end = name.begin()+gp::min(name.size(), prepared.name.capacity());
- while(it != end) {
- prepared.name.push_back(*it);
- ++it;
- }
- }
- {
- auto it = text.begin();
- auto end = text.begin()+gp::min(text.size(), prepared.text.capacity());
- while(it != end) {
- prepared.text.push_back(*it);
- ++it;
- }
- if(text.size()>prepared.text.capacity()) {
- auto it = prepared.text.rbegin();
- *it = '.'; ++it;
- *it = '.'; ++it;
- *it = '.';
- }
- }
-
- return prepared;
- }
-
- virtual size_t push_segment(gp::buffer<char> name, gp::buffer<char> 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(prio >= override_prio) {
- if(data[idx].priority == override_prio) {
- data[idx] = prepared;
- break;
- }
- idx = (++idx) % data.size();
- }
- idx = (++idx) % data.size();
- wrap_around = idx;
- return idx-1;
- } else {
- data.push_back(prepared);
- return data.size()-1;
- }
- }
-
- virtual void set_segment(gp::buffer<char> name, gp::buffer<char> text, int16_t prio = 0) {
- auto prepared = prepare_segment(name, text, prio);
- auto seg = get_segment(prepared.name.as_buffer());
-
- if(seg.has_value()) {
- seg.value().get() = prepared;
-
- return;
- }
-
- push_segment(prepared.name.as_buffer(), prepared.text.as_buffer(), prepared.priority);
- }
-
- virtual gp::optional<gp::reference_wrapper<segment>> get_segment(gp::buffer<char> name) {
- decltype(segment{}.name) tname;
- auto it = name.begin();
- auto end = name.begin()+gp::min(name.size(), tname.capacity());
- while(it != end) {
- tname.push_back(*it);
- ++it;
- }
-
- for(auto& elem : data) {
- if(elem.name == tname) {
- return gp::reference_wrapper<segment>(elem);
- }
- }
-
- return gp::nullopt;
- }
-
- virtual size_t size() {
- return data.size();
- }
-
- virtual segment& get_segment_by_idx(size_t idx) {
- return data[idx];
- }
-
- virtual void clear() {
- data.~dynarray();
- new(&data) decltype(data){};
- }
- };
-
- /*struct dynamic_logging_segment{
-
- };*/
|