123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- #pragma once
- #include <util/generic/ptr.h>
- #include <util/generic/vector.h>
- #include <util/generic/yexception.h>
- #include <iterator>
- namespace NPagedVector {
- template <class T, ui32 PageSize = 1u << 20u, class A = std::allocator<T>>
- class TPagedVector;
- namespace NPrivate {
- template <class T, class TT, ui32 PageSize, class A>
- struct TPagedVectorIterator {
- private:
- friend class TPagedVector<TT, PageSize, A>;
- typedef TPagedVector<TT, PageSize, A> TVec;
- typedef TPagedVectorIterator<T, TT, PageSize, A> TSelf;
- size_t Offset;
- TVec* Vector;
- template <class T1, class TT1, ui32 PageSize1, class A1>
- friend struct TPagedVectorIterator;
- public:
- TPagedVectorIterator()
- : Offset()
- , Vector()
- {
- }
- TPagedVectorIterator(TVec* vector, size_t offset)
- : Offset(offset)
- , Vector(vector)
- {
- }
- template <class T1, class TT1, ui32 PageSize1, class A1>
- TPagedVectorIterator(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it)
- : Offset(it.Offset)
- , Vector(it.Vector)
- {
- }
- T& operator*() const {
- return (*Vector)[Offset];
- }
- T* operator->() const {
- return &(**this);
- }
- template <class T1, class TT1, ui32 PageSize1, class A1>
- bool operator==(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const {
- return Offset == it.Offset;
- }
- template <class T1, class TT1, ui32 PageSize1, class A1>
- bool operator!=(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const {
- return !(*this == it);
- }
- template <class T1, class TT1, ui32 PageSize1, class A1>
- bool operator<(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const {
- return Offset < it.Offset;
- }
- template <class T1, class TT1, ui32 PageSize1, class A1>
- bool operator<=(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const {
- return Offset <= it.Offset;
- }
- template <class T1, class TT1, ui32 PageSize1, class A1>
- bool operator>(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const {
- return !(*this <= it);
- }
- template <class T1, class TT1, ui32 PageSize1, class A1>
- bool operator>=(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const {
- return !(*this < it);
- }
- template <class T1, class TT1, ui32 PageSize1, class A1>
- ptrdiff_t operator-(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const {
- return Offset - it.Offset;
- }
- TSelf& operator+=(ptrdiff_t off) {
- Offset += off;
- return *this;
- }
- TSelf& operator-=(ptrdiff_t off) {
- return this->operator+=(-off);
- }
- TSelf& operator++() {
- return this->operator+=(1);
- }
- TSelf& operator--() {
- return this->operator+=(-1);
- }
- TSelf operator++(int) {
- TSelf it = *this;
- this->operator+=(1);
- return it;
- }
- TSelf operator--(int) {
- TSelf it = *this;
- this->operator+=(-1);
- return it;
- }
- TSelf operator+(ptrdiff_t off) const {
- TSelf res = *this;
- res += off;
- return res;
- }
- TSelf operator-(ptrdiff_t off) const {
- return this->operator+(-off);
- }
- size_t GetOffset() const {
- return Offset;
- }
- };
- }
- }
- namespace std {
- template <class T, class TT, ui32 PageSize, class A>
- struct iterator_traits<NPagedVector::NPrivate::TPagedVectorIterator<T, TT, PageSize, A>> {
- typedef ptrdiff_t difference_type;
- typedef T value_type;
- typedef T* pointer;
- typedef T& reference;
- typedef random_access_iterator_tag iterator_category;
- };
- }
- namespace NPagedVector {
- //2-level radix tree
- template <class T, ui32 PageSize, class A>
- class TPagedVector: private TVector<TSimpleSharedPtr<TVector<T, A>>, A> {
- static_assert(PageSize, "expect PageSize");
- typedef TVector<T, A> TPage;
- typedef TVector<TSimpleSharedPtr<TPage>, A> TPages;
- typedef TPagedVector<T, PageSize, A> TSelf;
- public:
- typedef NPrivate::TPagedVectorIterator<T, T, PageSize, A> iterator;
- typedef NPrivate::TPagedVectorIterator<const T, T, PageSize, A> const_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- typedef T value_type;
- typedef value_type& reference;
- typedef const value_type& const_reference;
- TPagedVector() = default;
- template <typename TIter>
- TPagedVector(TIter b, TIter e) {
- append(b, e);
- }
- iterator begin() {
- return iterator(this, 0);
- }
- const_iterator begin() const {
- return const_iterator((TSelf*)this, 0);
- }
- iterator end() {
- return iterator(this, size());
- }
- const_iterator end() const {
- return const_iterator((TSelf*)this, size());
- }
- reverse_iterator rbegin() {
- return reverse_iterator(end());
- }
- const_reverse_iterator rbegin() const {
- return const_reverse_iterator(end());
- }
- reverse_iterator rend() {
- return reverse_iterator(begin());
- }
- const_reverse_iterator rend() const {
- return const_reverse_iterator(begin());
- }
- void swap(TSelf& v) {
- TPages::swap((TPages&)v);
- }
- private:
- static size_t PageNumber(size_t idx) {
- return idx / PageSize;
- }
- static size_t InPageIndex(size_t idx) {
- return idx % PageSize;
- }
- static size_t Index(size_t pnum, size_t poff) {
- return pnum * PageSize + poff;
- }
- TPage& PageAt(size_t pnum) const {
- return *TPages::at(pnum);
- }
- TPage& CurrentPage() const {
- return *TPages::back();
- }
- size_t CurrentPageSize() const {
- return TPages::empty() ? 0 : CurrentPage().size();
- }
- size_t NPages() const {
- return TPages::size();
- }
- void AllocateNewPage() {
- TPages::push_back(new TPage());
- CurrentPage().reserve(PageSize);
- }
- void MakeNewPage() {
- AllocateNewPage();
- CurrentPage().resize(PageSize);
- }
- void PrepareAppend() {
- if (TPages::empty() || CurrentPage().size() + 1 > PageSize)
- AllocateNewPage();
- }
- public:
- size_t size() const {
- return empty() ? 0 : (NPages() - 1) * PageSize + CurrentPage().size();
- }
- bool empty() const {
- return TPages::empty() || (1 == NPages() && CurrentPage().empty());
- }
- explicit operator bool() const noexcept {
- return !empty();
- }
- template<typename... Args>
- reference emplace_back(Args&&... args) {
- PrepareAppend();
- return CurrentPage().emplace_back(std::forward<Args>(args)...);
- }
- void push_back(const_reference t) {
- PrepareAppend();
- CurrentPage().push_back(t);
- }
- void pop_back() {
- if (CurrentPage().empty())
- TPages::pop_back();
- CurrentPage().pop_back();
- }
- template <typename TIter>
- void append(TIter b, TIter e) {
- size_t sz = e - b;
- size_t sz1 = Min<size_t>(sz, PageSize - CurrentPageSize());
- size_t sz2 = (sz - sz1) / PageSize;
- size_t sz3 = (sz - sz1) % PageSize;
- if (sz1) {
- PrepareAppend();
- TPage& p = CurrentPage();
- p.insert(p.end(), b, b + sz1);
- }
- for (size_t i = 0; i < sz2; ++i) {
- AllocateNewPage();
- TPage& p = CurrentPage();
- p.insert(p.end(), b + sz1 + i * PageSize, b + sz1 + (i + 1) * PageSize);
- }
- if (sz3) {
- AllocateNewPage();
- TPage& p = CurrentPage();
- p.insert(p.end(), b + sz1 + sz2 * PageSize, e);
- }
- }
- iterator erase(iterator it) {
- size_t pnum = PageNumber(it.Offset);
- size_t pidx = InPageIndex(it.Offset);
- if (CurrentPage().empty())
- TPages::pop_back();
- for (size_t p = NPages() - 1; p > pnum; --p) {
- PageAt(p - 1).push_back(PageAt(p).front());
- PageAt(p).erase(PageAt(p).begin());
- }
- PageAt(pnum).erase(PageAt(pnum).begin() + pidx);
- return it;
- }
- iterator erase(iterator b, iterator e) {
- // todo : suboptimal!
- while (b != e) {
- b = erase(b);
- --e;
- }
- return b;
- }
- iterator insert(iterator it, const value_type& v) {
- size_t pnum = PageNumber(it.Offset);
- size_t pidx = InPageIndex(it.Offset);
- PrepareAppend();
- for (size_t p = NPages() - 1; p > pnum; --p) {
- PageAt(p).insert(PageAt(p).begin(), PageAt(p - 1).back());
- PageAt(p - 1).pop_back();
- }
- PageAt(pnum).insert(PageAt(pnum).begin() + pidx, v);
- return it;
- }
- template <typename TIter>
- void insert(iterator it, TIter b, TIter e) {
- // todo : suboptimal!
- for (; b != e; ++b, ++it)
- it = insert(it, *b);
- }
- reference front() {
- return TPages::front()->front();
- }
- const_reference front() const {
- return TPages::front()->front();
- }
- reference back() {
- return CurrentPage().back();
- }
- const_reference back() const {
- return CurrentPage().back();
- }
- void clear() {
- TPages::clear();
- }
- void resize(size_t sz) {
- if (sz == size())
- return;
- const size_t npages = NPages();
- const size_t newwholepages = sz / PageSize;
- const size_t pagepart = sz % PageSize;
- const size_t newpages = newwholepages + bool(pagepart);
- if (npages && newwholepages >= npages)
- CurrentPage().resize(PageSize);
- if (newpages < npages)
- TPages::resize(newpages);
- else
- for (size_t i = npages; i < newpages; ++i)
- MakeNewPage();
- if (pagepart)
- CurrentPage().resize(pagepart);
- Y_ABORT_UNLESS(sz == size(), "%" PRIu64 " %" PRIu64, (ui64)sz, (ui64)size());
- }
- reference at(size_t idx) {
- return TPages::at(PageNumber(idx))->at(InPageIndex(idx));
- }
- const_reference at(size_t idx) const {
- return TPages::at(PageNumber(idx))->at(InPageIndex(idx));
- }
- reference operator[](size_t idx) {
- return TPages::operator[](PageNumber(idx))->operator[](InPageIndex(idx));
- }
- const_reference operator[](size_t idx) const {
- return TPages::operator[](PageNumber(idx))->operator[](InPageIndex(idx));
- }
- friend bool operator==(const TSelf& a, const TSelf& b) {
- return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
- }
- friend bool operator<(const TSelf& a, const TSelf& b) {
- return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
- }
- };
- namespace NPrivate {
- typedef std::is_same<std::random_access_iterator_tag, std::iterator_traits<
- TPagedVector<ui32>::iterator>::iterator_category>
- TIteratorCheck;
- static_assert(TIteratorCheck::value, "expect TIteratorCheck::Result");
- }
- }
|