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.

189 line
4.0 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::forward<T>(ref));
  59. }
  60. }*/
  61. constexpr associated_iterator begin()
  62. {
  63. return associated_iterator((T*)&data[0]);
  64. }
  65. constexpr associated_iterator end()
  66. {
  67. return associated_iterator((T*)&data[sz]);
  68. }
  69. constexpr associated_const_iterator cbegin() const
  70. {
  71. return associated_const_iterator((T*)&data[0]);
  72. }
  73. constexpr associated_const_iterator cend() const
  74. {
  75. return associated_const_iterator((T*)&data[sz]);
  76. }
  77. constexpr associated_riterator rbegin()
  78. {
  79. return associated_riterator((T*)&data[sz-1]);
  80. }
  81. constexpr associated_riterator rend()
  82. {
  83. return associated_riterator((T*)data-1);
  84. }
  85. constexpr associated_const_riterator crbegin() const
  86. {
  87. return associated_const_riterator((T*)&data[sz-1]);
  88. }
  89. constexpr associated_const_riterator crend() const
  90. {
  91. return associated_const_riterator((T*)data-1);
  92. }
  93. constexpr bool operator==(const dynarray& oth) const
  94. {
  95. if(size() != oth.size()) return false;
  96. for(size_t idx = 0; idx<sz; idx++)
  97. {
  98. if(data[idx].value() != oth.data[idx].value())
  99. {
  100. return false;
  101. }
  102. }
  103. return true;
  104. }
  105. constexpr bool operator!=(const dynarray& oth) const
  106. {
  107. return !(*this == oth);
  108. }
  109. size_t size() const {
  110. return sz;
  111. }
  112. constexpr size_t capacity() const {
  113. return cap;
  114. }
  115. T& operator[] (size_t idx) {
  116. return data[idx];
  117. }
  118. const T& operator[] (size_t idx) const {
  119. return data[idx];
  120. }
  121. void push_back(T& value) {
  122. data[sz].build(value);
  123. ++sz;
  124. }
  125. void push_back(T&& value) {
  126. data[sz].build(value);
  127. ++sz;
  128. }
  129. template<typename ...Args>
  130. void emplace_back(Args&&... argv) {
  131. data[sz].build(gp::forward<Args>(argv)...);
  132. ++sz;
  133. }
  134. void remove_back() {
  135. --sz;
  136. data[sz].clear();
  137. }
  138. gp::buffer<T> as_buffer()
  139. {
  140. return gp::buffer<T>{(T*)data, (T*)data+sz};
  141. }
  142. ~dynarray() {
  143. auto it = data;
  144. auto end = data + size();
  145. while(it != end) {
  146. (*it).clear();
  147. ++it;
  148. }
  149. }
  150. };
  151. }