General Purpose library for Freestanding C++ and POSIX systems
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

178 рядки
3.3 KiB

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