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.

260 rivejä
4.9 KiB

4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
  1. #pragma once
  2. #include <gp/buffer.hpp>
  3. #include <gp/allocator/allocator.hpp>
  4. #include <initializer_list>
  5. namespace gp{
  6. template<typename T>
  7. class vector{
  8. public:
  9. T* ary;
  10. size_t sz;
  11. size_t cap;
  12. gp::reference_wrapper<allocator> alloc;
  13. using associated_iterator = pointer_iterator<T, 1>;
  14. using associated_const_iterator = const_pointer_iterator<T, 1>;
  15. using associated_riterator = pointer_iterator<T, -1>;
  16. using associated_const_riterator = const_pointer_iterator<T, -1>;
  17. vector(allocator& v)
  18. : ary()
  19. , alloc(v)
  20. {}
  21. vector(const vector& oth)
  22. {
  23. sz = 0;
  24. cap = 0;
  25. ary = nullptr;
  26. alloc = oth.alloc;
  27. gp_config::assertion(reserve(oth.size()), "could not reserve space on building");
  28. sz = oth.size();
  29. cap = oth.size();
  30. auto it_l = begin();
  31. auto it_o = oth.cbegin();
  32. for(size_t i = 0; i < sz; ++i)
  33. {
  34. new(&*(it_l++)) T(*(it_o++));
  35. }
  36. }
  37. vector(vector&& oth)
  38. : ary(oth.ary)
  39. , sz(oth.sz)
  40. , cap(oth.cap)
  41. , alloc(oth.alloc)
  42. {
  43. oth.ary = nullptr;
  44. }
  45. /* TODO: Build the templated equivalents
  46. array(T (& oth)[sz]) {
  47. gp::move_uninitialized<T>(
  48. gp::nameless_range<int*>(oth, oth+sz),
  49. gp::nameless_range<associated_iterator>(begin(), end())
  50. );
  51. }
  52. array(T (&& oth)[sz]) {
  53. gp::move_uninitialized(
  54. gp::nameless_range<int*>((T*)oth, (T*)oth+sz),
  55. gp::nameless_range<associated_iterator>(begin(), end())
  56. );
  57. }*/
  58. vector& operator=(vector& oth)
  59. {
  60. gp_config::assertion(reserve(oth.size()), "could not reserve space on assign");
  61. for(size_t i = 0; i < gp::min(sz, oth.sz); ++i)
  62. {
  63. ary[i]=oth[i];
  64. }
  65. if(sz < oth.sz) {
  66. for(size_t i = sz; i < oth.sz; ++i) {
  67. new(ary+i) T(oth[i]);
  68. }
  69. } else if(sz > oth.sz) {
  70. for(size_t i = oth.sz; i < sz; ++i) {
  71. ary[i]->~T();
  72. }
  73. }
  74. sz = oth.sz;
  75. return *this;
  76. }
  77. vector& operator=(vector&& oth)
  78. {
  79. gp::swap(ary, oth.ary);
  80. gp::swap(alloc, oth.alloc);
  81. gp::swap(sz, oth.sz);
  82. gp::swap(cap, oth.cap);
  83. return *this;
  84. }
  85. constexpr T& operator[] (size_t off)
  86. {
  87. if constexpr (gp_config::has_buffer_bounds)
  88. {
  89. gp_config::assertion(
  90. off < sz,
  91. "Array bounds infringed"
  92. );
  93. }
  94. return ary[off];
  95. }
  96. ~vector()
  97. {
  98. if(ary)
  99. {
  100. for(auto& elem : *this) {
  101. elem->~T();
  102. }
  103. gp_config::assertion(alloc.get().deallocate(ary), "could not deallocate");
  104. }
  105. }
  106. bool grow() {
  107. if(sz == cap) return reserve(1 + sz + (sz >> 1));
  108. return true;
  109. }
  110. bool reserve(size_t new_cap) {
  111. if(new_cap <= cap) return true;
  112. size_t new_data_size = new_cap*sizeof(T);
  113. if(alloc.get().try_reallocate(ary, new_data_size)) return true;
  114. if(T* new_ary = alloc.get().allocate(new_data_size); new_ary) {
  115. auto new_it = new_ary;
  116. for(auto* elem : *this) {
  117. ++new_it = gp::move(elem);
  118. }
  119. gp_config::assertion(alloc.get().deallocate(ary), "failed to deallocate old range");
  120. ary = new_ary;
  121. cap = new_cap;
  122. return true;
  123. }
  124. return false;
  125. }
  126. constexpr const T& operator[] (size_t off) const
  127. {
  128. return ary[off];
  129. }
  130. constexpr size_t size() const
  131. {
  132. return sz;
  133. }
  134. constexpr size_t capacity() const
  135. {
  136. return cap;
  137. }
  138. constexpr bool push_back(T& value) {
  139. if(grow()) {
  140. new(ary+sz) T(value);
  141. sz++;
  142. return true;
  143. }
  144. return false;
  145. }
  146. constexpr bool push_back(T&& value) {
  147. if(grow()) {
  148. new(ary+sz) T(gp::move(value));
  149. sz++;
  150. return true;
  151. }
  152. return false;
  153. }
  154. template<typename ...U>
  155. constexpr bool emplace_back(U&&... value) {
  156. if(grow()) {
  157. new(ary+sz) T(gp::forward<U>(value)...);
  158. sz++;
  159. return true;
  160. }
  161. return false;
  162. }
  163. constexpr gp::optional<T> pop_back() {
  164. if(sz == 0) return gp::nullopt;
  165. sz--;
  166. gp::optional<T> ret_val = gp::move(ary[sz]);
  167. ary[sz]->~T();
  168. return gp::move(ret_val);
  169. }
  170. constexpr pointer_iterator<T, 1> begin()
  171. {
  172. return associated_iterator(&ary[0]);
  173. }
  174. constexpr pointer_iterator<T, 1> end()
  175. {
  176. return associated_iterator(&ary[sz]);
  177. }
  178. constexpr const_pointer_iterator<T, 1> cbegin() const
  179. {
  180. return associated_const_iterator(&ary[0]);
  181. }
  182. constexpr const_pointer_iterator<T, 1> cend() const
  183. {
  184. return associated_const_iterator(&ary[sz]);
  185. }
  186. constexpr pointer_iterator<T, -1> rbegin()
  187. {
  188. return associated_riterator(&ary[sz-1]);
  189. }
  190. constexpr pointer_iterator<T, -1> rend()
  191. {
  192. return associated_riterator(ary-1);
  193. }
  194. constexpr const_pointer_iterator<T, -1> crbegin() const
  195. {
  196. return associated_const_riterator(&ary[sz-1]);
  197. }
  198. constexpr const_pointer_iterator<T, -1> crend() const
  199. {
  200. return associated_const_riterator(ary-1);
  201. }
  202. constexpr bool operator==(const vector& oth) const
  203. {
  204. for(size_t idx = 0; idx<sz; idx++)
  205. {
  206. if(ary[idx] != oth.ary[idx])
  207. {
  208. return false;
  209. }
  210. }
  211. return true;
  212. }
  213. constexpr bool operator!=(const vector& oth) const
  214. {
  215. return !(*this == oth);
  216. }
  217. gp::buffer<T> as_buffer()
  218. {
  219. return gp::buffer<T>{(T*)ary, (T*)ary+sz};
  220. }
  221. };
  222. }