buffer.hpp 3.0 KB

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