General Purpose library for Freestanding C++ and POSIX systems
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

125 rindas
3.8 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&){};
  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(wrap_around.has_value()) {
  58. size_t idx = wrap_around.value();
  59. size_t override_prio = gp::min_of(data.begin(), data.end(), [](auto v){ return v.priority; });
  60. while(true) {
  61. if(data[idx].priority == override_prio) {
  62. data[idx] = prepared;
  63. break;
  64. }
  65. idx = (++idx) % data.size();
  66. }
  67. idx = (++idx) % data.size();
  68. wrap_around = idx;
  69. return idx-1;
  70. } else {
  71. data.push_back(prepared);
  72. return data.size()-1;
  73. }
  74. }
  75. virtual void set_segment(gp::buffer<char> name, gp::buffer<char> text, int16_t prio = 0) {
  76. auto prepared = prepare_segment(name, text, prio);
  77. if(auto seg = get_segment(name); seg.has_value()) {
  78. seg.value() = prepared;
  79. } else {
  80. data.push_back(prepared);
  81. }
  82. }
  83. virtual gp::optional<gp::reference_wrapper<segment>> get_segment(gp::buffer<char> name) {
  84. decltype(segment{}.name) tname;
  85. auto it = name.begin();
  86. auto end = name.begin()+gp::min(name.size(), tname.capacity());
  87. while(it != end) {
  88. tname.push_back(*it);
  89. ++it;
  90. }
  91. for(auto& elem : data) {
  92. if(elem.name == tname) {
  93. return gp::reference_wrapper<segment>(elem);
  94. }
  95. }
  96. return gp::nullopt;
  97. }
  98. virtual size_t size() {
  99. return data.size();
  100. }
  101. virtual segment& get_segment_by_idx(size_t idx) {
  102. return data[idx];
  103. }
  104. virtual void clear() {
  105. data.~dynarray();
  106. new(&data) decltype(data){};
  107. }
  108. };
  109. /*struct dynamic_logging_segment{
  110. };*/