List.h 5.7 KB

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