General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
2.8 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  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. public:
  17. using associated_iterator = pointer_iterator<T>;
  18. constexpr buffer(T* beg_ptr, T* end_ptr)
  19. : begin_elem{beg_ptr}
  20. , end_elem{end_ptr}
  21. {}
  22. constexpr buffer(associated_iterator beg_ptr, associated_iterator end_ptr)
  23. : begin_elem{beg_ptr}
  24. , end_elem{end_ptr}
  25. {}
  26. constexpr buffer(T* beg_ptr, std::size_t sz)
  27. : begin_elem{beg_ptr}
  28. , end_elem{beg_ptr+sz}
  29. {}
  30. constexpr typename pointer_iterator<T>::difference_type size() const
  31. {
  32. return end_elem - begin_elem;
  33. }
  34. constexpr associated_iterator begin() const
  35. {
  36. return begin_elem;
  37. }
  38. constexpr associated_iterator end() const
  39. {
  40. return end_elem;
  41. }
  42. constexpr T& operator[](std::size_t offset)
  43. {
  44. if constexpr (gp_config::has_buffer_bounds)
  45. {
  46. gp_config::assertion(
  47. offset < size(),
  48. "Buffer bounds infringed"
  49. );
  50. }
  51. return *(begin_elem+offset);
  52. }
  53. optional<pointer_iterator<T>> at(std::size_t offset)
  54. {
  55. auto elem = begin()+offset;
  56. if(!contains(elem))
  57. {
  58. return nullopt;
  59. }
  60. return elem;
  61. }
  62. constexpr bool contains(pointer_iterator<T> ptr)
  63. {
  64. return
  65. ptr.data < end_elem.data
  66. && ptr.data >= begin_elem.data;
  67. }
  68. template<typename U>
  69. buffer<U> cast()
  70. {
  71. if constexpr(sizeof(T)%sizeof(U) == 0)
  72. {
  73. return buffer<U>(reinterpret_cast<U*>(&*begin_elem), size()*(sizeof(T)/sizeof(U)));
  74. }
  75. else
  76. {
  77. if((size()*sizeof(T))%sizeof(U) == 0)
  78. {
  79. return buffer<U>(reinterpret_cast<U*>(&*begin_elem), size()*sizeof(T)/sizeof(U));
  80. }
  81. else if constexpr (gp_config::has_exceptions)
  82. {
  83. throw bad_buffer_cast<T, U>{};
  84. }
  85. else
  86. {
  87. return buffer<U>(reinterpret_cast<U*>(nullptr), 0);
  88. }
  89. }
  90. }
  91. buffer slice_start(size_t new_sz)
  92. {
  93. if(new_sz<=size())
  94. {
  95. return buffer{&*begin(), &*(begin()+new_sz)};
  96. }
  97. else
  98. {
  99. return buffer{(T*)nullptr,(size_t)0};
  100. }
  101. }
  102. buffer slice_end(size_t new_sz)
  103. {
  104. if(new_sz<=size())
  105. {
  106. return buffer{&*(end()-(new_sz)), &*end()};
  107. }
  108. else
  109. {
  110. return buffer{(T*)nullptr,(size_t)0};
  111. }
  112. }
  113. buffer trim_start(size_t rm_sz)
  114. {
  115. if(rm_sz<=size())
  116. {
  117. return buffer{begin().data + rm_sz, end().data};
  118. }
  119. else
  120. {
  121. return buffer{(T*)nullptr,(size_t)0};
  122. }
  123. }
  124. buffer trim_end(size_t rm_sz)
  125. {
  126. if(rm_sz<=size())
  127. {
  128. return buffer{begin().data, end().data - rm_sz};
  129. }
  130. else
  131. {
  132. return buffer{(T*)nullptr,(size_t)0};
  133. }
  134. }
  135. };
  136. }