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.

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