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.

223 lines
4.7 KiB

  1. #pragma once
  2. #include "gp/containers/array.hpp"
  3. namespace gp {
  4. template<typename T, size_t cap>
  5. class dynarray {
  6. struct build_order{};
  7. struct v_element{
  8. char data[sizeof(T)];
  9. operator T&() {
  10. return *(T*)data;
  11. }
  12. v_element()
  13. : data{}
  14. {}
  15. template<typename ...Args>
  16. v_element(build_order, Args&&... argv) {
  17. new(data) T(gp::forward<Args>(argv)...);
  18. }
  19. template<typename arg>
  20. T& operator=(arg& argv) {
  21. return *(T*)data = argv;
  22. }
  23. template<typename arg>
  24. T& operator=(arg&& argv) {
  25. return *(T*)data = gp::forward<arg>(argv);
  26. }
  27. template<typename ...Args>
  28. void build(Args&&... argv) {
  29. new(data) T(gp::forward<Args>(argv)...);
  30. }
  31. T& value() {
  32. return *(T*)data;
  33. }
  34. T& value() const {
  35. return *(T*)data;
  36. }
  37. void clear(){
  38. ((T*)data)->~T();
  39. }
  40. };
  41. using associated_iterator = pointer_iterator<T, 1>;
  42. using associated_const_iterator = const_pointer_iterator<T, 1>;
  43. using associated_riterator = pointer_iterator<T, -1>;
  44. using associated_const_riterator = const_pointer_iterator<T, -1>;
  45. v_element data[cap];
  46. size_t sz = 0;
  47. public:
  48. dynarray() = default;
  49. dynarray(dynarray& oth)
  50. {
  51. for(auto& ref : oth) {
  52. push_back(ref);
  53. }
  54. }
  55. dynarray(dynarray&& oth)
  56. {
  57. for(auto& ref : oth) {
  58. emplace_back(gp::move(ref));
  59. }
  60. oth.sz = 0;
  61. }
  62. dynarray& operator=(const dynarray& oth) {
  63. for(auto& self : data) {
  64. self.clear();
  65. }
  66. sz = 0;
  67. for(auto& ref : oth) {
  68. push_back(ref);
  69. }
  70. return *this;
  71. }
  72. dynarray& operator=(dynarray&& oth) {
  73. for(auto& self : data) {
  74. self.clear();
  75. }
  76. sz = 0;
  77. for(auto& ref : oth) {
  78. emplace_back(gp::forward<T>(ref));
  79. }
  80. oth.sz = 0;
  81. return *this;
  82. }
  83. constexpr associated_iterator begin()
  84. {
  85. return associated_iterator((T*)&data[0]);
  86. }
  87. constexpr associated_iterator end()
  88. {
  89. return associated_iterator((T*)&data[sz]);
  90. }
  91. constexpr const associated_iterator begin() const
  92. {
  93. return associated_iterator((T*)&data[0]);
  94. }
  95. constexpr const associated_iterator end() const
  96. {
  97. return associated_iterator((T*)&data[sz]);
  98. }
  99. constexpr associated_const_iterator cbegin() const
  100. {
  101. return associated_const_iterator((T*)&data[0]);
  102. }
  103. constexpr associated_const_iterator cend() const
  104. {
  105. return associated_const_iterator((T*)&data[sz]);
  106. }
  107. constexpr associated_riterator rbegin()
  108. {
  109. return associated_riterator((T*)&data[sz-1]);
  110. }
  111. constexpr associated_riterator rend()
  112. {
  113. return associated_riterator((T*)data-1);
  114. }
  115. constexpr associated_const_riterator crbegin() const
  116. {
  117. return associated_const_riterator((T*)&data[sz-1]);
  118. }
  119. constexpr associated_const_riterator crend() const
  120. {
  121. return associated_const_riterator((T*)data-1);
  122. }
  123. constexpr bool operator==(const dynarray& oth) const
  124. {
  125. if(size() != oth.size()) return false;
  126. for(size_t idx = 0; idx<sz; idx++)
  127. {
  128. if(data[idx].value() != oth.data[idx].value())
  129. {
  130. return false;
  131. }
  132. }
  133. return true;
  134. }
  135. constexpr bool operator!=(const dynarray& oth) const
  136. {
  137. return !(*this == oth);
  138. }
  139. size_t size() const {
  140. return sz;
  141. }
  142. constexpr size_t capacity() const {
  143. return cap;
  144. }
  145. T& operator[] (size_t idx) {
  146. return data[idx];
  147. }
  148. const T& operator[] (size_t idx) const {
  149. return data[idx];
  150. }
  151. void push_back(T& value) {
  152. data[sz].build(value);
  153. ++sz;
  154. }
  155. void push_back(T&& value) {
  156. data[sz].build(value);
  157. ++sz;
  158. }
  159. template<typename ...Args>
  160. void emplace_back(Args&&... argv) {
  161. data[sz].build(gp::forward<Args>(argv)...);
  162. ++sz;
  163. }
  164. void remove_back() {
  165. --sz;
  166. data[sz].clear();
  167. }
  168. gp::buffer<T> as_buffer()
  169. {
  170. return gp::buffer<T>{(T*)data, (T*)data+sz};
  171. }
  172. ~dynarray() {
  173. auto it = data;
  174. auto end = data + size();
  175. while(it != end) {
  176. (*it).clear();
  177. ++it;
  178. }
  179. }
  180. };
  181. }