buffer.hpp 2.9 KB

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