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.

139 lines
4.1 KiB

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