#pragma once #include #include namespace NRopeDetails { template class TChunkList { std::deque Chunks; static constexpr size_t MaxInplaceItems = 4; using TInplace = TStackVec; TInplace Inplace; private: template struct TIterator { TChunksIt ChunksIt; TInplaceIt InplaceIt; TIterator() = default; TIterator(TChunksIt chunksIt, TInplaceIt inplaceIt) : ChunksIt(std::move(chunksIt)) , InplaceIt(inplaceIt) {} template TIterator(const TIterator& other) : ChunksIt(other.ChunksIt) , InplaceIt(other.InplaceIt) {} TIterator(const TIterator&) = default; TIterator(TIterator&&) = default; TIterator& operator =(const TIterator&) = default; TIterator& operator =(TIterator&&) = default; TValue& operator *() const { return InplaceIt != TInplaceIt() ? *InplaceIt : *ChunksIt; } TValue* operator ->() const { return InplaceIt != TInplaceIt() ? &*InplaceIt : &*ChunksIt; } TIterator& operator ++() { if (InplaceIt != TInplaceIt()) { ++InplaceIt; } else { ++ChunksIt; } return *this; } TIterator& operator --() { if (InplaceIt != TInplaceIt()) { --InplaceIt; } else { --ChunksIt; } return *this; } template bool operator ==(const TIterator& other) const { return ChunksIt == other.ChunksIt && InplaceIt == other.InplaceIt; } template bool operator !=(const TIterator& other) const { return ChunksIt != other.ChunksIt || InplaceIt != other.InplaceIt; } }; public: using iterator = TIterator::iterator, typename TInplace::iterator, TChunk>; using const_iterator = TIterator::const_iterator, typename TInplace::const_iterator, const TChunk>; public: TChunkList() = default; TChunkList(const TChunkList& other) = default; TChunkList(TChunkList&& other) = default; TChunkList& operator=(const TChunkList& other) = default; TChunkList& operator=(TChunkList&& other) = default; template void PutToEnd(TArgs&&... args) { InsertBefore(end(), std::forward(args)...); } template iterator InsertBefore(iterator pos, TArgs&&... args) { if (!Inplace) { pos.InplaceIt = Inplace.end(); } if (Chunks.empty() && Inplace.size() < MaxInplaceItems) { return {{}, Inplace.emplace(pos.InplaceIt, std::forward(args)...)}; } else { if (Inplace) { Y_VERIFY_DEBUG(Chunks.empty()); for (auto& item : Inplace) { Chunks.push_back(std::move(item)); } pos.ChunksIt = pos.InplaceIt - Inplace.begin() + Chunks.begin(); Inplace.clear(); } return {Chunks.emplace(pos.ChunksIt, std::forward(args)...), {}}; } } iterator Erase(iterator pos) { if (Inplace) { return {{}, Inplace.erase(pos.InplaceIt)}; } else { return {Chunks.erase(pos.ChunksIt), {}}; } } iterator Erase(iterator first, iterator last) { if (Inplace) { return {{}, Inplace.erase(first.InplaceIt, last.InplaceIt)}; } else { return {Chunks.erase(first.ChunksIt, last.ChunksIt), {}}; } } void EraseFront() { if (Inplace) { Inplace.erase(Inplace.begin()); } else { Chunks.pop_front(); } } void EraseBack() { if (Inplace) { Inplace.pop_back(); } else { Chunks.pop_back(); } } iterator Splice(iterator pos, TChunkList& from, iterator first, iterator last) { if (!Inplace) { pos.InplaceIt = Inplace.end(); } size_t n = 0; for (auto it = first; it != last; ++it, ++n) {} if (Chunks.empty() && Inplace.size() + n <= MaxInplaceItems) { if (first.InplaceIt != typename TInplace::iterator()) { Inplace.insert(pos.InplaceIt, first.InplaceIt, last.InplaceIt); } else { Inplace.insert(pos.InplaceIt, first.ChunksIt, last.ChunksIt); } } else { if (Inplace) { Y_VERIFY_DEBUG(Chunks.empty()); for (auto& item : Inplace) { Chunks.push_back(std::move(item)); } pos.ChunksIt = pos.InplaceIt - Inplace.begin() + Chunks.begin(); Inplace.clear(); } if (first.InplaceIt != typename TInplace::iterator()) { Chunks.insert(pos.ChunksIt, first.InplaceIt, last.InplaceIt); } else { Chunks.insert(pos.ChunksIt, first.ChunksIt, last.ChunksIt); } } return from.Erase(first, last); } operator bool() const { return !Inplace.empty() || !Chunks.empty(); } TChunk& GetFirstChunk() { return Inplace ? Inplace.front() : Chunks.front(); } const TChunk& GetFirstChunk() const { return Inplace ? Inplace.front() : Chunks.front(); } TChunk& GetLastChunk() { return Inplace ? Inplace.back() : Chunks.back(); } iterator begin() { return {Chunks.begin(), Inplace ? Inplace.begin() : typename TInplace::iterator()}; } const_iterator begin() const { return {Chunks.begin(), Inplace ? Inplace.begin() : typename TInplace::const_iterator()}; } iterator end() { return {Chunks.end(), Inplace ? Inplace.end() : typename TInplace::iterator()}; } const_iterator end() const { return {Chunks.end(), Inplace ? Inplace.end() : typename TInplace::const_iterator()}; } }; } // NRopeDetails