General Purpose library for Freestanding C++ and POSIX systems
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

204 linhas
3.9 KiB

  1. #pragma once
  2. #include <cstddef>
  3. #include <cstdint>
  4. #include <gp/optional.hpp>
  5. #include <gp/iterator.hpp>
  6. #include <gp/function.hpp>
  7. #include <gp/exception.hpp>
  8. #include <gp/algorithm/move.hpp>
  9. namespace gp{
  10. template<typename T>
  11. class buffer final{
  12. public:
  13. struct buffer_iterator final
  14. {
  15. T* data;
  16. typedef T value_type;
  17. typedef std::size_t difference_type;
  18. static constexpr iterator_type_t iterator_type = iterator_type_t::contiguous_iterator;
  19. constexpr buffer_iterator(const buffer_iterator& oth)
  20. : data{oth.data}
  21. {}
  22. constexpr buffer_iterator(T* ptr)
  23. : data{ptr}
  24. {}
  25. constexpr operator T&()
  26. {
  27. return *data;
  28. }
  29. constexpr T& operator*(){
  30. return *data;
  31. }
  32. constexpr buffer_iterator operator++()
  33. {
  34. return buffer_iterator{++data};
  35. }
  36. constexpr buffer_iterator operator++(int)
  37. {
  38. return buffer_iterator{data++};
  39. }
  40. constexpr buffer_iterator operator--()
  41. {
  42. return buffer_iterator{--data};
  43. }
  44. constexpr buffer_iterator operator--(int)
  45. {
  46. return buffer_iterator{data--};
  47. }
  48. constexpr buffer_iterator operator+(const std::size_t offset)
  49. {
  50. return buffer_iterator{data+offset};
  51. }
  52. constexpr buffer_iterator operator+(const int offset)
  53. {
  54. return buffer_iterator{data+offset};
  55. }
  56. constexpr buffer_iterator operator-(const std::size_t offset)
  57. {
  58. return buffer_iterator{data-offset};
  59. }
  60. constexpr buffer_iterator operator-(const int offset)
  61. {
  62. return buffer_iterator{data-offset};
  63. }
  64. constexpr difference_type operator-(const buffer_iterator& oth) const
  65. {
  66. return (T*)data-(T*)oth.data;
  67. }
  68. constexpr bool operator==(const buffer_iterator& oth)
  69. {
  70. return data==oth.data;
  71. }
  72. constexpr bool operator!=(buffer_iterator& oth)
  73. {
  74. return data!=oth.data;
  75. }
  76. constexpr bool before_or_equal(const buffer_iterator& oth)
  77. {
  78. return reinterpret_cast<std::intptr_t>(data) <= reinterpret_cast<std::intptr_t>(oth.data);
  79. }
  80. constexpr bool operator<=(const buffer_iterator& oth)
  81. {
  82. return before_or_equal(oth);
  83. }
  84. };
  85. private:
  86. buffer_iterator begin_elem;
  87. buffer_iterator end_elem;
  88. public:
  89. using associated_iterator = buffer_iterator;
  90. constexpr buffer(T* beg_ptr, T* end_ptr)
  91. : begin_elem{beg_ptr}
  92. , end_elem{end_ptr}
  93. {}
  94. constexpr buffer(T* beg_ptr, std::size_t sz)
  95. : begin_elem{beg_ptr}
  96. , end_elem{beg_ptr+sz}
  97. {}
  98. constexpr typename buffer_iterator::difference_type size() const
  99. {
  100. return end_elem - begin_elem;
  101. }
  102. constexpr associated_iterator begin() const
  103. {
  104. return begin_elem;
  105. }
  106. constexpr associated_iterator end() const
  107. {
  108. return end_elem;
  109. }
  110. constexpr T& operator[](std::size_t offset)
  111. {
  112. return *(begin_elem+offset);
  113. }
  114. optional<buffer_iterator> at(std::size_t offset)
  115. {
  116. auto elem = begin()+offset;
  117. if(!contains(elem))
  118. {
  119. return nullopt;
  120. }
  121. return elem;
  122. }
  123. constexpr bool contains(buffer_iterator ptr)
  124. {
  125. return
  126. ptr.data < end_elem.data
  127. && ptr.data >= begin_elem.data;
  128. }
  129. template<typename U>
  130. buffer<U> cast()
  131. {
  132. if constexpr(sizeof(T)%sizeof(U) == 0)
  133. {
  134. return buffer<U>(reinterpret_cast<U*>(&*begin_elem), size()*(sizeof(T)/sizeof(U)));
  135. }
  136. else
  137. {
  138. if(size()*sizeof(T)/sizeof(U))
  139. {
  140. return buffer<U>(reinterpret_cast<U*>(&*begin_elem), size()*sizeof(T)/sizeof(U));
  141. }
  142. else if constexpr (gp_config::has_exceptions)
  143. {
  144. throw bad_buffer_cast<T, U>{};
  145. }
  146. else
  147. {
  148. return buffer<U>(reinterpret_cast<U*>(nullptr), 0);
  149. }
  150. }
  151. }
  152. buffer slice_start(size_t new_sz)
  153. {
  154. if(new_sz<=size())
  155. {
  156. return buffer{&*begin(), &*(begin()+new_sz)};
  157. }
  158. else
  159. {
  160. return buffer{(T*)nullptr,(size_t)0};
  161. }
  162. }
  163. buffer slice_end(size_t new_sz)
  164. {
  165. if(new_sz<=size())
  166. {
  167. return buffer{&*(end()-(1+new_sz)), &*end()};
  168. }
  169. else
  170. {
  171. return buffer{(T*)nullptr,(size_t)0};
  172. }
  173. }
  174. };
  175. }