General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
4.1 KiB

  1. #pragma once
  2. #include "gp/algorithms/min_of.hpp"
  3. #include "gp/containers/dynarray.hpp"
  4. #include "gp/containers/vector.hpp"
  5. #include "gp/functional/optional.hpp"
  6. #include <stdint.h>
  7. struct segment{
  8. int16_t priority = 0;
  9. gp::dynarray<char, 32> name;
  10. gp::dynarray<char, gp_config::limits::loggers_segment_size> text;
  11. };
  12. struct virtual_logging_segment{
  13. virtual size_t push_segment(gp::buffer<char> name, gp::buffer<char> text, int16_t prio = 0) = 0;
  14. virtual void set_segment(gp::buffer<char> name, gp::buffer<char> text, int16_t prio = 0) = 0;
  15. virtual gp::optional<gp::reference_wrapper<segment>> get_segment(gp::buffer<char> name) = 0;
  16. virtual size_t size() = 0;
  17. virtual segment& get_segment_by_idx(size_t) = 0;
  18. virtual void clear() = 0;
  19. };
  20. template<size_t capacity>
  21. struct static_logging_segment : virtual_logging_segment{
  22. gp::dynarray<segment, capacity> data;
  23. gp::optional<size_t> wrap_around;
  24. //gp::function<void(virtual_logging_segment&)> on_destruct{[](virtual_logging_segment&){}, gp::nullopt};
  25. ~static_logging_segment() {
  26. //on_destruct(*this);
  27. }
  28. segment prepare_segment(gp::buffer<char> name, gp::buffer<char> text, int prio = 0) {
  29. segment prepared;
  30. prepared.priority = prio;
  31. {
  32. auto it = name.begin();
  33. auto end = name.begin()+gp::min(name.size(), prepared.name.capacity());
  34. while(it != end) {
  35. prepared.name.push_back(*it);
  36. ++it;
  37. }
  38. }
  39. {
  40. auto it = text.begin();
  41. auto end = text.begin()+gp::min(text.size(), prepared.text.capacity());
  42. while(it != end) {
  43. prepared.text.push_back(*it);
  44. ++it;
  45. }
  46. if(text.size()>prepared.text.capacity()) {
  47. auto it = prepared.text.rbegin();
  48. *it = '.'; ++it;
  49. *it = '.'; ++it;
  50. *it = '.';
  51. }
  52. }
  53. return prepared;
  54. }
  55. virtual size_t push_segment(gp::buffer<char> name, gp::buffer<char> text, int16_t prio = 0) {
  56. auto prepared = prepare_segment(name, text, prio);
  57. if(data.size() == data.capacity()) {
  58. wrap_around = 0;
  59. }
  60. if(wrap_around.has_value()) {
  61. size_t idx = wrap_around.value();
  62. int16_t override_prio = gp::min_of(data.begin(), data.end(), [](auto v){ return v.priority; });
  63. while(prio >= override_prio) {
  64. if(data[idx].priority == override_prio) {
  65. data[idx] = prepared;
  66. break;
  67. }
  68. idx = (++idx) % data.size();
  69. }
  70. idx = (++idx) % data.size();
  71. wrap_around = idx;
  72. return idx-1;
  73. } else {
  74. data.push_back(prepared);
  75. return data.size()-1;
  76. }
  77. }
  78. virtual void set_segment(gp::buffer<char> name, gp::buffer<char> text, int16_t prio = 0) {
  79. auto prepared = prepare_segment(name, text, prio);
  80. auto seg = get_segment(prepared.name.as_buffer());
  81. if(seg.has_value()) {
  82. seg.value().get() = prepared;
  83. return;
  84. }
  85. push_segment(prepared.name.as_buffer(), prepared.text.as_buffer(), prepared.priority);
  86. }
  87. virtual gp::optional<gp::reference_wrapper<segment>> get_segment(gp::buffer<char> name) {
  88. decltype(segment{}.name) tname;
  89. auto it = name.begin();
  90. auto end = name.begin()+gp::min(name.size(), tname.capacity());
  91. while(it != end) {
  92. tname.push_back(*it);
  93. ++it;
  94. }
  95. for(auto& elem : data) {
  96. if(elem.name == tname) {
  97. return gp::reference_wrapper<segment>(elem);
  98. }
  99. }
  100. return gp::nullopt;
  101. }
  102. virtual size_t size() {
  103. return data.size();
  104. }
  105. virtual segment& get_segment_by_idx(size_t idx) {
  106. return data[idx];
  107. }
  108. virtual void clear() {
  109. data.~dynarray();
  110. new(&data) decltype(data){};
  111. }
  112. };
  113. /*struct dynamic_logging_segment{
  114. };*/