paged_vector.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. #pragma once
  2. #include <util/generic/ptr.h>
  3. #include <util/generic/vector.h>
  4. #include <util/generic/yexception.h>
  5. #include <iterator>
  6. namespace NPagedVector {
  7. template <class T, ui32 PageSize = 1u << 20u, class A = std::allocator<T>>
  8. class TPagedVector;
  9. namespace NPrivate {
  10. template <class T, class TT, ui32 PageSize, class A>
  11. struct TPagedVectorIterator {
  12. private:
  13. friend class TPagedVector<TT, PageSize, A>;
  14. typedef TPagedVector<TT, PageSize, A> TVec;
  15. typedef TPagedVectorIterator<T, TT, PageSize, A> TSelf;
  16. size_t Offset;
  17. TVec* Vector;
  18. template <class T1, class TT1, ui32 PageSize1, class A1>
  19. friend struct TPagedVectorIterator;
  20. public:
  21. TPagedVectorIterator()
  22. : Offset()
  23. , Vector()
  24. {
  25. }
  26. TPagedVectorIterator(TVec* vector, size_t offset)
  27. : Offset(offset)
  28. , Vector(vector)
  29. {
  30. }
  31. template <class T1, class TT1, ui32 PageSize1, class A1>
  32. TPagedVectorIterator(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it)
  33. : Offset(it.Offset)
  34. , Vector(it.Vector)
  35. {
  36. }
  37. T& operator*() const {
  38. return (*Vector)[Offset];
  39. }
  40. T* operator->() const {
  41. return &(**this);
  42. }
  43. template <class T1, class TT1, ui32 PageSize1, class A1>
  44. bool operator==(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const {
  45. return Offset == it.Offset;
  46. }
  47. template <class T1, class TT1, ui32 PageSize1, class A1>
  48. bool operator!=(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const {
  49. return !(*this == it);
  50. }
  51. template <class T1, class TT1, ui32 PageSize1, class A1>
  52. bool operator<(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const {
  53. return Offset < it.Offset;
  54. }
  55. template <class T1, class TT1, ui32 PageSize1, class A1>
  56. bool operator<=(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const {
  57. return Offset <= it.Offset;
  58. }
  59. template <class T1, class TT1, ui32 PageSize1, class A1>
  60. bool operator>(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const {
  61. return !(*this <= it);
  62. }
  63. template <class T1, class TT1, ui32 PageSize1, class A1>
  64. bool operator>=(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const {
  65. return !(*this < it);
  66. }
  67. template <class T1, class TT1, ui32 PageSize1, class A1>
  68. ptrdiff_t operator-(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const {
  69. return Offset - it.Offset;
  70. }
  71. TSelf& operator+=(ptrdiff_t off) {
  72. Offset += off;
  73. return *this;
  74. }
  75. TSelf& operator-=(ptrdiff_t off) {
  76. return this->operator+=(-off);
  77. }
  78. TSelf& operator++() {
  79. return this->operator+=(1);
  80. }
  81. TSelf& operator--() {
  82. return this->operator+=(-1);
  83. }
  84. TSelf operator++(int) {
  85. TSelf it = *this;
  86. this->operator+=(1);
  87. return it;
  88. }
  89. TSelf operator--(int) {
  90. TSelf it = *this;
  91. this->operator+=(-1);
  92. return it;
  93. }
  94. TSelf operator+(ptrdiff_t off) const {
  95. TSelf res = *this;
  96. res += off;
  97. return res;
  98. }
  99. TSelf operator-(ptrdiff_t off) const {
  100. return this->operator+(-off);
  101. }
  102. size_t GetOffset() const {
  103. return Offset;
  104. }
  105. };
  106. }
  107. }
  108. namespace std {
  109. template <class T, class TT, ui32 PageSize, class A>
  110. struct iterator_traits<NPagedVector::NPrivate::TPagedVectorIterator<T, TT, PageSize, A>> {
  111. typedef ptrdiff_t difference_type;
  112. typedef T value_type;
  113. typedef T* pointer;
  114. typedef T& reference;
  115. typedef random_access_iterator_tag iterator_category;
  116. };
  117. }
  118. namespace NPagedVector {
  119. //2-level radix tree
  120. template <class T, ui32 PageSize, class A>
  121. class TPagedVector: private TVector<TSimpleSharedPtr<TVector<T, A>>, A> {
  122. static_assert(PageSize, "expect PageSize");
  123. typedef TVector<T, A> TPage;
  124. typedef TVector<TSimpleSharedPtr<TPage>, A> TPages;
  125. typedef TPagedVector<T, PageSize, A> TSelf;
  126. public:
  127. typedef NPrivate::TPagedVectorIterator<T, T, PageSize, A> iterator;
  128. typedef NPrivate::TPagedVectorIterator<const T, T, PageSize, A> const_iterator;
  129. typedef std::reverse_iterator<iterator> reverse_iterator;
  130. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  131. typedef T value_type;
  132. typedef value_type& reference;
  133. typedef const value_type& const_reference;
  134. TPagedVector() = default;
  135. template <typename TIter>
  136. TPagedVector(TIter b, TIter e) {
  137. append(b, e);
  138. }
  139. iterator begin() {
  140. return iterator(this, 0);
  141. }
  142. const_iterator begin() const {
  143. return const_iterator((TSelf*)this, 0);
  144. }
  145. iterator end() {
  146. return iterator(this, size());
  147. }
  148. const_iterator end() const {
  149. return const_iterator((TSelf*)this, size());
  150. }
  151. reverse_iterator rbegin() {
  152. return reverse_iterator(end());
  153. }
  154. const_reverse_iterator rbegin() const {
  155. return const_reverse_iterator(end());
  156. }
  157. reverse_iterator rend() {
  158. return reverse_iterator(begin());
  159. }
  160. const_reverse_iterator rend() const {
  161. return const_reverse_iterator(begin());
  162. }
  163. void swap(TSelf& v) {
  164. TPages::swap((TPages&)v);
  165. }
  166. private:
  167. static size_t PageNumber(size_t idx) {
  168. return idx / PageSize;
  169. }
  170. static size_t InPageIndex(size_t idx) {
  171. return idx % PageSize;
  172. }
  173. static size_t Index(size_t pnum, size_t poff) {
  174. return pnum * PageSize + poff;
  175. }
  176. TPage& PageAt(size_t pnum) const {
  177. return *TPages::at(pnum);
  178. }
  179. TPage& CurrentPage() const {
  180. return *TPages::back();
  181. }
  182. size_t CurrentPageSize() const {
  183. return TPages::empty() ? 0 : CurrentPage().size();
  184. }
  185. size_t NPages() const {
  186. return TPages::size();
  187. }
  188. void AllocateNewPage() {
  189. TPages::push_back(new TPage());
  190. CurrentPage().reserve(PageSize);
  191. }
  192. void MakeNewPage() {
  193. AllocateNewPage();
  194. CurrentPage().resize(PageSize);
  195. }
  196. void PrepareAppend() {
  197. if (TPages::empty() || CurrentPage().size() + 1 > PageSize)
  198. AllocateNewPage();
  199. }
  200. public:
  201. size_t size() const {
  202. return empty() ? 0 : (NPages() - 1) * PageSize + CurrentPage().size();
  203. }
  204. bool empty() const {
  205. return TPages::empty() || (1 == NPages() && CurrentPage().empty());
  206. }
  207. explicit operator bool() const noexcept {
  208. return !empty();
  209. }
  210. template<typename... Args>
  211. reference emplace_back(Args&&... args) {
  212. PrepareAppend();
  213. return CurrentPage().emplace_back(std::forward<Args>(args)...);
  214. }
  215. void push_back(const_reference t) {
  216. PrepareAppend();
  217. CurrentPage().push_back(t);
  218. }
  219. void pop_back() {
  220. if (CurrentPage().empty())
  221. TPages::pop_back();
  222. CurrentPage().pop_back();
  223. }
  224. template <typename TIter>
  225. void append(TIter b, TIter e) {
  226. size_t sz = e - b;
  227. size_t sz1 = Min<size_t>(sz, PageSize - CurrentPageSize());
  228. size_t sz2 = (sz - sz1) / PageSize;
  229. size_t sz3 = (sz - sz1) % PageSize;
  230. if (sz1) {
  231. PrepareAppend();
  232. TPage& p = CurrentPage();
  233. p.insert(p.end(), b, b + sz1);
  234. }
  235. for (size_t i = 0; i < sz2; ++i) {
  236. AllocateNewPage();
  237. TPage& p = CurrentPage();
  238. p.insert(p.end(), b + sz1 + i * PageSize, b + sz1 + (i + 1) * PageSize);
  239. }
  240. if (sz3) {
  241. AllocateNewPage();
  242. TPage& p = CurrentPage();
  243. p.insert(p.end(), b + sz1 + sz2 * PageSize, e);
  244. }
  245. }
  246. iterator erase(iterator it) {
  247. size_t pnum = PageNumber(it.Offset);
  248. size_t pidx = InPageIndex(it.Offset);
  249. if (CurrentPage().empty())
  250. TPages::pop_back();
  251. for (size_t p = NPages() - 1; p > pnum; --p) {
  252. PageAt(p - 1).push_back(PageAt(p).front());
  253. PageAt(p).erase(PageAt(p).begin());
  254. }
  255. PageAt(pnum).erase(PageAt(pnum).begin() + pidx);
  256. return it;
  257. }
  258. iterator erase(iterator b, iterator e) {
  259. // todo : suboptimal!
  260. while (b != e) {
  261. b = erase(b);
  262. --e;
  263. }
  264. return b;
  265. }
  266. iterator insert(iterator it, const value_type& v) {
  267. size_t pnum = PageNumber(it.Offset);
  268. size_t pidx = InPageIndex(it.Offset);
  269. PrepareAppend();
  270. for (size_t p = NPages() - 1; p > pnum; --p) {
  271. PageAt(p).insert(PageAt(p).begin(), PageAt(p - 1).back());
  272. PageAt(p - 1).pop_back();
  273. }
  274. PageAt(pnum).insert(PageAt(pnum).begin() + pidx, v);
  275. return it;
  276. }
  277. template <typename TIter>
  278. void insert(iterator it, TIter b, TIter e) {
  279. // todo : suboptimal!
  280. for (; b != e; ++b, ++it)
  281. it = insert(it, *b);
  282. }
  283. reference front() {
  284. return TPages::front()->front();
  285. }
  286. const_reference front() const {
  287. return TPages::front()->front();
  288. }
  289. reference back() {
  290. return CurrentPage().back();
  291. }
  292. const_reference back() const {
  293. return CurrentPage().back();
  294. }
  295. void clear() {
  296. TPages::clear();
  297. }
  298. void resize(size_t sz) {
  299. if (sz == size())
  300. return;
  301. const size_t npages = NPages();
  302. const size_t newwholepages = sz / PageSize;
  303. const size_t pagepart = sz % PageSize;
  304. const size_t newpages = newwholepages + bool(pagepart);
  305. if (npages && newwholepages >= npages)
  306. CurrentPage().resize(PageSize);
  307. if (newpages < npages)
  308. TPages::resize(newpages);
  309. else
  310. for (size_t i = npages; i < newpages; ++i)
  311. MakeNewPage();
  312. if (pagepart)
  313. CurrentPage().resize(pagepart);
  314. Y_ABORT_UNLESS(sz == size(), "%" PRIu64 " %" PRIu64, (ui64)sz, (ui64)size());
  315. }
  316. reference at(size_t idx) {
  317. return TPages::at(PageNumber(idx))->at(InPageIndex(idx));
  318. }
  319. const_reference at(size_t idx) const {
  320. return TPages::at(PageNumber(idx))->at(InPageIndex(idx));
  321. }
  322. reference operator[](size_t idx) {
  323. return TPages::operator[](PageNumber(idx))->operator[](InPageIndex(idx));
  324. }
  325. const_reference operator[](size_t idx) const {
  326. return TPages::operator[](PageNumber(idx))->operator[](InPageIndex(idx));
  327. }
  328. friend bool operator==(const TSelf& a, const TSelf& b) {
  329. return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
  330. }
  331. friend bool operator<(const TSelf& a, const TSelf& b) {
  332. return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
  333. }
  334. };
  335. namespace NPrivate {
  336. typedef std::is_same<std::random_access_iterator_tag, std::iterator_traits<
  337. TPagedVector<ui32>::iterator>::iterator_category>
  338. TIteratorCheck;
  339. static_assert(TIteratorCheck::value, "expect TIteratorCheck::Result");
  340. }
  341. }