List.hpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #ifndef CORE_LIST_HPP
  2. #define CORE_LIST_HPP
  3. #include "core/math/Math.hpp"
  4. #include "core/utils/AlignedData.hpp"
  5. #include "core/utils/ArrayString.hpp"
  6. #include "core/utils/Error.hpp"
  7. #include "core/utils/New.hpp"
  8. namespace Core {
  9. template<typename T>
  10. class List final {
  11. size_t length;
  12. size_t capacity;
  13. T* data;
  14. public:
  15. List() : length(0), capacity(0), data(nullptr) {
  16. }
  17. List(const List& other) = delete;
  18. List(List&& other) : List() {
  19. swap(other);
  20. }
  21. ~List() {
  22. clear();
  23. delete[] reinterpret_cast<AlignedType<T>*>(data);
  24. }
  25. List& operator=(const List& other) = delete;
  26. List& operator=(List&& other) {
  27. swap(other);
  28. return *this;
  29. }
  30. check_return Error copyFrom(const List& other) {
  31. List copy;
  32. CORE_RETURN_ERROR(allocate(copy.data, other.capacity));
  33. copy.capacity = other.capacity;
  34. for(size_t i = 0; i < other.length; i++) {
  35. copy.unsafeAdd(other[i]);
  36. }
  37. swap(copy);
  38. return ErrorCode::NONE;
  39. }
  40. T* begin() {
  41. return data;
  42. }
  43. T* end() {
  44. return data + length;
  45. }
  46. const T* begin() const {
  47. return data;
  48. }
  49. const T* end() const {
  50. return data + length;
  51. }
  52. check_return Error reserve(size_t n) {
  53. if(n <= capacity) {
  54. return ErrorCode::NONE;
  55. }
  56. return setSize(n);
  57. }
  58. check_return Error shrink() {
  59. if(length == capacity) {
  60. return ErrorCode::NONE;
  61. }
  62. return setSize(length);
  63. }
  64. check_return Error resize(size_t n, const T& t) {
  65. if(length < n) {
  66. CORE_RETURN_ERROR(reserve(n));
  67. for(size_t i = n - length; i != 0; i--) {
  68. unsafeAdd(t);
  69. }
  70. } else if(length > n) {
  71. for(size_t i = n; i < length; i++) {
  72. data[i].~T();
  73. }
  74. length = n;
  75. }
  76. return ErrorCode::NONE;
  77. }
  78. check_return Error resize(size_t n) {
  79. if(length < n) {
  80. CORE_RETURN_ERROR(reserve(n));
  81. for(size_t i = n - length; i != 0; i--) {
  82. unsafeAdd(T());
  83. }
  84. } else if(length > n) {
  85. for(size_t i = n; i < length; i++) {
  86. data[i].~T();
  87. }
  88. length = n;
  89. }
  90. return ErrorCode::NONE;
  91. }
  92. template<typename... Args>
  93. check_return Error put(T*& t, Args&&... args) {
  94. CORE_RETURN_ERROR(ensureCapacity());
  95. t = unsafeAdd(Core::forward<Args>(args)...);
  96. return ErrorCode::NONE;
  97. }
  98. template<typename... Args>
  99. check_return Error add(Args&&... args) {
  100. T* t = nullptr;
  101. return put(t, Core::forward<Args>(args)...);
  102. }
  103. T& operator[](size_t index) {
  104. return data[index];
  105. }
  106. const T& operator[](size_t index) const {
  107. return data[index];
  108. }
  109. size_t getLength() const {
  110. return length;
  111. }
  112. size_t getCapacity() const {
  113. return capacity;
  114. }
  115. void clear() {
  116. for(size_t i = 0; i < length; i++) {
  117. data[i].~T();
  118. }
  119. length = 0;
  120. }
  121. check_return Error removeBySwap(size_t index) {
  122. if(index >= length) {
  123. return ErrorCode::INVALID_INDEX;
  124. }
  125. length--;
  126. if(index != length) {
  127. data[index] = Core::move(data[length]);
  128. }
  129. data[length].~T();
  130. return ErrorCode::NONE;
  131. }
  132. check_return Error remove(size_t index) {
  133. if(index >= length) {
  134. return ErrorCode::INVALID_INDEX;
  135. }
  136. length--;
  137. T* currentT = begin() + index;
  138. T* endT = end();
  139. while(currentT != endT) {
  140. T* nextT = currentT + 1;
  141. *currentT = Core::move(*nextT);
  142. currentT = nextT;
  143. }
  144. endT->~T();
  145. return ErrorCode::NONE;
  146. }
  147. check_return Error removeLast() {
  148. return removeBySwap(length - 1);
  149. }
  150. template<typename String>
  151. check_return Error toString(String& s) const {
  152. return Core::toString(s, *this);
  153. }
  154. void swap(List& other) {
  155. Core::swap(length, other.length);
  156. Core::swap(capacity, other.capacity);
  157. Core::swap(data, other.data);
  158. }
  159. private:
  160. static Error allocate(T*& t, size_t n) {
  161. if(n > (1lu << 48)) {
  162. return ErrorCode::CAPACITY_REACHED;
  163. } else if(n <= 0) {
  164. return ErrorCode::NONE;
  165. }
  166. t = reinterpret_cast<T*>(new(noThrow) AlignedType<T>[n]);
  167. return t == nullptr ? ErrorCode::OUT_OF_MEMORY : ErrorCode::NONE;
  168. }
  169. check_return Error ensureCapacity() {
  170. return length < capacity
  171. ? ErrorCode::NONE
  172. : reserve(capacity + Math::max(4lu, capacity / 4));
  173. }
  174. // does not check for capacity
  175. template<typename... Args>
  176. T* unsafeAdd(Args&&... args) {
  177. return new(data + length++) T(Core::forward<Args>(args)...);
  178. }
  179. check_return Error setSize(size_t n) {
  180. List copy;
  181. CORE_RETURN_ERROR(allocate(copy.data, n));
  182. copy.capacity = n;
  183. for(size_t i = 0; i < length; i++) {
  184. copy.unsafeAdd(Core::move(data[i]));
  185. }
  186. swap(copy);
  187. return ErrorCode::NONE;
  188. }
  189. };
  190. }
  191. #endif