vector.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. #pragma once
  2. #include <cassert>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <memory>
  6. #include <algorithm>
  7. #include "pocketpy/common/traits.hpp"
  8. #include "pocketpy/common/types.hpp"
  9. namespace pkpy {
  10. template <typename T>
  11. struct array {
  12. T* _data;
  13. int _size;
  14. using size_type = int;
  15. array() : _data(nullptr), _size(0) {}
  16. array(int size) : _data((T*)std::malloc(sizeof(T) * size)), _size(size) {}
  17. array(array&& other) noexcept : _data(other._data), _size(other._size) {
  18. other._data = nullptr;
  19. other._size = 0;
  20. }
  21. array(const array& other) = delete;
  22. array(explicit_copy_t, const array& other) {
  23. _data = (T*)std::malloc(sizeof(T) * other._size);
  24. _size = other._size;
  25. for(int i = 0; i < _size; i++)
  26. _data[i] = other._data[i];
  27. }
  28. array(T* data, int size) : _data(data), _size(size) {}
  29. array& operator= (array&& other) noexcept {
  30. if(_data) {
  31. std::destroy(begin(), end());
  32. std::free(_data);
  33. }
  34. _data = other._data;
  35. _size = other._size;
  36. other._data = nullptr;
  37. other._size = 0;
  38. return *this;
  39. }
  40. array& operator= (const array& other) = delete;
  41. T& operator[] (int i) {
  42. assert(i >= 0 && i < _size);
  43. return _data[i];
  44. }
  45. const T& operator[] (int i) const {
  46. assert(i >= 0 && i < _size);
  47. return _data[i];
  48. }
  49. int size() const { return _size; }
  50. T* begin() const { return _data; }
  51. T* end() const { return _data + _size; }
  52. T* data() const { return _data; }
  53. std::pair<T*, int> detach() noexcept {
  54. std::pair<T*, int> retval(_data, _size);
  55. _data = nullptr;
  56. _size = 0;
  57. return retval;
  58. }
  59. ~array() {
  60. if(_data) {
  61. std::destroy(begin(), end());
  62. std::free(_data);
  63. }
  64. }
  65. };
  66. template <bool may_alias = false, typename T>
  67. void uninitialized_copy_n(const T* src, int n, T* dest) {
  68. if(n == 0) return;
  69. if constexpr(std::is_trivially_copyable_v<T>) {
  70. if constexpr(may_alias) {
  71. std::memmove(dest, src, sizeof(T) * n);
  72. } else {
  73. std::memcpy(dest, src, sizeof(T) * n);
  74. }
  75. } else {
  76. for(int i = 0; i < n; i++) {
  77. new (dest + i) T(*(src + i));
  78. }
  79. }
  80. }
  81. template <bool may_alias = false, bool backward = false, typename T>
  82. void uninitialized_relocate_n(T* src, int n, T* dest) {
  83. if(n == 0) return;
  84. if constexpr(is_trivially_relocatable_v<T>) {
  85. if constexpr(may_alias) {
  86. std::memmove(dest, src, sizeof(T) * n);
  87. } else {
  88. std::memcpy(dest, src, sizeof(T) * n);
  89. }
  90. } else {
  91. if constexpr(backward) {
  92. for(int i = n - 1; i >= 0; i--) {
  93. new (dest + i) T(std::move(*(src + i)));
  94. (src + i)->~T();
  95. }
  96. } else {
  97. for(int i = 0; i < n; i++) {
  98. new (dest + i) T(std::move(*(src + i)));
  99. (src + i)->~T();
  100. }
  101. }
  102. }
  103. }
  104. template <typename T>
  105. struct vector {
  106. T* _data;
  107. int _capacity;
  108. int _size;
  109. using size_type = int;
  110. vector() : _data(nullptr), _capacity(0), _size(0) {}
  111. vector(int size) : _data((T*)std::malloc(sizeof(T) * size)), _capacity(size), _size(size) {}
  112. vector(vector&& other) noexcept : _data(other._data), _capacity(other._capacity), _size(other._size) {
  113. other._data = nullptr;
  114. other._capacity = 0;
  115. other._size = 0;
  116. }
  117. vector(const vector& other) = delete;
  118. vector(explicit_copy_t, const vector& other) : _capacity(other._size), _size(other._size) {
  119. _data = (T*)std::malloc(sizeof(T) * _capacity);
  120. uninitialized_copy_n(other._data, _size, _data);
  121. }
  122. // allow move
  123. vector& operator= (vector&& other) noexcept {
  124. if(_data) {
  125. std::destroy(begin(), end());
  126. std::free(_data);
  127. }
  128. new (this) vector(std::move(other));
  129. return *this;
  130. }
  131. // disallow copy
  132. vector& operator= (const vector& other) = delete;
  133. bool empty() const { return _size == 0; }
  134. int size() const { return _size; }
  135. int capacity() const { return _capacity; }
  136. T& back() { return _data[_size - 1]; }
  137. T* begin() const { return _data; }
  138. T* end() const { return _data + _size; }
  139. T* data() const { return _data; }
  140. T& operator[] (int i) { return _data[i]; }
  141. const T& operator[] (int i) const { return _data[i]; }
  142. void clear() {
  143. std::destroy(begin(), end());
  144. _size = 0;
  145. }
  146. void reserve(int cap) {
  147. if(cap < 4) cap = 4; // minimum capacity
  148. if(cap <= capacity()) return;
  149. T* new_data = (T*)std::malloc(sizeof(T) * cap);
  150. uninitialized_relocate_n(_data, _size, new_data);
  151. if(_data) std::free(_data);
  152. _data = new_data;
  153. _capacity = cap;
  154. }
  155. template <typename... Args>
  156. void emplace_back(Args&&... args) {
  157. if(_size == _capacity) reserve(_capacity * 2);
  158. new (_data + _size) T(std::forward<Args>(args)...);
  159. _size++;
  160. }
  161. void push_back(const T& t) { emplace_back(t); }
  162. void push_back(T&& t) { emplace_back(std::move(t)); }
  163. bool contains(const T& t) const {
  164. for(int i = 0; i < _size; i++) {
  165. if(_data[i] == t) return true;
  166. }
  167. return false;
  168. }
  169. void extend(const T* begin, const T* end) {
  170. int n = end - begin;
  171. reserve(_size + n);
  172. uninitialized_copy_n(begin, n, _data + _size);
  173. _size += n;
  174. }
  175. void insert(const T* it, const T& t) {
  176. assert(it >= begin() && it <= end());
  177. int pos = it - begin();
  178. if(_size == _capacity) {
  179. int new_capacity = (_capacity == 0) ? 4 : _capacity * 2;
  180. T* new_data = (T*)std::malloc(sizeof(T) * new_capacity);
  181. uninitialized_relocate_n(_data, pos, new_data);
  182. new (new_data + pos) T(t);
  183. uninitialized_relocate_n(_data + pos, _size - pos, new_data + pos + 1);
  184. if(_data) std::free(_data);
  185. _data = new_data;
  186. _capacity = new_capacity;
  187. } else {
  188. uninitialized_relocate_n<true, true>(_data + pos, _size - pos, _data + pos + 1);
  189. new (_data + pos) T(t);
  190. }
  191. _size++;
  192. }
  193. void erase(T* it) {
  194. assert(it >= begin() && it < end());
  195. int pos = it - begin();
  196. _data[pos].~T();
  197. uninitialized_relocate_n<true>(_data + pos + 1, _size - pos, _data + pos);
  198. _size--;
  199. }
  200. void pop_back() {
  201. assert(_size > 0);
  202. _size--;
  203. _data[_size].~T();
  204. }
  205. T popx_back() {
  206. T retval = std::move(back());
  207. pop_back();
  208. return retval;
  209. }
  210. std::pair<T*, int> detach() noexcept {
  211. std::pair<T*, int> retval(_data, _size);
  212. _data = nullptr;
  213. _capacity = 0;
  214. _size = 0;
  215. return retval;
  216. }
  217. void swap(vector& other) {
  218. std::swap(_data, other._data);
  219. std::swap(_capacity, other._capacity);
  220. std::swap(_size, other._size);
  221. }
  222. ~vector() {
  223. if(_data) {
  224. std::destroy(begin(), end());
  225. std::free(_data);
  226. }
  227. }
  228. };
  229. template <typename T, std::size_t N>
  230. struct small_vector {
  231. alignas(T) char _buffer[sizeof(T) * N];
  232. T* _begin;
  233. T* _end;
  234. T* _capacity;
  235. [[nodiscard]] bool is_small() const { return _begin == reinterpret_cast<const T*>(_buffer); }
  236. [[nodiscard]] int size() const { return _end - _begin; }
  237. [[nodiscard]] int capacity() const { return _capacity - _begin; }
  238. [[nodiscard]] bool empty() const { return _begin == _end; }
  239. [[nodiscard]] T* data() const { return _begin; }
  240. [[nodiscard]] T* begin() const { return _begin; }
  241. [[nodiscard]] T* end() const { return _end; }
  242. [[nodiscard]] T& back() const { return *(end() - 1); }
  243. [[nodiscard]] T& operator[] (int index) { return _begin[index]; }
  244. [[nodiscard]] const T& operator[] (int index) const { return _begin[index]; }
  245. small_vector() : _begin(reinterpret_cast<T*>(_buffer)), _end(_begin), _capacity(_begin + N) {}
  246. small_vector(const small_vector& other) noexcept {
  247. const auto size = other.size();
  248. const auto capacity = other.capacity();
  249. _begin = reinterpret_cast<T*>(other.is_small() ? _buffer : std::malloc(sizeof(T) * capacity));
  250. uninitialized_copy_n(other._begin, size, this->_begin);
  251. _end = _begin + size;
  252. _capacity = _begin + capacity;
  253. }
  254. small_vector(small_vector&& other) noexcept {
  255. if(other.is_small()) {
  256. _begin = reinterpret_cast<T*>(_buffer);
  257. uninitialized_relocate_n((T*)other._buffer, other.size(), (T*)_buffer);
  258. _end = _begin + other.size();
  259. _capacity = _begin + N;
  260. } else {
  261. _begin = other._begin;
  262. _end = other._end;
  263. _capacity = other._capacity;
  264. }
  265. other._begin = reinterpret_cast<T*>(other._buffer);
  266. other._end = other._begin;
  267. other._capacity = other._begin + N;
  268. }
  269. small_vector& operator= (const small_vector& other) noexcept {
  270. if(this != &other) {
  271. ~small_vector();
  272. ::new (this) small_vector(other);
  273. }
  274. return *this;
  275. }
  276. small_vector& operator= (small_vector&& other) noexcept {
  277. if(this != &other) {
  278. ~small_vector();
  279. ::new (this) small_vector(std::move(other));
  280. }
  281. return *this;
  282. }
  283. ~small_vector() {
  284. std::destroy(_begin, _end);
  285. if(!is_small()) std::free(_begin);
  286. }
  287. template <typename... Args>
  288. void emplace_back(Args&&... args) noexcept {
  289. if(_end == _capacity) {
  290. const auto new_capacity = capacity() * 2;
  291. const auto size = this->size();
  292. auto new_data = (T*)std::malloc(sizeof(T) * new_capacity);
  293. uninitialized_relocate_n(_begin, size, new_data);
  294. if(!is_small()) std::free(_begin);
  295. _begin = new_data;
  296. _end = _begin + size;
  297. _capacity = _begin + new_capacity;
  298. }
  299. ::new (_end) T(std::forward<Args>(args)...);
  300. _end++;
  301. }
  302. void push_back(const T& value) { emplace_back(value); }
  303. void push_back(T&& value) { emplace_back(std::move(value)); }
  304. void pop_back() {
  305. _end--;
  306. _end->~T();
  307. }
  308. void clear() {
  309. std::destroy(_begin, _end);
  310. _end = _begin;
  311. }
  312. };
  313. template <typename T, std::size_t N>
  314. class small_vector_2 : public small_vector<T, N> {
  315. public:
  316. small_vector_2() = default;
  317. small_vector_2(const small_vector_2& other) = delete;
  318. small_vector_2& operator= (const small_vector_2& other) = delete;
  319. small_vector_2(small_vector_2&& other) = delete;
  320. small_vector_2& operator= (small_vector_2&& other) = delete;
  321. };
  322. template <typename K, typename V>
  323. struct small_map {
  324. struct Item {
  325. K first;
  326. V second;
  327. bool operator< (const K& other) const { return first < other; }
  328. bool operator< (const Item& other) const { return first < other.first; }
  329. };
  330. vector<Item> _data;
  331. small_map() = default;
  332. using size_type = int;
  333. int size() const { return _data.size(); }
  334. bool empty() const { return _data.empty(); }
  335. Item* begin() const { return _data.begin(); }
  336. Item* end() const { return _data.end(); }
  337. Item* data() const { return _data.data(); }
  338. void insert(const K& key, const V& value) {
  339. Item* it = std::lower_bound(_data.begin(), _data.end(), key);
  340. assert(it == _data.end() || it->first != key);
  341. _data.insert(it, {key, value});
  342. }
  343. V* try_get(const K& key) const {
  344. auto it = std::lower_bound(_data.begin(), _data.end(), key);
  345. if(it == _data.end() || it->first != key) return nullptr;
  346. return &it->second;
  347. }
  348. bool contains(const K& key) const { return try_get(key) != nullptr; }
  349. void clear() { _data.clear(); }
  350. const V& operator[] (const K& key) const {
  351. auto it = try_get(key);
  352. assert(it != nullptr);
  353. return *it;
  354. }
  355. };
  356. } // namespace pkpy