buffer.hpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #pragma once
  2. #include <stdint.h>
  3. #include <types/allocator.hpp>
  4. namespace types {
  5. template <template <typename> class Allocator>
  6. class buffer {
  7. public:
  8. using allocator_type = Allocator<char>;
  9. private:
  10. char* const start;
  11. char* const end;
  12. char* base;
  13. char* head;
  14. size_t count;
  15. private:
  16. constexpr char _get_char(char* ptr)
  17. {
  18. --count;
  19. return *ptr;
  20. }
  21. constexpr void _put_char(char c)
  22. {
  23. *head = c;
  24. ++count;
  25. }
  26. constexpr char* _forward(char* ptr)
  27. {
  28. if (ptr == end)
  29. return start;
  30. else
  31. return ptr + 1;
  32. }
  33. constexpr char* _backward(char* ptr)
  34. {
  35. if (ptr == start)
  36. return end;
  37. else
  38. return ptr - 1;
  39. }
  40. public:
  41. constexpr buffer(size_t size)
  42. : start { types::allocator_traits<allocator_type>::allocate(size) }
  43. , end { start + size - 1 }
  44. , base { start }
  45. , head { start }
  46. , count { 0 }
  47. {
  48. }
  49. constexpr buffer(const buffer& buf)
  50. : start { types::allocator_traits<allocator_type>::allocate(buf.end + 1 - buf.start) }
  51. , end { (uint32_t)start + (uint32_t)buf.end - (uint32_t)buf.start }
  52. , base { (uint32_t)start + (uint32_t)buf.base - (uint32_t)buf.start }
  53. , head { (uint32_t)start + (uint32_t)buf.base - (uint32_t)buf.start }
  54. , count { buf.count }
  55. {
  56. }
  57. constexpr buffer(buffer&& buf)
  58. : start { buf.start }
  59. , end { buf.end }
  60. , base { buf.base }
  61. , head { buf.head }
  62. , count { buf.count }
  63. {
  64. }
  65. constexpr ~buffer()
  66. {
  67. if (start)
  68. types::allocator_traits<allocator_type>::deallocate(start);
  69. }
  70. constexpr bool empty(void) const
  71. {
  72. return count == 0;
  73. }
  74. constexpr bool full(void) const
  75. {
  76. return count == static_cast<size_t>(end - start + 1);
  77. }
  78. constexpr char front(void)
  79. {
  80. return *base;
  81. }
  82. constexpr char back(void)
  83. {
  84. return *_backward(head);
  85. }
  86. constexpr char get(void)
  87. {
  88. // TODO: set error flag
  89. if (empty())
  90. return 0xff;
  91. char c = _get_char(base);
  92. base = _forward(base);
  93. return c;
  94. }
  95. constexpr char pop(void)
  96. {
  97. // TODO: set error flag
  98. if (empty())
  99. return 0xff;
  100. char c = _get_char(_backward(head));
  101. head = _backward(head);
  102. return c;
  103. }
  104. constexpr char put(char c)
  105. {
  106. // TODO: set error flag
  107. if (full())
  108. return 0xff;
  109. _put_char(c);
  110. head = _forward(head);
  111. return c;
  112. }
  113. };
  114. } // namespace types