diff options
author | Anton Samokhvalov <pg83@yandex.ru> | 2022-02-10 16:45:17 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:17 +0300 |
commit | d3a398281c6fd1d3672036cb2d63f842d2cb28c5 (patch) | |
tree | dd4bd3ca0f36b817e96812825ffaf10d645803f2 /library/cpp/containers | |
parent | 72cb13b4aff9bc9cf22e49251bc8fd143f82538f (diff) | |
download | ydb-d3a398281c6fd1d3672036cb2d63f842d2cb28c5.tar.gz |
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 2 of 2.
Diffstat (limited to 'library/cpp/containers')
73 files changed, 4850 insertions, 4850 deletions
diff --git a/library/cpp/containers/2d_array/2d_array.h b/library/cpp/containers/2d_array/2d_array.h index d57f6e4b2f..9e24650637 100644 --- a/library/cpp/containers/2d_array/2d_array.h +++ b/library/cpp/containers/2d_array/2d_array.h @@ -1,5 +1,5 @@ #pragma once - + #include <util/system/yassert.h> #include <util/generic/algorithm.h> @@ -27,9 +27,9 @@ private: T** PData; size_t XSize; size_t YSize; - + private: - void Copy(const TArray2D& a) { + void Copy(const TArray2D& a) { XSize = a.XSize; YSize = a.YSize; Create(); @@ -46,17 +46,17 @@ private: for (size_t i = 0; i < YSize; i++) PData[i] = Data + i * XSize; } - + public: TArray2D(size_t xsize = 1, size_t ysize = 1) { XSize = xsize; YSize = ysize; Create(); } - TArray2D(const TArray2D& a) { + TArray2D(const TArray2D& a) { Copy(a); } - TArray2D& operator=(const TArray2D& a) { + TArray2D& operator=(const TArray2D& a) { Destroy(); Copy(a); return *this; @@ -73,7 +73,7 @@ public: Create(); } void Clear() { - SetSizes(1, 1); + SetSizes(1, 1); } #ifdef _DEBUG TBoundCheck<T> operator[](size_t i) const { @@ -107,8 +107,8 @@ public: } }; -template <class T> -inline bool operator==(const TArray2D<T>& a, const TArray2D<T>& b) { +template <class T> +inline bool operator==(const TArray2D<T>& a, const TArray2D<T>& b) { if (a.GetXSize() != b.GetXSize() || a.GetYSize() != b.GetYSize()) return false; for (size_t y = 0; y < a.GetYSize(); ++y) { @@ -119,7 +119,7 @@ inline bool operator==(const TArray2D<T>& a, const TArray2D<T>& b) { return true; } -template <class T> -inline bool operator!=(const TArray2D<T>& a, const TArray2D<T>& b) { +template <class T> +inline bool operator!=(const TArray2D<T>& a, const TArray2D<T>& b) { return !(a == b); } diff --git a/library/cpp/containers/2d_array/ya.make b/library/cpp/containers/2d_array/ya.make index c542a46070..71d56b902f 100644 --- a/library/cpp/containers/2d_array/ya.make +++ b/library/cpp/containers/2d_array/ya.make @@ -1,6 +1,6 @@ LIBRARY() -OWNER(kirillovs) +OWNER(kirillovs) SRCS( 2d_array.cpp diff --git a/library/cpp/containers/atomizer/atomizer.cpp b/library/cpp/containers/atomizer/atomizer.cpp index 90d526adb4..7a5f781d99 100644 --- a/library/cpp/containers/atomizer/atomizer.cpp +++ b/library/cpp/containers/atomizer/atomizer.cpp @@ -1 +1 @@ -#include "atomizer.h" +#include "atomizer.h" diff --git a/library/cpp/containers/atomizer/atomizer.h b/library/cpp/containers/atomizer/atomizer.h index 8f9e5c5001..5e40f47ab9 100644 --- a/library/cpp/containers/atomizer/atomizer.h +++ b/library/cpp/containers/atomizer/atomizer.h @@ -1,24 +1,24 @@ #pragma once #include <library/cpp/containers/str_map/str_map.h> - + #include <util/generic/vector.h> #include <util/generic/utility.h> - + #include <utility> -#include <cstdio> - -template <class HashFcn = THash<const char*>, class EqualTo = TEqualTo<const char*>> -class atomizer; - -template <class T, class HashFcn = THash<const char*>, class EqualTo = TEqualTo<const char*>> -class super_atomizer; - +#include <cstdio> + +template <class HashFcn = THash<const char*>, class EqualTo = TEqualTo<const char*>> +class atomizer; + +template <class T, class HashFcn = THash<const char*>, class EqualTo = TEqualTo<const char*>> +class super_atomizer; + template <class HashFcn, class EqualTo> -class atomizer: public string_hash<ui32, HashFcn, EqualTo> { +class atomizer: public string_hash<ui32, HashFcn, EqualTo> { private: TVector<const char*> order; - + public: using iterator = typename string_hash<ui32, HashFcn, EqualTo>::iterator; using const_iterator = typename string_hash<ui32, HashFcn, EqualTo>::const_iterator; @@ -33,84 +33,84 @@ public: using string_hash<ui32, HashFcn, EqualTo>::insert_copy; using string_hash<ui32, HashFcn, EqualTo>::clear_hash; - atomizer() { + atomizer() { order.reserve(HASH_SIZE_DEFAULT); } atomizer(size_type hash_size, pool_size_type pool_size) - : string_hash<ui32, HashFcn, EqualTo>(hash_size, pool_size) + : string_hash<ui32, HashFcn, EqualTo>(hash_size, pool_size) { order.reserve(hash_size); } ~atomizer() = default; - ui32 string_to_atom(const char* key) { - const char* old_begin = pool.Begin(); - const char* old_end = pool.End(); + ui32 string_to_atom(const char* key) { + const char* old_begin = pool.Begin(); + const char* old_end = pool.End(); std::pair<iterator, bool> ins = insert_copy(key, ui32(size() + 1)); - if (ins.second) { // new? - if (pool.Begin() != old_begin) // repoint? + if (ins.second) { // new? + if (pool.Begin() != old_begin) // repoint? for (TVector<const char*>::iterator ptr = order.begin(); ptr != order.end(); ++ptr) if (old_begin <= *ptr && *ptr < old_end) // from old pool? - *ptr += pool.Begin() - old_begin; + *ptr += pool.Begin() - old_begin; order.push_back((*ins.first).first); // copy of 'key' } return (ui32)(*ins.first).second; } - ui32 perm_string_to_atom(const char* key) { - value_type val(key, ui32(size() + 1)); + ui32 perm_string_to_atom(const char* key) { + value_type val(key, ui32(size() + 1)); std::pair<iterator, bool> ins = this->insert(val); if (ins.second) order.push_back((*ins.first).first); // == copy of 'key' - return (ui32)(*ins.first).second; // == size()+1 + return (ui32)(*ins.first).second; // == size()+1 } - ui32 find_atom(const char* key) const { + ui32 find_atom(const char* key) const { const_iterator it = find(key); if (it == end()) return 0; // INVALID_ATOM else return (ui32)(*it).second; } - const char* get_atom_name(ui32 atom) const { + const char* get_atom_name(ui32 atom) const { if (atom && atom <= size()) - return order[atom - 1]; + return order[atom - 1]; return nullptr; } - void clear_atomizer() { + void clear_atomizer() { clear_hash(); order.clear(); } - void SaveC2N(FILE* f) const { // we write sorted file + void SaveC2N(FILE* f) const { // we write sorted file for (ui32 i = 0; i < order.size(); i++) if (order[i]) - fprintf(f, "%d\t%s\n", i + 1, order[i]); + fprintf(f, "%d\t%s\n", i + 1, order[i]); } - void LoadC2N(FILE* f) { // but can read unsorted one + void LoadC2N(FILE* f) { // but can read unsorted one long k, km = 0; char buf[1000]; - char* s; + char* s; while (fgets(buf, 1000, f)) { k = strtol(buf, &s, 10); - char* endl = strchr(s, '\n'); + char* endl = strchr(s, '\n'); if (endl) *endl = 0; if (k > 0 && k != LONG_MAX) { - km = Max(km, k); + km = Max(km, k); insert_copy(++s, ui32(k)); } } order.resize(km); - memset(&order[0], 0, order.size()); // if some atoms are absent + memset(&order[0], 0, order.size()); // if some atoms are absent for (const_iterator I = this->begin(); I != end(); ++I) order[(*I).second - 1] = (*I).first; } }; template <class T, class HashFcn, class EqualTo> -class super_atomizer: public string_hash<ui32, HashFcn, EqualTo> { +class super_atomizer: public string_hash<ui32, HashFcn, EqualTo> { private: using TOrder = TVector<std::pair<const char*, T>>; TOrder order; - + public: using iterator = typename string_hash<ui32, HashFcn, EqualTo>::iterator; using const_iterator = typename string_hash<ui32, HashFcn, EqualTo>::const_iterator; @@ -129,56 +129,56 @@ public: using string_hash<ui32, HashFcn, EqualTo>::insert_copy; using string_hash<ui32, HashFcn, EqualTo>::clear_hash; - super_atomizer() { + super_atomizer() { order.reserve(HASH_SIZE_DEFAULT); } super_atomizer(size_type hash_size, pool_size_type pool_size) - : string_hash<ui32, HashFcn, EqualTo>(hash_size, pool_size) + : string_hash<ui32, HashFcn, EqualTo>(hash_size, pool_size) { order.reserve(hash_size); } ~super_atomizer() = default; - ui32 string_to_atom(const char* key, const T* atom_data = NULL) { - const char* old_begin = pool.Begin(); - const char* old_end = pool.End(); + ui32 string_to_atom(const char* key, const T* atom_data = NULL) { + const char* old_begin = pool.Begin(); + const char* old_end = pool.End(); std::pair<iterator, bool> ins = insert_copy(key, ui32(size() + 1)); - if (ins.second) { // new? - if (pool.Begin() != old_begin) // repoint? + if (ins.second) { // new? + if (pool.Begin() != old_begin) // repoint? for (typename TOrder::iterator ptr = order.begin(); ptr != order.end(); ++ptr) if (old_begin <= (*ptr).first && (*ptr).first < old_end) // from old pool? - (*ptr).first += pool.Begin() - old_begin; + (*ptr).first += pool.Begin() - old_begin; order.push_back(std::pair<const char*, T>((*ins.first).first, atom_data ? *atom_data : T())); } return (*ins.first).second; } - ui32 perm_string_to_atom(const char* key, const T* atom_data = NULL) { - value_type val(key, ui32(size() + 1)); + ui32 perm_string_to_atom(const char* key, const T* atom_data = NULL) { + value_type val(key, ui32(size() + 1)); std::pair<iterator, bool> ins = this->insert(val); if (ins.second) order.push_back(std::pair<const char*, T>((*ins.first).first, atom_data ? *atom_data : T())); return (*ins.first).second; // == size()+1 } - ui32 find_atom(const char* key) const { + ui32 find_atom(const char* key) const { const_iterator it = find(key); if (it == end()) return 0; // INVALID_ATOM else return (*it).second; } - const char* get_atom_name(ui32 atom) const { + const char* get_atom_name(ui32 atom) const { if (atom && atom <= size()) - return order[atom - 1].first; + return order[atom - 1].first; return nullptr; } const T* get_atom_data(ui32 atom) const { if (atom && atom <= size()) - return &order[atom - 1].second; + return &order[atom - 1].second; return NULL; } T* get_atom_data(ui32 atom) { if (atom && atom <= size()) - return &order[atom - 1].second; + return &order[atom - 1].second; return NULL; } o_iterator o_begin() { @@ -193,7 +193,7 @@ public: o_const_iterator o_end() const { return order.end(); } - void clear_atomizer() { + void clear_atomizer() { clear_hash(); order.clear(); } diff --git a/library/cpp/containers/atomizer/ya.make b/library/cpp/containers/atomizer/ya.make index c3ad49fff2..55165a3b67 100644 --- a/library/cpp/containers/atomizer/ya.make +++ b/library/cpp/containers/atomizer/ya.make @@ -1,13 +1,13 @@ -LIBRARY() - +LIBRARY() + OWNER(g:util) - -PEERDIR( + +PEERDIR( library/cpp/containers/str_map -) - -SRCS( - atomizer.cpp -) - -END() +) + +SRCS( + atomizer.cpp +) + +END() diff --git a/library/cpp/containers/bitseq/bititerator.h b/library/cpp/containers/bitseq/bititerator.h index 6eeaec4073..52dadd3798 100644 --- a/library/cpp/containers/bitseq/bititerator.h +++ b/library/cpp/containers/bitseq/bititerator.h @@ -3,7 +3,7 @@ #include "traits.h" #include <library/cpp/pop_count/popcount.h> - + template <typename T> class TBitIterator { public: @@ -15,8 +15,8 @@ public: : Current(0) , Mask(0) , Data(data) - { - } + { + } /// Get the word next to the one we are currenlty iterating over. const TWord* NextWord() const { @@ -49,7 +49,7 @@ public: if (!Mask) return *Data & TTraits::ElemMask(count); - auto usedBits = (size_t)PopCount(Mask - 1); + auto usedBits = (size_t)PopCount(Mask - 1); TWord result = Current >> usedBits; auto leftInCurrent = TTraits::NumBits - usedBits; if (count <= leftInCurrent) @@ -72,7 +72,7 @@ public: return Current & TTraits::ElemMask(count); } - auto usedBits = (size_t)PopCount(Mask - 1); + auto usedBits = (size_t)PopCount(Mask - 1); TWord result = Current >> usedBits; auto leftInCurrent = TTraits::NumBits - usedBits; if (count < leftInCurrent) { @@ -97,7 +97,7 @@ public: if (!count) return; - int leftInCurrent = (size_t)PopCount(~(Mask - 1)); + int leftInCurrent = (size_t)PopCount(~(Mask - 1)); if (count < leftInCurrent) { Mask <<= count; return; diff --git a/library/cpp/containers/bitseq/bititerator_ut.cpp b/library/cpp/containers/bitseq/bititerator_ut.cpp index e5aa5a9184..ed0925866f 100644 --- a/library/cpp/containers/bitseq/bititerator_ut.cpp +++ b/library/cpp/containers/bitseq/bititerator_ut.cpp @@ -12,7 +12,7 @@ Y_UNIT_TEST_SUITE(TBitIteratorTest) { } template <typename TWord> - void AssertPeekRead(TBitIterator<TWord> & iter, ui8 count, TWord expected) { + void AssertPeekRead(TBitIterator<TWord> & iter, ui8 count, TWord expected) { auto peek = iter.Peek(count); auto read = iter.Read(count); UNIT_ASSERT_EQUAL(peek, read); diff --git a/library/cpp/containers/bitseq/bitvector.cpp b/library/cpp/containers/bitseq/bitvector.cpp index 895baeb99b..05cb3a881d 100644 --- a/library/cpp/containers/bitseq/bitvector.cpp +++ b/library/cpp/containers/bitseq/bitvector.cpp @@ -1 +1 @@ -#include "bitvector.h" +#include "bitvector.h" diff --git a/library/cpp/containers/bitseq/bitvector.h b/library/cpp/containers/bitseq/bitvector.h index e5d171a203..3f8fd81ee5 100644 --- a/library/cpp/containers/bitseq/bitvector.h +++ b/library/cpp/containers/bitseq/bitvector.h @@ -3,7 +3,7 @@ #include "traits.h" #include <library/cpp/pop_count/popcount.h> - + #include <util/generic/vector.h> #include <util/ysaveload.h> @@ -78,8 +78,8 @@ public: } void Set(ui64 pos, TWord value, ui8 width, TWord mask) { - if (!width) - return; + if (!width) + return; Y_ASSERT((pos + width) <= Size_); size_t word = pos >> TTraits::DivShift; TWord shift1 = pos & TTraits::ModMask; @@ -87,8 +87,8 @@ public: Data_[word] &= ~(mask << shift1); Data_[word] |= (value & mask) << shift1; if (shift2 < width) { - Data_[word + 1] &= ~(mask >> shift2); - Data_[word + 1] |= (value & mask) >> shift2; + Data_[word + 1] &= ~(mask >> shift2); + Data_[word + 1] |= (value & mask) >> shift2; } } @@ -97,8 +97,8 @@ public: } void Append(TWord value, ui8 width, TWord mask) { - if (!width) - return; + if (!width) + return; if (Data_.size() * TTraits::NumBits < Size_ + width) { Data_.push_back(0); } @@ -113,7 +113,7 @@ public: size_t Count() const { size_t count = 0; for (size_t i = 0; i < Data_.size(); ++i) { - count += (size_t)PopCount(Data_[i]); + count += (size_t)PopCount(Data_[i]); } return count; } @@ -142,7 +142,7 @@ public: ui64 Space() const { return CHAR_BIT * (sizeof(Size_) + - Data_.size() * sizeof(TWord)); + Data_.size() * sizeof(TWord)); } void Print(IOutputStream& out, size_t truncate = 128) { diff --git a/library/cpp/containers/bitseq/readonly_bitvector.h b/library/cpp/containers/bitseq/readonly_bitvector.h index 419e49811e..8612739c3f 100644 --- a/library/cpp/containers/bitseq/readonly_bitvector.h +++ b/library/cpp/containers/bitseq/readonly_bitvector.h @@ -16,8 +16,8 @@ public: TReadonlyBitVector() : Size_() , Data_() - { - } + { + } explicit TReadonlyBitVector(const TBitVector<T>& vector) : Size_(vector.Size_) diff --git a/library/cpp/containers/bitseq/ya.make b/library/cpp/containers/bitseq/ya.make index 758e2bec77..7090956c55 100644 --- a/library/cpp/containers/bitseq/ya.make +++ b/library/cpp/containers/bitseq/ya.make @@ -2,14 +2,14 @@ LIBRARY() OWNER(g:util) -PEERDIR( - util/draft +PEERDIR( + util/draft library/cpp/pop_count -) - -SRCS( - bitvector.cpp +) + +SRCS( + bitvector.cpp readonly_bitvector.cpp -) - +) + END() diff --git a/library/cpp/containers/compact_vector/compact_vector.h b/library/cpp/containers/compact_vector/compact_vector.h index 9e37938546..dbe7473f0c 100644 --- a/library/cpp/containers/compact_vector/compact_vector.h +++ b/library/cpp/containers/compact_vector/compact_vector.h @@ -24,11 +24,11 @@ private: T* Ptr; THeader* Header() { - return ((THeader*)Ptr) - 1; + return ((THeader*)Ptr) - 1; } const THeader* Header() const { - return ((THeader*)Ptr) - 1; + return ((THeader*)Ptr) - 1; } public: @@ -40,8 +40,8 @@ public: TCompactVector() : Ptr(nullptr) - { - } + { + } TCompactVector(const TThis& that) : Ptr(nullptr) @@ -105,7 +105,7 @@ public: void* mem = ::malloc(sizeof(THeader) + newCapacity * sizeof(T)); if (mem == nullptr) ythrow yexception() << "out of memory"; - Ptr = (T*)(((THeader*)mem) + 1); + Ptr = (T*)(((THeader*)mem) + 1); Header()->Size = 0; Header()->Capacity = newCapacity; } else { @@ -197,12 +197,12 @@ public: Clear(); } - T& operator[](size_t index) { + T& operator[](size_t index) { Y_ASSERT(index < Size()); return Ptr[index]; } - const T& operator[](size_t index) const { + const T& operator[](size_t index) const { Y_ASSERT(index < Size()); return Ptr[index]; } diff --git a/library/cpp/containers/comptrie/array_with_size.h b/library/cpp/containers/comptrie/array_with_size.h index 148200fe6a..36e61c7410 100644 --- a/library/cpp/containers/comptrie/array_with_size.h +++ b/library/cpp/containers/comptrie/array_with_size.h @@ -3,19 +3,19 @@ #include <util/generic/ptr.h> #include <util/generic/noncopyable.h> #include <util/generic/utility.h> -#include <util/system/sys_alloc.h> +#include <util/system/sys_alloc.h> template <typename T> -class TArrayWithSizeHolder : TNonCopyable { +class TArrayWithSizeHolder : TNonCopyable { typedef TArrayWithSizeHolder<T> TThis; T* Data; public: - TArrayWithSizeHolder() - : Data(nullptr) - { - } + TArrayWithSizeHolder() + : Data(nullptr) + { + } ~TArrayWithSizeHolder() { if (!Data) @@ -26,7 +26,7 @@ public: } catch (...) { } } - y_deallocate(((size_t*)Data) - 1); + y_deallocate(((size_t*)Data) - 1); } void Swap(TThis& copy) { @@ -37,7 +37,7 @@ public: if (newSize == Size()) return; TThis copy; - copy.Data = (T*)(((size_t*)y_allocate(sizeof(size_t) + sizeof(T) * newSize)) + 1); + copy.Data = (T*)(((size_t*)y_allocate(sizeof(size_t) + sizeof(T) * newSize)) + 1); // does not handle constructor exceptions properly for (size_t i = 0; i < Min(Size(), newSize); ++i) { new (copy.Data + i) T(Data[i]); @@ -45,12 +45,12 @@ public: for (size_t i = Min(Size(), newSize); i < newSize; ++i) { new (copy.Data + i) T; } - ((size_t*)copy.Data)[-1] = newSize; + ((size_t*)copy.Data)[-1] = newSize; Swap(copy); } size_t Size() const { - return Data ? ((size_t*)Data)[-1] : 0; + return Data ? ((size_t*)Data)[-1] : 0; } bool Empty() const { diff --git a/library/cpp/containers/comptrie/chunked_helpers_trie.h b/library/cpp/containers/comptrie/chunked_helpers_trie.h index 6efe55b5f0..cfa35f5ba2 100644 --- a/library/cpp/containers/comptrie/chunked_helpers_trie.h +++ b/library/cpp/containers/comptrie/chunked_helpers_trie.h @@ -13,7 +13,7 @@ public: : Trie(blob) { } - + bool Has(const char* key) const { return Trie.Find(key, strlen(key)); } @@ -23,7 +23,7 @@ public: } }; -template <bool sorted = false> +template <bool sorted = false> class TTrieSetWriter { private: TCompactTrieBuilder<char> Builder; @@ -57,24 +57,24 @@ public: } }; -template <bool isWriter, bool sorted = false> +template <bool isWriter, bool sorted = false> struct TTrieSetG; -template <bool sorted> +template <bool sorted> struct TTrieSetG<false, sorted> { typedef TTrieSet T; }; -template <bool sorted> +template <bool sorted> struct TTrieSetG<true, sorted> { typedef TTrieSetWriter<sorted> T; }; -template <typename T> +template <typename T> class TTrieMap { private: TCompactTrie<char> Trie; - static_assert(sizeof(T) <= sizeof(ui64), "expect sizeof(T) <= sizeof(ui64)"); + static_assert(sizeof(T) <= sizeof(ui64), "expect sizeof(T) <= sizeof(ui64)"); public: TTrieMap(const TBlob& blob) @@ -101,17 +101,17 @@ public: } } - const TCompactTrie<char>& GetTrie() const { + const TCompactTrie<char>& GetTrie() const { return Trie; } }; -template <typename T, bool sorted = false> +template <typename T, bool sorted = false> class TTrieMapWriter { private: typedef TCompactTrieBuilder<char> TBuilder; TBuilder Builder; - static_assert(sizeof(T) <= sizeof(ui64), "expect sizeof(T) <= sizeof(ui64)"); + static_assert(sizeof(T) <= sizeof(ui64), "expect sizeof(T) <= sizeof(ui64)"); #ifndef NDEBUG bool IsSorted; #endif @@ -130,12 +130,12 @@ public: memcpy(&intValue, &value, sizeof(T)); Builder.Add(key, strlen(key), intValue); #ifndef NDEBUG - /* + /* if (!IsSorted) { T test; assert(Get(key, &test) && value == test); } - */ + */ #endif } @@ -177,7 +177,7 @@ public: } }; -template <typename T> +template <typename T> class TTrieSortedMapWriter { private: typedef std::pair<TString, T> TValue; @@ -204,15 +204,15 @@ public: } }; -template <typename X, bool isWriter, bool sorted = false> +template <typename X, bool isWriter, bool sorted = false> struct TTrieMapG; -template <typename X, bool sorted> +template <typename X, bool sorted> struct TTrieMapG<X, false, sorted> { typedef TTrieMap<X> T; }; -template <typename X, bool sorted> +template <typename X, bool sorted> struct TTrieMapG<X, true, sorted> { typedef TTrieMapWriter<X, sorted> T; }; diff --git a/library/cpp/containers/comptrie/comptrie.cpp b/library/cpp/containers/comptrie/comptrie.cpp index 86a006a231..4556e5b571 100644 --- a/library/cpp/containers/comptrie/comptrie.cpp +++ b/library/cpp/containers/comptrie/comptrie.cpp @@ -1,8 +1,8 @@ -#include "comptrie_impl.h" -#include "comptrie.h" -#include "array_with_size.h" -#include "comptrie_trie.h" -#include "comptrie_builder.h" -#include "protopacker.h" -#include "set.h" -#include "chunked_helpers_trie.h" +#include "comptrie_impl.h" +#include "comptrie.h" +#include "array_with_size.h" +#include "comptrie_trie.h" +#include "comptrie_builder.h" +#include "protopacker.h" +#include "set.h" +#include "chunked_helpers_trie.h" diff --git a/library/cpp/containers/comptrie/comptrie_builder.h b/library/cpp/containers/comptrie/comptrie_builder.h index e0364eef9f..cf7d2e39a3 100644 --- a/library/cpp/containers/comptrie/comptrie_builder.h +++ b/library/cpp/containers/comptrie/comptrie_builder.h @@ -26,18 +26,18 @@ enum ECompactTrieBuilderFlags { using TCompactTrieBuilderFlags = ECompactTrieBuilderFlags; -inline TCompactTrieBuilderFlags operator|(TCompactTrieBuilderFlags first, TCompactTrieBuilderFlags second) { +inline TCompactTrieBuilderFlags operator|(TCompactTrieBuilderFlags first, TCompactTrieBuilderFlags second) { return static_cast<TCompactTrieBuilderFlags>(static_cast<int>(first) | second); } -inline TCompactTrieBuilderFlags& operator|=(TCompactTrieBuilderFlags& first, TCompactTrieBuilderFlags second) { +inline TCompactTrieBuilderFlags& operator|=(TCompactTrieBuilderFlags& first, TCompactTrieBuilderFlags second) { return first = first | second; } template <typename T> class TArrayWithSizeHolder; -template <class T = char, class D = ui64, class S = TCompactTriePacker<D>> +template <class T = char, class D = ui64, class S = TCompactTriePacker<D>> class TCompactTrieBuilder { public: typedef T TSymbol; @@ -92,12 +92,12 @@ public: size_t GetEntryCount() const; size_t GetNodeCount() const; - + // Exact output file size in bytes. size_t MeasureByteSize() const { return Impl->MeasureByteSize(); } - + protected: class TCompactTrieBuilderImpl; THolder<TCompactTrieBuilderImpl> Impl; diff --git a/library/cpp/containers/comptrie/comptrie_builder.inl b/library/cpp/containers/comptrie/comptrie_builder.inl index e19f005d7c..f273fa6571 100644 --- a/library/cpp/containers/comptrie/comptrie_builder.inl +++ b/library/cpp/containers/comptrie/comptrie_builder.inl @@ -27,7 +27,7 @@ template <class T, class D, class S> class TCompactTrieBuilder<T, D, S>::TCompactTrieBuilderImpl { protected: - TMemoryPool Pool; + TMemoryPool Pool; size_t PayloadSize; THolder<TFixedSizeAllocator> NodeAllocator; class TNode; @@ -138,7 +138,7 @@ public: Y_ASSERT(reinterpret_cast<ISubtree*>(this) == static_cast<void*>(this)); // This assumption is used in TNode::Subtree() } - iterator Find(char ch); + iterator Find(char ch); const_iterator Find(char ch) const; void Add(const TBlob& s, TNode* node); @@ -422,8 +422,8 @@ public: template <class T, class D, class S> TCompactTrieBuilder<T, D, S>::TCompactTrieBuilder(TCompactTrieBuilderFlags flags, TPacker packer, IAllocator* alloc) : Impl(new TCompactTrieBuilderImpl(flags, packer, alloc)) -{ -} +{ +} template <class T, class D, class S> bool TCompactTrieBuilder<T, D, S>::Add(const TSymbol* key, size_t keylen, const TData& value) { @@ -742,7 +742,7 @@ bool TCompactTrieBuilder<T, D, S>::TCompactTrieBuilderImpl::FindLongestPrefixImp template <class T, class D, class S> void TCompactTrieBuilder<T, D, S>::TCompactTrieBuilderImpl::Clear() { DestroyNode(Root); - Pool.Clear(); + Pool.Clear(); NodeAllocator.Reset(new TFixedSizeAllocator(sizeof(TNode) + PayloadSize, TDefaultAllocator::Instance())); Root = new (*NodeAllocator) TNode; EntryCount = 0; @@ -980,11 +980,11 @@ ui64 TCompactTrieBuilder<T, D, S>::TCompactTrieBuilderImpl::ArcSaveAndDestroy(co template <class T, class D, class S> typename TCompactTrieBuilder<T, D, S>::TCompactTrieBuilderImpl::TNode::TArcSet::iterator TCompactTrieBuilder<T, D, S>::TCompactTrieBuilderImpl::TNode::TArcSet::Find(char ch) { - using namespace NCompTriePrivate; - iterator it = LowerBound(this->begin(), this->end(), ch, TCmp()); - + using namespace NCompTriePrivate; + iterator it = LowerBound(this->begin(), this->end(), ch, TCmp()); + if (it != this->end() && it->Label[0] == (unsigned char)ch) { - return it; + return it; } return this->end(); @@ -1005,7 +1005,7 @@ typename TCompactTrieBuilder<T, D, S>::TCompactTrieBuilderImpl::TNode::TArcSet:: template <class T, class D, class S> void TCompactTrieBuilder<T, D, S>::TCompactTrieBuilderImpl::TNode::TArcSet::Add(const TBlob& s, TNode* node) { - using namespace NCompTriePrivate; + using namespace NCompTriePrivate; this->insert(LowerBound(this->begin(), this->end(), s[0], TCmp()), TArc(s, node)); } diff --git a/library/cpp/containers/comptrie/comptrie_impl.cpp b/library/cpp/containers/comptrie/comptrie_impl.cpp index a293b45d1c..a116ab6d1e 100644 --- a/library/cpp/containers/comptrie/comptrie_impl.cpp +++ b/library/cpp/containers/comptrie/comptrie_impl.cpp @@ -6,34 +6,34 @@ // Unpack the leaf value. The algorithm can store up to 8 full bytes in leafs. namespace NCompactTrie { - size_t MeasureOffset(size_t offset) { - int n = 0; - - while (offset) { - offset >>= 8; - ++n; - } - - return n; + size_t MeasureOffset(size_t offset) { + int n = 0; + + while (offset) { + offset >>= 8; + ++n; + } + + return n; } - - size_t PackOffset(char* buffer, size_t offset) { - size_t len = MeasureOffset(offset); - size_t i = len; - - while (i--) { - buffer[i] = (char)(offset & 0xFF); - offset >>= 8; - } - - return len; + + size_t PackOffset(char* buffer, size_t offset) { + size_t len = MeasureOffset(offset); + size_t i = len; + + while (i--) { + buffer[i] = (char)(offset & 0xFF); + offset >>= 8; + } + + return len; } - - void ShowProgress(size_t n) { - if (n % 1000000 == 0) + + void ShowProgress(size_t n) { + if (n % 1000000 == 0) Cerr << n << ", RSS=" << (TRusage::Get().MaxRss >> 20) << "mb" << Endl; - else if (n % 20000 == 0) - Cerr << "."; - } + else if (n % 20000 == 0) + Cerr << "."; + } } diff --git a/library/cpp/containers/comptrie/comptrie_impl.h b/library/cpp/containers/comptrie/comptrie_impl.h index f4b0bf072e..f41c38311a 100644 --- a/library/cpp/containers/comptrie/comptrie_impl.h +++ b/library/cpp/containers/comptrie/comptrie_impl.h @@ -9,10 +9,10 @@ // NCompactTrie namespace NCompactTrie { - const char MT_FINAL = '\x80'; - const char MT_NEXT = '\x40'; + const char MT_FINAL = '\x80'; + const char MT_NEXT = '\x40'; const char MT_SIZEMASK = '\x07'; - const size_t MT_LEFTSHIFT = 3; + const size_t MT_LEFTSHIFT = 3; const size_t MT_RIGHTSHIFT = 0; Y_FORCE_INLINE size_t UnpackOffset(const char* p, size_t len); @@ -72,22 +72,22 @@ namespace NCompTriePrivate { typedef TUtf32String TResult; }; -} +} -namespace NCompTriePrivate { - struct TCmp { - template <class T> - inline bool operator()(const T& l, const T& r) { +namespace NCompTriePrivate { + struct TCmp { + template <class T> + inline bool operator()(const T& l, const T& r) { return (unsigned char)(l.Label[0]) < (unsigned char)(r.Label[0]); - } - - template <class T> - inline bool operator()(const T& l, char r) { + } + + template <class T> + inline bool operator()(const T& l, char r) { return (unsigned char)(l.Label[0]) < (unsigned char)r; - } - }; -} - + } + }; +} + namespace NCompactTrie { static inline ui64 ArcSaveOffset(size_t offset, IOutputStream& os) { using namespace NCompactTrie; @@ -184,7 +184,7 @@ namespace NCompactTrie { // Returns true if the symbol was succesfully found in the trie, false otherwise. template <typename TSymbol, class TPacker> Y_FORCE_INLINE bool Advance(const char*& datapos, const char* const dataend, const char*& value, - TSymbol label, TPacker packer) { + TSymbol label, TPacker packer) { Y_ASSERT(datapos < dataend); char flags = MT_NEXT; for (int i = (int)ExtraBits<TSymbol>(); i >= 0; i -= 8) { diff --git a/library/cpp/containers/comptrie/comptrie_trie.h b/library/cpp/containers/comptrie/comptrie_trie.h index 1fa8794897..40ec1e52b3 100644 --- a/library/cpp/containers/comptrie/comptrie_trie.h +++ b/library/cpp/containers/comptrie/comptrie_trie.h @@ -29,7 +29,7 @@ template <class TTrie> class TPrefixIterator; // in case of <char> specialization cannot distinguish between "" and "\0" keys -template <class T = char, class D = ui64, class S = TCompactTriePacker<D>> +template <class T = char, class D = ui64, class S = TCompactTriePacker<D>> class TCompactTrie { public: typedef T TSymbol; @@ -56,12 +56,12 @@ public: TCompactTrie(const char* d, size_t len, TPacker packer); TCompactTrie(const char* d, size_t len) - : TCompactTrie{d, len, TPacker{}} { + : TCompactTrie{d, len, TPacker{}} { } TCompactTrie(const TBlob& data, TPacker packer); explicit TCompactTrie(const TBlob& data) - : TCompactTrie{data, TPacker{}} { + : TCompactTrie{data, TPacker{}} { } // Skipper should be initialized with &Packer, not with &other.Packer, so you have to redefine these. @@ -126,7 +126,7 @@ public: bool FindLongestPrefix(const TKeyBuf& key, size_t* prefixLen, TData* value = nullptr, bool* hasNext = nullptr) const { return FindLongestPrefix(key.data(), key.size(), prefixLen, value, hasNext); } - + // Return trie, containing all tails for the given key inline TCompactTrie<T, D, S> FindTails(const TSymbol* key, size_t keylen) const; TCompactTrie<T, D, S> FindTails(const TKeyBuf& key) const { @@ -146,17 +146,17 @@ public: typedef NCompactTrie::TOpaqueTrieIterator TOpaqueTrieIterator; typedef NCompactTrie::TOpaqueTrie TOpaqueTrie; friend class TCompactTrie; - TConstIterator(const TOpaqueTrie& trie, const char* emptyValue, bool atend, TPacker packer); // only usable from Begin() and End() methods + TConstIterator(const TOpaqueTrie& trie, const char* emptyValue, bool atend, TPacker packer); // only usable from Begin() and End() methods TConstIterator(const TOpaqueTrie& trie, const char* emptyValue, const TKeyBuf& key, TPacker packer); // only usable from UpperBound() method public: TConstIterator() = default; - bool IsEmpty() const { - return !Impl; - } // Almost no other method can be called. + bool IsEmpty() const { + return !Impl; + } // Almost no other method can be called. - bool operator==(const TConstIterator& other) const; - bool operator!=(const TConstIterator& other) const; + bool operator==(const TConstIterator& other) const; + bool operator!=(const TConstIterator& other) const; TConstIterator& operator++(); TConstIterator operator++(int /*unused*/); TConstIterator& operator--(); @@ -205,8 +205,8 @@ protected: void LookupPhrases(const char* datapos, size_t len, const TSymbol* key, size_t keylen, TVector<TPhraseMatch>& matches, TSymbol separator) const; }; -template <class T = char, class D = ui64, class S = TCompactTriePacker<D>> -class TCompactTrieHolder: public TCompactTrie<T, D, S>, NNonCopyable::TNonCopyable { +template <class T = char, class D = ui64, class S = TCompactTriePacker<D>> +class TCompactTrieHolder: public TCompactTrie<T, D, S>, NNonCopyable::TNonCopyable { private: typedef TCompactTrie<T, D, S> TBase; TArrayHolder<char> Storage; @@ -239,35 +239,35 @@ TCompactTrie<T, D, S>::TCompactTrie(const char* d, size_t len, TPacker packer) template <class T, class D, class S> TCompactTrie<T, D, S>::TCompactTrie(const char* emptyValue) : EmptyValue(emptyValue) -{ -} +{ +} template <class T, class D, class S> TCompactTrie<T, D, S>::TCompactTrie(const TBlob& data, const char* emptyValue, TPacker packer) : DataHolder(data) , EmptyValue(emptyValue) , Packer(packer) -{ -} +{ +} template <class T, class D, class S> TCompactTrie<T, D, S>::TCompactTrie(const TCompactTrie& other) - : DataHolder(other.DataHolder) - , EmptyValue(other.EmptyValue) - , Packer(other.Packer) -{ -} + : DataHolder(other.DataHolder) + , EmptyValue(other.EmptyValue) + , Packer(other.Packer) +{ +} template <class T, class D, class S> TCompactTrie<T, D, S>::TCompactTrie(TCompactTrie&& other) noexcept - : DataHolder(std::move(other.DataHolder)) - , EmptyValue(std::move(other.EmptyValue)) - , Packer(std::move(other.Packer)) -{ -} + : DataHolder(std::move(other.DataHolder)) + , EmptyValue(std::move(other.EmptyValue)) + , Packer(std::move(other.Packer)) +{ +} template <class T, class D, class S> -TCompactTrie<T, D, S>& TCompactTrie<T, D, S>::operator=(const TCompactTrie& other) { +TCompactTrie<T, D, S>& TCompactTrie<T, D, S>::operator=(const TCompactTrie& other) { if (this != &other) { DataHolder = other.DataHolder; EmptyValue = other.EmptyValue; @@ -529,7 +529,7 @@ bool TCompactTrie<T, D, S>::LookupLongestPrefix(const TSymbol* key, size_t keyle template <class T, class D, class S> void TCompactTrie<T, D, S>::LookupPhrases( const char* datapos, size_t len, const TSymbol* key, size_t keylen, - TVector<TPhraseMatch>& matches, TSymbol separator) const { + TVector<TPhraseMatch>& matches, TSymbol separator) const { using namespace NCompactTrie; matches.clear(); @@ -572,10 +572,10 @@ TCompactTrieHolder<T, D, S>::TCompactTrieHolder(IInputStream& is, size_t len) template <class T, class D, class S> TCompactTrie<T, D, S>::TConstIterator::TConstIterator(const TOpaqueTrie& trie, const char* emptyValue, bool atend, TPacker packer) - : Packer(packer) - , Impl(new TOpaqueTrieIterator(trie, emptyValue, atend)) -{ -} + : Packer(packer) + , Impl(new TOpaqueTrieIterator(trie, emptyValue, atend)) +{ +} template <class T, class D, class S> TCompactTrie<T, D, S>::TConstIterator::TConstIterator(const TOpaqueTrie& trie, const char* emptyValue, const TKeyBuf& key, TPacker packer) @@ -586,7 +586,7 @@ TCompactTrie<T, D, S>::TConstIterator::TConstIterator(const TOpaqueTrie& trie, c } template <class T, class D, class S> -bool TCompactTrie<T, D, S>::TConstIterator::operator==(const TConstIterator& other) const { +bool TCompactTrie<T, D, S>::TConstIterator::operator==(const TConstIterator& other) const { if (!Impl) return !other.Impl; if (!other.Impl) @@ -595,8 +595,8 @@ bool TCompactTrie<T, D, S>::TConstIterator::operator==(const TConstIterator& oth } template <class T, class D, class S> -bool TCompactTrie<T, D, S>::TConstIterator::operator!=(const TConstIterator& other) const { - return !operator==(other); +bool TCompactTrie<T, D, S>::TConstIterator::operator!=(const TConstIterator& other) const { + return !operator==(other); } template <class T, class D, class S> diff --git a/library/cpp/containers/comptrie/comptrie_ut.cpp b/library/cpp/containers/comptrie/comptrie_ut.cpp index b4f84b3e4b..74bee09b5d 100644 --- a/library/cpp/containers/comptrie/comptrie_ut.cpp +++ b/library/cpp/containers/comptrie/comptrie_ut.cpp @@ -1,12 +1,12 @@ -#include <util/random/shuffle.h> +#include <util/random/shuffle.h> #include <library/cpp/testing/unittest/registar.h> - + #include <util/stream/output.h> #include <utility> - -#include <util/charset/wide.h> + +#include <util/charset/wide.h> #include <util/generic/algorithm.h> -#include <util/generic/buffer.h> +#include <util/generic/buffer.h> #include <util/generic/map.h> #include <util/generic/vector.h> #include <util/generic/ptr.h> @@ -14,100 +14,100 @@ #include <util/folder/dirut.h> -#include <util/random/random.h> +#include <util/random/random.h> #include <util/random/fast.h> - + #include <util/string/hex.h> #include <util/string/cast.h> -#include "comptrie.h" +#include "comptrie.h" #include "set.h" #include "first_symbol_iterator.h" #include "search_iterator.h" #include "pattern_searcher.h" - + #include <array> #include <iterator> -class TCompactTrieTest: public TTestBase { +class TCompactTrieTest: public TTestBase { private: UNIT_TEST_SUITE(TCompactTrieTest); - UNIT_TEST(TestTrie8); - UNIT_TEST(TestTrie16); - UNIT_TEST(TestTrie32); - - UNIT_TEST(TestFastTrie8); - UNIT_TEST(TestFastTrie16); - UNIT_TEST(TestFastTrie32); - - UNIT_TEST(TestMinimizedTrie8); - UNIT_TEST(TestMinimizedTrie16); - UNIT_TEST(TestMinimizedTrie32); - - UNIT_TEST(TestFastMinimizedTrie8); - UNIT_TEST(TestFastMinimizedTrie16); - UNIT_TEST(TestFastMinimizedTrie32); - - UNIT_TEST(TestTrieIterator8); - UNIT_TEST(TestTrieIterator16); - UNIT_TEST(TestTrieIterator32); - - UNIT_TEST(TestMinimizedTrieIterator8); - UNIT_TEST(TestMinimizedTrieIterator16); - UNIT_TEST(TestMinimizedTrieIterator32); - - UNIT_TEST(TestPhraseSearch); - UNIT_TEST(TestAddGet); - UNIT_TEST(TestEmpty); - UNIT_TEST(TestUninitializedNonEmpty); - UNIT_TEST(TestRandom); - UNIT_TEST(TestFindTails); - UNIT_TEST(TestPrefixGrouped); - UNIT_TEST(CrashTestPrefixGrouped); + UNIT_TEST(TestTrie8); + UNIT_TEST(TestTrie16); + UNIT_TEST(TestTrie32); + + UNIT_TEST(TestFastTrie8); + UNIT_TEST(TestFastTrie16); + UNIT_TEST(TestFastTrie32); + + UNIT_TEST(TestMinimizedTrie8); + UNIT_TEST(TestMinimizedTrie16); + UNIT_TEST(TestMinimizedTrie32); + + UNIT_TEST(TestFastMinimizedTrie8); + UNIT_TEST(TestFastMinimizedTrie16); + UNIT_TEST(TestFastMinimizedTrie32); + + UNIT_TEST(TestTrieIterator8); + UNIT_TEST(TestTrieIterator16); + UNIT_TEST(TestTrieIterator32); + + UNIT_TEST(TestMinimizedTrieIterator8); + UNIT_TEST(TestMinimizedTrieIterator16); + UNIT_TEST(TestMinimizedTrieIterator32); + + UNIT_TEST(TestPhraseSearch); + UNIT_TEST(TestAddGet); + UNIT_TEST(TestEmpty); + UNIT_TEST(TestUninitializedNonEmpty); + UNIT_TEST(TestRandom); + UNIT_TEST(TestFindTails); + UNIT_TEST(TestPrefixGrouped); + UNIT_TEST(CrashTestPrefixGrouped); UNIT_TEST(TestMergeFromFile); UNIT_TEST(TestMergeFromBuffer); - UNIT_TEST(TestUnique); - UNIT_TEST(TestAddRetValue); - UNIT_TEST(TestClear); + UNIT_TEST(TestUnique); + UNIT_TEST(TestAddRetValue); + UNIT_TEST(TestClear); - UNIT_TEST(TestIterateEmptyKey); + UNIT_TEST(TestIterateEmptyKey); - UNIT_TEST(TestTrieSet); + UNIT_TEST(TestTrieSet); - UNIT_TEST(TestTrieForVectorInt64); - UNIT_TEST(TestTrieForListInt64); - UNIT_TEST(TestTrieForSetInt64); + UNIT_TEST(TestTrieForVectorInt64); + UNIT_TEST(TestTrieForListInt64); + UNIT_TEST(TestTrieForSetInt64); - UNIT_TEST(TestTrieForVectorStroka); - UNIT_TEST(TestTrieForListStroka); - UNIT_TEST(TestTrieForSetStroka); + UNIT_TEST(TestTrieForVectorStroka); + UNIT_TEST(TestTrieForListStroka); + UNIT_TEST(TestTrieForSetStroka); - UNIT_TEST(TestTrieForVectorWtroka); - UNIT_TEST(TestTrieForVectorFloat); - UNIT_TEST(TestTrieForVectorDouble); + UNIT_TEST(TestTrieForVectorWtroka); + UNIT_TEST(TestTrieForVectorFloat); + UNIT_TEST(TestTrieForVectorDouble); - UNIT_TEST(TestTrieForListVectorInt64); - UNIT_TEST(TestTrieForPairWtrokaVectorInt64); + UNIT_TEST(TestTrieForListVectorInt64); + UNIT_TEST(TestTrieForPairWtrokaVectorInt64); - UNIT_TEST(TestEmptyValueOutOfOrder); - UNIT_TEST(TestFindLongestPrefixWithEmptyValue); + UNIT_TEST(TestEmptyValueOutOfOrder); + UNIT_TEST(TestFindLongestPrefixWithEmptyValue); - UNIT_TEST(TestSearchIterChar); - UNIT_TEST(TestSearchIterWchar); + UNIT_TEST(TestSearchIterChar); + UNIT_TEST(TestSearchIterWchar); UNIT_TEST(TestSearchIterWchar32) - UNIT_TEST(TestCopyAndAssignment); + UNIT_TEST(TestCopyAndAssignment); - UNIT_TEST(TestFirstSymbolIterator8); - UNIT_TEST(TestFirstSymbolIterator16); - UNIT_TEST(TestFirstSymbolIterator32); + UNIT_TEST(TestFirstSymbolIterator8); + UNIT_TEST(TestFirstSymbolIterator16); + UNIT_TEST(TestFirstSymbolIterator32); UNIT_TEST(TestFirstSymbolIteratorChar32); - UNIT_TEST(TestArrayPacker); + UNIT_TEST(TestArrayPacker); - UNIT_TEST(TestBuilderFindLongestPrefix); - UNIT_TEST(TestBuilderFindLongestPrefixWithEmptyValue); + UNIT_TEST(TestBuilderFindLongestPrefix); + UNIT_TEST(TestBuilderFindLongestPrefixWithEmptyValue); UNIT_TEST(TestPatternSearcherEmpty); UNIT_TEST(TestPatternSearcherSimple); @@ -147,7 +147,7 @@ private: TVector<TContainer> GetSampleVectorData(size_t nValues); template <class TContainer> TVector<TContainer> GetSampleTextVectorData(size_t nValues); - template <class T> + template <class T> void CheckEquality(const T& value1, const T& value2) const; template <class TContainer> void TestTrieWithContainers(const TVector<TUtf16String>& keys, const TVector<TContainer>& sampleData, TString methodName); @@ -265,38 +265,38 @@ public: UNIT_TEST_SUITE_REGISTRATION(TCompactTrieTest); -const char* TCompactTrieTest::SampleData[] = { - "", - "a", "b", "c", "d", - "aa", "ab", "ac", "ad", - "aaa", "aab", "aac", "aad", - "aba", "abb", "abc", "abd", - "fba", "fbb", "fbc", "fbd", - "fbbaa", - "c\x85\xA4\xBF" // Just something outside ASCII. +const char* TCompactTrieTest::SampleData[] = { + "", + "a", "b", "c", "d", + "aa", "ab", "ac", "ad", + "aaa", "aab", "aac", "aad", + "aba", "abb", "abc", "abd", + "fba", "fbb", "fbc", "fbd", + "fbbaa", + "c\x85\xA4\xBF" // Just something outside ASCII. }; -template <class T> +template <class T> typename TCompactTrie<T>::TKey MakeWideKey(const char* str, size_t len) { typename TCompactTrie<T>::TKey buffer; for (size_t i = 0; i < len; i++) { unsigned int ch = (str[i] & 0xFF); - buffer.push_back((T)(ch | ch << 8 | ch << 16 | ch << 24)); + buffer.push_back((T)(ch | ch << 8 | ch << 16 | ch << 24)); } return buffer; } -template <class T> +template <class T> typename TCompactTrie<T>::TKey MakeWideKey(const TString& str) { return MakeWideKey<T>(str.c_str(), str.length()); } -template <class T> +template <class T> typename TCompactTrie<T>::TKey MakeWideKey(const TStringBuf& buf) { return MakeWideKey<T>(buf.data(), buf.length()); } -template <class T> +template <class T> void TCompactTrieTest::CreateTrie(IOutputStream& out, bool minimize, bool useFastLayout) { TCompactTrieBuilder<T> builder; @@ -305,18 +305,18 @@ void TCompactTrieTest::CreateTrie(IOutputStream& out, bool minimize, bool useFas builder.Add(MakeWideKey<T>(i, len), len * 2); } - + TBufferOutput tmp2; IOutputStream& currentOutput = useFastLayout ? tmp2 : out; if (minimize) { TBufferOutput buftmp; builder.Save(buftmp); - CompactTrieMinimize<TCompactTriePacker<ui64>>(currentOutput, buftmp.Buffer().Data(), buftmp.Buffer().Size(), false); + CompactTrieMinimize<TCompactTriePacker<ui64>>(currentOutput, buftmp.Buffer().Data(), buftmp.Buffer().Size(), false); } else { builder.Save(currentOutput); } if (useFastLayout) { - CompactTrieMakeFastLayout<TCompactTriePacker<T>>(out, tmp2.Buffer().Data(), tmp2.Buffer().Size(), false); + CompactTrieMakeFastLayout<TCompactTriePacker<T>>(out, tmp2.Buffer().Data(), tmp2.Buffer().Size(), false); } } @@ -337,7 +337,7 @@ static bool LexicographicStep(TString& s) { return true; } -template <class T> +template <class T> void TCompactTrieTest::CheckUpperBound(const char* data, size_t datalen) { TCompactTrie<T> trie(data, datalen); typedef typename TCompactTrie<T>::TKey TKey; @@ -357,7 +357,7 @@ void TCompactTrieTest::CheckUpperBound(const char* data, size_t datalen) { } while (LexicographicStep(key)); } -template <class T> +template <class T> void TCompactTrieTest::CheckData(const char* data, size_t datalen) { TCompactTrie<T> trie(data, datalen); @@ -413,13 +413,13 @@ void TCompactTrieTest::CheckData(const char* data, size_t datalen) { UNIT_ASSERT(trie.FindLongestPrefix(key, &prefixLen, &value)); UNIT_ASSERT_EQUAL(prefixLen, 3); UNIT_ASSERT_EQUAL(6, value); - + value = 12345678; UNIT_ASSERT(!trie.Find(key, &value)); - UNIT_ASSERT_EQUAL(12345678, value); //Failed Find() should not change value + UNIT_ASSERT_EQUAL(12345678, value); //Failed Find() should not change value } -template <class T> +template <class T> void TCompactTrieTest::CheckIterator(const char* data, size_t datalen) { typedef typename TCompactTrie<T>::TKey TKey; typedef typename TCompactTrie<T>::TValueType TValue; @@ -441,10 +441,10 @@ void TCompactTrieTest::CheckIterator(const char* data, size_t datalen) { received.insert(*it); items.push_back(*it); entry_count++; - it++; + it++; } TMap<TKey, ui64> received2; - for (std::pair<TKey, ui64> x : trie) { + for (std::pair<TKey, ui64> x : trie) { received2.insert(x); } UNIT_ASSERT(entry_count == stored.size()); @@ -485,7 +485,7 @@ void TCompactTrieTest::CheckIterator(const char* data, size_t datalen) { UNIT_ASSERT(revIt != trie.End()); } -template <class T> +template <class T> void TCompactTrieTest::TestTrie(bool minimize, bool useFastLayout) { TBufferOutput bufout; CreateTrie<T>(bufout, minimize, useFastLayout); @@ -493,75 +493,75 @@ void TCompactTrieTest::TestTrie(bool minimize, bool useFastLayout) { CheckUpperBound<T>(bufout.Buffer().Data(), bufout.Buffer().Size()); } -template <class T> +template <class T> void TCompactTrieTest::TestTrieIterator(bool minimize) { TBufferOutput bufout; CreateTrie<T>(bufout, minimize, false); CheckIterator<T>(bufout.Buffer().Data(), bufout.Buffer().Size()); } -void TCompactTrieTest::TestTrie8() { - TestTrie<char>(false, false); -} -void TCompactTrieTest::TestTrie16() { - TestTrie<wchar16>(false, false); -} -void TCompactTrieTest::TestTrie32() { - TestTrie<wchar32>(false, false); -} - -void TCompactTrieTest::TestFastTrie8() { - TestTrie<char>(false, true); -} -void TCompactTrieTest::TestFastTrie16() { - TestTrie<wchar16>(false, true); -} -void TCompactTrieTest::TestFastTrie32() { - TestTrie<wchar32>(false, true); -} - -void TCompactTrieTest::TestMinimizedTrie8() { - TestTrie<char>(true, false); -} -void TCompactTrieTest::TestMinimizedTrie16() { - TestTrie<wchar16>(true, false); -} -void TCompactTrieTest::TestMinimizedTrie32() { - TestTrie<wchar32>(true, false); -} - -void TCompactTrieTest::TestFastMinimizedTrie8() { - TestTrie<char>(true, true); -} -void TCompactTrieTest::TestFastMinimizedTrie16() { - TestTrie<wchar16>(true, true); -} -void TCompactTrieTest::TestFastMinimizedTrie32() { - TestTrie<wchar32>(true, true); -} - -void TCompactTrieTest::TestTrieIterator8() { - TestTrieIterator<char>(false); -} -void TCompactTrieTest::TestTrieIterator16() { - TestTrieIterator<wchar16>(false); -} -void TCompactTrieTest::TestTrieIterator32() { - TestTrieIterator<wchar32>(false); -} - -void TCompactTrieTest::TestMinimizedTrieIterator8() { - TestTrieIterator<char>(true); -} -void TCompactTrieTest::TestMinimizedTrieIterator16() { - TestTrieIterator<wchar16>(true); -} -void TCompactTrieTest::TestMinimizedTrieIterator32() { - TestTrieIterator<wchar32>(true); -} +void TCompactTrieTest::TestTrie8() { + TestTrie<char>(false, false); +} +void TCompactTrieTest::TestTrie16() { + TestTrie<wchar16>(false, false); +} +void TCompactTrieTest::TestTrie32() { + TestTrie<wchar32>(false, false); +} + +void TCompactTrieTest::TestFastTrie8() { + TestTrie<char>(false, true); +} +void TCompactTrieTest::TestFastTrie16() { + TestTrie<wchar16>(false, true); +} +void TCompactTrieTest::TestFastTrie32() { + TestTrie<wchar32>(false, true); +} + +void TCompactTrieTest::TestMinimizedTrie8() { + TestTrie<char>(true, false); +} +void TCompactTrieTest::TestMinimizedTrie16() { + TestTrie<wchar16>(true, false); +} +void TCompactTrieTest::TestMinimizedTrie32() { + TestTrie<wchar32>(true, false); +} + +void TCompactTrieTest::TestFastMinimizedTrie8() { + TestTrie<char>(true, true); +} +void TCompactTrieTest::TestFastMinimizedTrie16() { + TestTrie<wchar16>(true, true); +} +void TCompactTrieTest::TestFastMinimizedTrie32() { + TestTrie<wchar32>(true, true); +} + +void TCompactTrieTest::TestTrieIterator8() { + TestTrieIterator<char>(false); +} +void TCompactTrieTest::TestTrieIterator16() { + TestTrieIterator<wchar16>(false); +} +void TCompactTrieTest::TestTrieIterator32() { + TestTrieIterator<wchar32>(false); +} + +void TCompactTrieTest::TestMinimizedTrieIterator8() { + TestTrieIterator<char>(true); +} +void TCompactTrieTest::TestMinimizedTrieIterator16() { + TestTrieIterator<wchar16>(true); +} +void TCompactTrieTest::TestMinimizedTrieIterator32() { + TestTrieIterator<wchar32>(true); +} void TCompactTrieTest::TestPhraseSearch() { - static const char* phrases[] = {"ab", "ab cd", "ab cd ef"}; + static const char* phrases[] = {"ab", "ab cd", "ab cd ef"}; static const char* const goodphrase = "ab cd ef gh"; static const char* const badphrase = "cd ef gh ab"; TBufferOutput bufout; @@ -651,7 +651,7 @@ static char RandChar() { } static TString RandStr(const size_t max) { - size_t len = RandomNumber<size_t>() % max; + size_t len = RandomNumber<size_t>() % max; TString key; for (size_t j = 0; j < len; ++j) key += RandChar(); @@ -664,7 +664,7 @@ void TCompactTrieTest::TestRandom(const size_t n, const size_t maxKeySize) { TCompactTrieBuilder<char, typename T::TData, T> builder; typedef TMap<TString, typename T::TData> TKeys; TKeys keys; - + typename T::TData dummy; for (size_t i = 0; i < n; ++i) { const TString key = RandStr(maxKeySize); @@ -677,7 +677,7 @@ void TCompactTrieTest::TestRandom(const size_t n, const size_t maxKeySize) { UNIT_ASSERT(dummy == val); } } - + TBufferStream stream; size_t len = builder.Save(stream); TCompactTrie<char, typename T::TData, T> trie(stream.Buffer().Data(), len); @@ -721,12 +721,12 @@ void TCompactTrieTest::TestRandom(const size_t n, const size_t maxKeySize) { } void TCompactTrieTest::TestRandom() { - TestRandom<TIntPacker<ui64>, true>(1000, 1000); - TestRandom<TIntPacker<int>, true>(100, 100); - TestRandom<TDummyPacker<ui64>, true>(0, 0); - TestRandom<TDummyPacker<ui64>, true>(100, 3); - TestRandom<TDummyPacker<ui64>, true>(100, 100); - TestRandom<TStrokaPacker, true>(100, 100); + TestRandom<TIntPacker<ui64>, true>(1000, 1000); + TestRandom<TIntPacker<int>, true>(100, 100); + TestRandom<TDummyPacker<ui64>, true>(0, 0); + TestRandom<TDummyPacker<ui64>, true>(100, 3); + TestRandom<TDummyPacker<ui64>, true>(100, 100); + TestRandom<TStrokaPacker, true>(100, 100); } void TCompactTrieTest::TestFindTailsImpl(const TString& prefix) { @@ -779,14 +779,14 @@ void TCompactTrieTest::TestPrefixGrouped() { TBuffer b1b; TCompactTrieBuilder<char, ui32> b1(CTBF_PREFIX_GROUPED); const char* data[] = { - "Kazan", - "Moscow", - "Monino", - "Murmansk", - "Fryanovo", - "Fryazino", - "Fryazevo", - "Tumen", + "Kazan", + "Moscow", + "Monino", + "Murmansk", + "Fryanovo", + "Fryazino", + "Fryazevo", + "Tumen", }; for (size_t i = 0; i < Y_ARRAY_SIZE(data); ++i) { @@ -937,15 +937,15 @@ void TCompactTrieTest::TestUnique() { void TCompactTrieTest::TestUniqueImpl(bool isPrefixGrouped) { TCompactTrieBuilder<char, ui32> builder(CTBF_UNIQUE | (isPrefixGrouped ? CTBF_PREFIX_GROUPED : CTBF_NONE)); const char* data[] = { - "Kazan", - "Moscow", - "Monino", - "Murmansk", - "Fryanovo", - "Fryazino", - "Fryazevo", - "Fry", - "Tumen", + "Kazan", + "Moscow", + "Monino", + "Murmansk", + "Fryanovo", + "Fryazino", + "Fryazevo", + "Fry", + "Tumen", }; for (size_t i = 0; i < Y_ARRAY_SIZE(data); ++i) { UNIT_ASSERT_C(builder.Add(data[i], strlen(data[i]), i + 1), i); @@ -963,15 +963,15 @@ void TCompactTrieTest::TestUniqueImpl(bool isPrefixGrouped) { void TCompactTrieTest::TestAddRetValue() { TCompactTrieBuilder<char, ui32> builder; const char* data[] = { - "Kazan", - "Moscow", - "Monino", - "Murmansk", - "Fryanovo", - "Fryazino", - "Fryazevo", - "Fry", - "Tumen", + "Kazan", + "Moscow", + "Monino", + "Murmansk", + "Fryanovo", + "Fryazino", + "Fryazevo", + "Fry", + "Tumen", }; for (size_t i = 0; i < Y_ARRAY_SIZE(data); ++i) { UNIT_ASSERT(builder.Add(data[i], strlen(data[i]), i + 1)); @@ -982,7 +982,7 @@ void TCompactTrieTest::TestAddRetValue() { } } -void TCompactTrieTest::TestClear() { +void TCompactTrieTest::TestClear() { TCompactTrieBuilder<char, ui32> builder; const char* data[] = { "Kazan", @@ -1008,14 +1008,14 @@ void TCompactTrieTest::TestFindTails() { TestFindTailsImpl("aa"); TestFindTailsImpl("bb"); TestFindTailsImpl("fb"); - TestFindTailsImpl("fbc"); - TestFindTailsImpl("fbbaa"); + TestFindTailsImpl("fbc"); + TestFindTailsImpl("fbbaa"); } template <class T> -class TCompactTrieTest::TDummyPacker: public TNullPacker<T> { +class TCompactTrieTest::TDummyPacker: public TNullPacker<T> { public: - static T Data(const TString&) { + static T Data(const TString&) { T data; TNullPacker<T>().UnpackLeaf(nullptr, data); return data; @@ -1024,21 +1024,21 @@ public: typedef T TData; }; -class TCompactTrieTest::TStrokaPacker: public TCompactTriePacker<TString> { +class TCompactTrieTest::TStrokaPacker: public TCompactTriePacker<TString> { public: typedef TString TData; - static TString Data(const TString& str) { + static TString Data(const TString& str) { return str; } }; template <class T> -class TCompactTrieTest::TIntPacker: public TCompactTriePacker<T> { +class TCompactTrieTest::TIntPacker: public TCompactTriePacker<T> { public: typedef T TData; - static TData Data(const TString&) { + static TData Data(const TString&) { return RandomNumber<std::make_unsigned_t<T>>(); } }; @@ -1099,7 +1099,7 @@ void TCompactTrieTest::TestTrieSet() { UNIT_ASSERT(!empty.Has("d")); UNIT_ASSERT(!empty.Has("d")); - UNIT_ASSERT(empty.Has("")); // contains only empty string + UNIT_ASSERT(empty.Has("")); // contains only empty string } // Tests for trie with vector (list, set) values @@ -1119,7 +1119,7 @@ TVector<TContainer> TCompactTrieTest::GetSampleVectorData(size_t nValues) { for (size_t i = 0; i < nValues; i++) { data.push_back(TContainer()); for (size_t j = 0; j < i; j++) - data[i].insert(data[i].end(), (typename TContainer::value_type)((j == 3) ? 0 : (1 << (j * 5)))); + data[i].insert(data[i].end(), (typename TContainer::value_type)((j == 3) ? 0 : (1 << (j * 5)))); } return data; } @@ -1135,16 +1135,16 @@ TVector<TContainer> TCompactTrieTest::GetSampleTextVectorData(size_t nValues) { return data; } -template <class T> +template <class T> void TCompactTrieTest::CheckEquality(const T& value1, const T& value2) const { UNIT_ASSERT_VALUES_EQUAL(value1, value2); } -template <> -void TCompactTrieTest::CheckEquality<TVector<i64>>(const TVector<i64>& value1, const TVector<i64>& value2) const { - UNIT_ASSERT_VALUES_EQUAL(value1.size(), value2.size()); - for (size_t i = 0; i < value1.size(); i++) - UNIT_ASSERT_VALUES_EQUAL(value1[i], value2[i]); +template <> +void TCompactTrieTest::CheckEquality<TVector<i64>>(const TVector<i64>& value1, const TVector<i64>& value2) const { + UNIT_ASSERT_VALUES_EQUAL(value1.size(), value2.size()); + for (size_t i = 0; i < value1.size(); i++) + UNIT_ASSERT_VALUES_EQUAL(value1[i], value2[i]); } template <class TContainer> @@ -1171,9 +1171,9 @@ void TCompactTrieTest::TestTrieWithContainers(const TVector<TUtf16String>& keys, unlink(fileName.data()); } -template <> -void TCompactTrieTest::TestTrieWithContainers<std::pair<TUtf16String, TVector<i64>>>(const TVector<TUtf16String>& keys, const TVector<std::pair<TUtf16String, TVector<i64>>>& sampleData, TString methodName) { - typedef std::pair<TUtf16String, TVector<i64>> TContainer; +template <> +void TCompactTrieTest::TestTrieWithContainers<std::pair<TUtf16String, TVector<i64>>>(const TVector<TUtf16String>& keys, const TVector<std::pair<TUtf16String, TVector<i64>>>& sampleData, TString methodName) { + typedef std::pair<TUtf16String, TVector<i64>> TContainer; TString fileName = GetSystemTempDir() + "/TCompactTrieTest-TestTrieWithContainers-" + methodName; TCompactTrieBuilder<wchar16, TContainer> b; @@ -1194,63 +1194,63 @@ void TCompactTrieTest::TestTrieWithContainers<std::pair<TUtf16String, TVector<i6 } void TCompactTrieTest::TestTrieForVectorInt64() { - TestTrieWithContainers<TVector<i64>>(GetSampleKeys(10), GetSampleVectorData<TVector<i64>>(10), "v-i64"); + TestTrieWithContainers<TVector<i64>>(GetSampleKeys(10), GetSampleVectorData<TVector<i64>>(10), "v-i64"); } void TCompactTrieTest::TestTrieForListInt64() { - TestTrieWithContainers<TList<i64>>(GetSampleKeys(10), GetSampleVectorData<TList<i64>>(10), "l-i64"); + TestTrieWithContainers<TList<i64>>(GetSampleKeys(10), GetSampleVectorData<TList<i64>>(10), "l-i64"); } void TCompactTrieTest::TestTrieForSetInt64() { - TestTrieWithContainers<TSet<i64>>(GetSampleKeys(10), GetSampleVectorData<TSet<i64>>(10), "s-i64"); + TestTrieWithContainers<TSet<i64>>(GetSampleKeys(10), GetSampleVectorData<TSet<i64>>(10), "s-i64"); } void TCompactTrieTest::TestTrieForVectorStroka() { - TestTrieWithContainers<TVector<TString>>(GetSampleKeys(10), GetSampleTextVectorData<TVector<TString>>(10), "v-str"); + TestTrieWithContainers<TVector<TString>>(GetSampleKeys(10), GetSampleTextVectorData<TVector<TString>>(10), "v-str"); } void TCompactTrieTest::TestTrieForListStroka() { - TestTrieWithContainers<TList<TString>>(GetSampleKeys(10), GetSampleTextVectorData<TList<TString>>(10), "l-str"); + TestTrieWithContainers<TList<TString>>(GetSampleKeys(10), GetSampleTextVectorData<TList<TString>>(10), "l-str"); } void TCompactTrieTest::TestTrieForSetStroka() { - TestTrieWithContainers<TSet<TString>>(GetSampleKeys(10), GetSampleTextVectorData<TSet<TString>>(10), "s-str"); + TestTrieWithContainers<TSet<TString>>(GetSampleKeys(10), GetSampleTextVectorData<TSet<TString>>(10), "s-str"); } void TCompactTrieTest::TestTrieForVectorWtroka() { - TVector<TVector<TString>> data = GetSampleTextVectorData<TVector<TString>>(10); - TVector<TVector<TUtf16String>> wData; + TVector<TVector<TString>> data = GetSampleTextVectorData<TVector<TString>>(10); + TVector<TVector<TUtf16String>> wData; for (size_t i = 0; i < data.size(); i++) { wData.push_back(TVector<TUtf16String>()); for (size_t j = 0; j < data[i].size(); j++) - wData[i].push_back(UTF8ToWide(data[i][j])); + wData[i].push_back(UTF8ToWide(data[i][j])); } - TestTrieWithContainers<TVector<TUtf16String>>(GetSampleKeys(10), wData, "v-wtr"); + TestTrieWithContainers<TVector<TUtf16String>>(GetSampleKeys(10), wData, "v-wtr"); } void TCompactTrieTest::TestTrieForVectorFloat() { - TestTrieWithContainers<TVector<float>>(GetSampleKeys(10), GetSampleVectorData<TVector<float>>(10), "v-float"); + TestTrieWithContainers<TVector<float>>(GetSampleKeys(10), GetSampleVectorData<TVector<float>>(10), "v-float"); } void TCompactTrieTest::TestTrieForVectorDouble() { - TestTrieWithContainers<TVector<double>>(GetSampleKeys(10), GetSampleVectorData<TVector<double>>(10), "v-double"); + TestTrieWithContainers<TVector<double>>(GetSampleKeys(10), GetSampleVectorData<TVector<double>>(10), "v-double"); } void TCompactTrieTest::TestTrieForListVectorInt64() { TVector<i64> tmp; - tmp.push_back(0); - TList<TVector<i64>> dataElement(5, tmp); - TVector<TList<TVector<i64>>> data(10, dataElement); - TestTrieWithContainers<TList<TVector<i64>>>(GetSampleKeys(10), data, "l-v-i64"); + tmp.push_back(0); + TList<TVector<i64>> dataElement(5, tmp); + TVector<TList<TVector<i64>>> data(10, dataElement); + TestTrieWithContainers<TList<TVector<i64>>>(GetSampleKeys(10), data, "l-v-i64"); } void TCompactTrieTest::TestTrieForPairWtrokaVectorInt64() { TVector<TUtf16String> keys = GetSampleKeys(10); - TVector<TVector<i64>> values = GetSampleVectorData<TVector<i64>>(10); - TVector<std::pair<TUtf16String, TVector<i64>>> data; + TVector<TVector<i64>> values = GetSampleVectorData<TVector<i64>>(10); + TVector<std::pair<TUtf16String, TVector<i64>>> data; for (size_t i = 0; i < 10; i++) data.push_back(std::pair<TUtf16String, TVector<i64>>(keys[i] + u"_v", values[i])); - TestTrieWithContainers<std::pair<TUtf16String, TVector<i64>>>(keys, data, "pair-str-v-i64"); + TestTrieWithContainers<std::pair<TUtf16String, TVector<i64>>>(keys, data, "pair-str-v-i64"); } void TCompactTrieTest::TestEmptyValueOutOfOrder() { @@ -1468,7 +1468,7 @@ void TCompactTrieTest::TestArrayPacker() { void TCompactTrieTest::TestBuilderFindLongestPrefix() { const size_t sizes[] = {10, 100}; - const double branchProbabilities[] = {0.01, 0.1, 0.5, 0.9, 0.99}; + const double branchProbabilities[] = {0.01, 0.1, 0.5, 0.9, 0.99}; for (size_t size : sizes) { for (double branchProbability : branchProbabilities) { TestBuilderFindLongestPrefix(size, branchProbability, false, false); @@ -1498,7 +1498,7 @@ void TCompactTrieTest::TestBuilderFindLongestPrefix(size_t keysCount, double bra if (isPrefixGrouped) Sort(keys.begin(), keys.end()); else - Shuffle(keys.begin(), keys.end()); + Shuffle(keys.begin(), keys.end()); TCompactTrieBuilder<char, TString> builder(isPrefixGrouped ? CTBF_PREFIX_GROUPED : CTBF_NONE); const TString EMPTY_VALUE = "empty"; diff --git a/library/cpp/containers/comptrie/first_symbol_iterator.h b/library/cpp/containers/comptrie/first_symbol_iterator.h index d3c521e7e6..d06135f06f 100644 --- a/library/cpp/containers/comptrie/first_symbol_iterator.h +++ b/library/cpp/containers/comptrie/first_symbol_iterator.h @@ -6,7 +6,7 @@ namespace NCompactTrie { // Iterates over possible first symbols in a trie. // Allows one to get the symbol and the subtrie starting from it. - template <class TTrie> + template <class TTrie> class TFirstSymbolIterator { public: using TSymbol = typename TTrie::TSymbol; @@ -58,4 +58,4 @@ namespace NCompactTrie { TCopyPtr<TOpaqueTrieIterator> Impl; }; -} +} diff --git a/library/cpp/containers/comptrie/key_selector.h b/library/cpp/containers/comptrie/key_selector.h index 80191df744..60466cef71 100644 --- a/library/cpp/containers/comptrie/key_selector.h +++ b/library/cpp/containers/comptrie/key_selector.h @@ -4,24 +4,24 @@ #include <util/generic/string.h> #include <util/generic/strbuf.h> -template <class T> +template <class T> struct TCompactTrieKeySelector { typedef TVector<T> TKey; typedef TVector<T> TKeyBuf; }; -template <class TChar> +template <class TChar> struct TCompactTrieCharKeySelector { typedef TBasicString<TChar> TKey; typedef TBasicStringBuf<TChar> TKeyBuf; }; -template <> -struct TCompactTrieKeySelector<char>: public TCompactTrieCharKeySelector<char> { +template <> +struct TCompactTrieKeySelector<char>: public TCompactTrieCharKeySelector<char> { }; -template <> -struct TCompactTrieKeySelector<wchar16>: public TCompactTrieCharKeySelector<wchar16> { +template <> +struct TCompactTrieKeySelector<wchar16>: public TCompactTrieCharKeySelector<wchar16> { }; template <> diff --git a/library/cpp/containers/comptrie/leaf_skipper.h b/library/cpp/containers/comptrie/leaf_skipper.h index 0bdfa11d63..3959258948 100644 --- a/library/cpp/containers/comptrie/leaf_skipper.h +++ b/library/cpp/containers/comptrie/leaf_skipper.h @@ -9,11 +9,11 @@ namespace NCompactTrie { virtual ~ILeafSkipper() = default; }; - template <class TPacker> - class TPackerLeafSkipper: public ILeafSkipper { + template <class TPacker> + class TPackerLeafSkipper: public ILeafSkipper { private: const TPacker* Packer; - + public: TPackerLeafSkipper(const TPacker* packer) : Packer(packer) @@ -25,9 +25,9 @@ namespace NCompactTrie { } // For test purposes. - const TPacker* GetPacker() const { - return Packer; - } + const TPacker* GetPacker() const { + return Packer; + } }; // The data you need to traverse the trie without unpacking the values. @@ -40,13 +40,13 @@ namespace NCompactTrie { : Data(data) , Length(dataLength) , SkipFunction(skipFunction) - { - } + { + } bool operator==(const TOpaqueTrie& other) const { return Data == other.Data && - Length == other.Length && - &SkipFunction == &other.SkipFunction; + Length == other.Length && + &SkipFunction == &other.SkipFunction; } bool operator!=(const TOpaqueTrie& other) const { diff --git a/library/cpp/containers/comptrie/loader/loader.h b/library/cpp/containers/comptrie/loader/loader.h index d172efa541..ee10e9b451 100644 --- a/library/cpp/containers/comptrie/loader/loader.h +++ b/library/cpp/containers/comptrie/loader/loader.h @@ -9,7 +9,7 @@ template <class TrieType, size_t N> TrieType LoadTrieFromArchive(const TString& key, const unsigned char (&data)[N], - bool ignoreErrors = false) { + bool ignoreErrors = false) { TArchiveReader archive(TBlob::NoCopy(data, sizeof(data))); if (archive.Has(key)) { TAutoPtr<IInputStream> trie = archive.ObjectByKey(key); diff --git a/library/cpp/containers/comptrie/loader/loader_ut.cpp b/library/cpp/containers/comptrie/loader/loader_ut.cpp index 2e771357fe..345063a31e 100644 --- a/library/cpp/containers/comptrie/loader/loader_ut.cpp +++ b/library/cpp/containers/comptrie/loader/loader_ut.cpp @@ -6,25 +6,25 @@ using TDummyTrie = TCompactTrie<char, i32>; namespace { const unsigned char DATA[] = { -#include "data.inc" +#include "data.inc" }; -} +} Y_UNIT_TEST_SUITE(ArchiveLoaderTests) { Y_UNIT_TEST(BaseTest) { - TDummyTrie trie = LoadTrieFromArchive<TDummyTrie>("/dummy.trie", DATA, true); - UNIT_ASSERT_EQUAL(trie.Size(), 3); + TDummyTrie trie = LoadTrieFromArchive<TDummyTrie>("/dummy.trie", DATA, true); + UNIT_ASSERT_EQUAL(trie.Size(), 3); - const TString TrieKyes[3] = { - "zero", "one", "two"}; - i32 val = -1; - for (i32 i = 0; i < 3; ++i) { + const TString TrieKyes[3] = { + "zero", "one", "two"}; + i32 val = -1; + for (i32 i = 0; i < 3; ++i) { UNIT_ASSERT(trie.Find(TrieKyes[i].data(), TrieKyes[i].size(), &val)); - UNIT_ASSERT_EQUAL(i, val); - } + UNIT_ASSERT_EQUAL(i, val); + } - UNIT_CHECK_GENERATED_EXCEPTION( - LoadTrieFromArchive<TDummyTrie>("/noname.trie", DATA), - yexception); + UNIT_CHECK_GENERATED_EXCEPTION( + LoadTrieFromArchive<TDummyTrie>("/noname.trie", DATA), + yexception); } } diff --git a/library/cpp/containers/comptrie/make_fast_layout.cpp b/library/cpp/containers/comptrie/make_fast_layout.cpp index 693384ee7f..ade78d7899 100644 --- a/library/cpp/containers/comptrie/make_fast_layout.cpp +++ b/library/cpp/containers/comptrie/make_fast_layout.cpp @@ -24,444 +24,444 @@ // (there is not much difference between these papers, actually). // namespace NCompactTrie { - static size_t FindSupportingPowerOf2(size_t n) { - size_t result = 1ull << (8 * sizeof(size_t) - 1); - while (result > n) { - result >>= 1; - } - return result; + static size_t FindSupportingPowerOf2(size_t n) { + size_t result = 1ull << (8 * sizeof(size_t) - 1); + while (result > n) { + result >>= 1; + } + return result; } - namespace { - class TTrieNodeSet { - public: + namespace { + class TTrieNodeSet { + public: TTrieNodeSet() = default; - explicit TTrieNodeSet(const TOpaqueTrie& trie) - : Body(trie.Length / (8 * MinNodeSize) + 1, 0) - { - } - - bool Has(size_t offset) const { - const size_t reducedOffset = ReducedOffset(offset); - return OffsetCell(reducedOffset) & OffsetMask(reducedOffset); - } - - void Add(size_t offset) { - const size_t reducedOffset = ReducedOffset(offset); - OffsetCell(reducedOffset) |= OffsetMask(reducedOffset); - } - - void Remove(size_t offset) { - const size_t reducedOffset = ReducedOffset(offset); - OffsetCell(reducedOffset) &= ~OffsetMask(reducedOffset); - } - - void Swap(TTrieNodeSet& other) { - Body.swap(other.Body); - } - - private: - static const size_t MinNodeSize = 2; - TVector<ui8> Body; - - static size_t ReducedOffset(size_t offset) { - return offset / MinNodeSize; - } - static ui8 OffsetMask(size_t reducedOffset) { - return 1 << (reducedOffset % 8); - } - ui8& OffsetCell(size_t reducedOffset) { - return Body.at(reducedOffset / 8); - } - const ui8& OffsetCell(size_t reducedOffset) const { - return Body.at(reducedOffset / 8); - } - }; - - //--------------------------------------------------------------------- - - class TTrieNodeCounts { - public: + explicit TTrieNodeSet(const TOpaqueTrie& trie) + : Body(trie.Length / (8 * MinNodeSize) + 1, 0) + { + } + + bool Has(size_t offset) const { + const size_t reducedOffset = ReducedOffset(offset); + return OffsetCell(reducedOffset) & OffsetMask(reducedOffset); + } + + void Add(size_t offset) { + const size_t reducedOffset = ReducedOffset(offset); + OffsetCell(reducedOffset) |= OffsetMask(reducedOffset); + } + + void Remove(size_t offset) { + const size_t reducedOffset = ReducedOffset(offset); + OffsetCell(reducedOffset) &= ~OffsetMask(reducedOffset); + } + + void Swap(TTrieNodeSet& other) { + Body.swap(other.Body); + } + + private: + static const size_t MinNodeSize = 2; + TVector<ui8> Body; + + static size_t ReducedOffset(size_t offset) { + return offset / MinNodeSize; + } + static ui8 OffsetMask(size_t reducedOffset) { + return 1 << (reducedOffset % 8); + } + ui8& OffsetCell(size_t reducedOffset) { + return Body.at(reducedOffset / 8); + } + const ui8& OffsetCell(size_t reducedOffset) const { + return Body.at(reducedOffset / 8); + } + }; + + //--------------------------------------------------------------------- + + class TTrieNodeCounts { + public: TTrieNodeCounts() = default; - explicit TTrieNodeCounts(const TOpaqueTrie& trie) - : Body(trie.Length / MinNodeSize, 0) - , IsTree(false) - { - } - - size_t Get(size_t offset) const { - return IsTree ? 1 : Body.at(offset / MinNodeSize); - } - - void Inc(size_t offset) { - if (IsTree) { - return; - } - ui8& count = Body.at(offset / MinNodeSize); - if (count != MaxCount) { - ++count; - } - } - - size_t Dec(size_t offset) { - if (IsTree) { - return 0; - } - ui8& count = Body.at(offset / MinNodeSize); - Y_ASSERT(count > 0); - if (count != MaxCount) { - --count; - } - return count; - } - - void Swap(TTrieNodeCounts& other) { - Body.swap(other.Body); - ::DoSwap(IsTree, other.IsTree); - } - - void SetTreeMode() { - IsTree = true; - Body = TVector<ui8>(); - } - - private: - static const size_t MinNodeSize = 2; - static const ui8 MaxCount = 255; - - TVector<ui8> Body; - bool IsTree = false; - }; - - //---------------------------------------------------------- - - class TOffsetIndex { - public: - // In all methods: - // Key --- offset from the beginning of the old trie. - // Value --- offset from the end of the new trie. - - explicit TOffsetIndex(TTrieNodeCounts& counts) { - ParentCounts.Swap(counts); - } - - void Add(size_t key, size_t value) { - Data[key] = value; - } - - size_t Size() const { - return Data.size(); - } - - size_t Get(size_t key) { - auto pos = Data.find(key); - if (pos == Data.end()) { - ythrow yexception() << "Bad node walking order: trying to get node offset too early or too many times!"; - } - size_t result = pos->second; - if (ParentCounts.Dec(key) == 0) { - // We don't need this offset any more. - Data.erase(pos); - } - return result; - } - - private: - TTrieNodeCounts ParentCounts; - THashMap<size_t, size_t> Data; - }; - - //--------------------------------------------------------------------------------------- - - class TTrieMeasurer { - public: - TTrieMeasurer(const TOpaqueTrie& trie, bool verbose); - void Measure(); - - size_t GetDepth() const { - return Depth; - } - - size_t GetNodeCount() const { - return NodeCount; - } - - size_t GetUnminimizedNodeCount() const { - return UnminimizedNodeCount; - } - - bool IsTree() const { - return NodeCount == UnminimizedNodeCount; - } - - TTrieNodeCounts& GetParentCounts() { - return ParentCounts; - } - - const TOpaqueTrie& GetTrie() const { - return Trie; - } - - private: - const TOpaqueTrie& Trie; - size_t Depth; - TTrieNodeCounts ParentCounts; - size_t NodeCount; - size_t UnminimizedNodeCount; - const bool Verbose; - - // returns depth, increments NodeCount. - size_t MeasureSubtrie(size_t rootOffset, bool isNewPath); - }; - - TTrieMeasurer::TTrieMeasurer(const TOpaqueTrie& trie, bool verbose) - : Trie(trie) - , Depth(0) - , ParentCounts(trie) - , NodeCount(0) - , UnminimizedNodeCount(0) - , Verbose(verbose) - { - Y_ASSERT(Trie.Data); - } - - void TTrieMeasurer::Measure() { - if (Verbose) { - Cerr << "Measuring the trie..." << Endl; - } - NodeCount = 0; - UnminimizedNodeCount = 0; - Depth = MeasureSubtrie(0, true); - if (IsTree()) { - ParentCounts.SetTreeMode(); - } - if (Verbose) { - Cerr << "Unminimized node count: " << UnminimizedNodeCount << Endl; - Cerr << "Trie depth: " << Depth << Endl; - Cerr << "Node count: " << NodeCount << Endl; - } - } - - // A chain of nodes linked by forward links - // is considered one node with many left and right children - // for depth measuring here and in - // TVanEmdeBoasReverseNodeEnumerator::FindDescendants. - size_t TTrieMeasurer::MeasureSubtrie(size_t rootOffset, bool isNewPath) { - Y_ASSERT(rootOffset < Trie.Length); - TNode node(Trie.Data, rootOffset, Trie.SkipFunction); - size_t depth = 0; - for (;;) { - ++UnminimizedNodeCount; - if (Verbose) { - ShowProgress(UnminimizedNodeCount); - } - if (isNewPath) { - if (ParentCounts.Get(node.GetOffset()) > 0) { - isNewPath = false; - } else { - ++NodeCount; - } - ParentCounts.Inc(node.GetOffset()); - } - if (node.GetLeftOffset()) { - depth = Max(depth, 1 + MeasureSubtrie(node.GetLeftOffset(), isNewPath)); - } - if (node.GetRightOffset()) { - depth = Max(depth, 1 + MeasureSubtrie(node.GetRightOffset(), isNewPath)); - } - if (node.GetForwardOffset()) { - node = TNode(Trie.Data, node.GetForwardOffset(), Trie.SkipFunction); - } else { - break; - } - } - return depth; + explicit TTrieNodeCounts(const TOpaqueTrie& trie) + : Body(trie.Length / MinNodeSize, 0) + , IsTree(false) + { + } + + size_t Get(size_t offset) const { + return IsTree ? 1 : Body.at(offset / MinNodeSize); + } + + void Inc(size_t offset) { + if (IsTree) { + return; + } + ui8& count = Body.at(offset / MinNodeSize); + if (count != MaxCount) { + ++count; + } + } + + size_t Dec(size_t offset) { + if (IsTree) { + return 0; + } + ui8& count = Body.at(offset / MinNodeSize); + Y_ASSERT(count > 0); + if (count != MaxCount) { + --count; + } + return count; + } + + void Swap(TTrieNodeCounts& other) { + Body.swap(other.Body); + ::DoSwap(IsTree, other.IsTree); + } + + void SetTreeMode() { + IsTree = true; + Body = TVector<ui8>(); + } + + private: + static const size_t MinNodeSize = 2; + static const ui8 MaxCount = 255; + + TVector<ui8> Body; + bool IsTree = false; + }; + + //---------------------------------------------------------- + + class TOffsetIndex { + public: + // In all methods: + // Key --- offset from the beginning of the old trie. + // Value --- offset from the end of the new trie. + + explicit TOffsetIndex(TTrieNodeCounts& counts) { + ParentCounts.Swap(counts); + } + + void Add(size_t key, size_t value) { + Data[key] = value; + } + + size_t Size() const { + return Data.size(); + } + + size_t Get(size_t key) { + auto pos = Data.find(key); + if (pos == Data.end()) { + ythrow yexception() << "Bad node walking order: trying to get node offset too early or too many times!"; + } + size_t result = pos->second; + if (ParentCounts.Dec(key) == 0) { + // We don't need this offset any more. + Data.erase(pos); + } + return result; + } + + private: + TTrieNodeCounts ParentCounts; + THashMap<size_t, size_t> Data; + }; + + //--------------------------------------------------------------------------------------- + + class TTrieMeasurer { + public: + TTrieMeasurer(const TOpaqueTrie& trie, bool verbose); + void Measure(); + + size_t GetDepth() const { + return Depth; + } + + size_t GetNodeCount() const { + return NodeCount; + } + + size_t GetUnminimizedNodeCount() const { + return UnminimizedNodeCount; + } + + bool IsTree() const { + return NodeCount == UnminimizedNodeCount; + } + + TTrieNodeCounts& GetParentCounts() { + return ParentCounts; + } + + const TOpaqueTrie& GetTrie() const { + return Trie; + } + + private: + const TOpaqueTrie& Trie; + size_t Depth; + TTrieNodeCounts ParentCounts; + size_t NodeCount; + size_t UnminimizedNodeCount; + const bool Verbose; + + // returns depth, increments NodeCount. + size_t MeasureSubtrie(size_t rootOffset, bool isNewPath); + }; + + TTrieMeasurer::TTrieMeasurer(const TOpaqueTrie& trie, bool verbose) + : Trie(trie) + , Depth(0) + , ParentCounts(trie) + , NodeCount(0) + , UnminimizedNodeCount(0) + , Verbose(verbose) + { + Y_ASSERT(Trie.Data); } - - //-------------------------------------------------------------------------------------- - - using TLevelNodes = TVector<size_t>; - - struct TLevel { - size_t Depth; - TLevelNodes Nodes; - - explicit TLevel(size_t depth) - : Depth(depth) - { - } - }; - - //---------------------------------------------------------------------------------------- - - class TVanEmdeBoasReverseNodeEnumerator: public TReverseNodeEnumerator { - public: - TVanEmdeBoasReverseNodeEnumerator(TTrieMeasurer& measurer, bool verbose) - : Fresh(true) - , Trie(measurer.GetTrie()) - , Depth(measurer.GetDepth()) - , MaxIndexSize(0) - , BackIndex(measurer.GetParentCounts()) - , ProcessedNodes(measurer.GetTrie()) - , Verbose(verbose) - { - } - - bool Move() override { - if (!Fresh) { - CentralWord.pop_back(); - } - if (CentralWord.empty()) { - return MoveCentralWordStart(); - } - return true; - } - - const TNode& Get() const { - return CentralWord.back(); - } - - size_t GetLeafLength() const override { - return Get().GetLeafLength(); - } - - // Returns recalculated offset from the end of the current node. - size_t PrepareOffset(size_t absoffset, size_t resultLength) { - if (!absoffset) - return NPOS; - return resultLength - BackIndex.Get(absoffset); - } - - size_t RecreateNode(char* buffer, size_t resultLength) override { - TWriteableNode newNode(Get(), Trie.Data); - newNode.ForwardOffset = PrepareOffset(Get().GetForwardOffset(), resultLength); - newNode.LeftOffset = PrepareOffset(Get().GetLeftOffset(), resultLength); - newNode.RightOffset = PrepareOffset(Get().GetRightOffset(), resultLength); - - const size_t len = newNode.Pack(buffer); - ProcessedNodes.Add(Get().GetOffset()); - BackIndex.Add(Get().GetOffset(), resultLength + len); - MaxIndexSize = Max(MaxIndexSize, BackIndex.Size()); - return len; - } - - private: - bool Fresh; - TOpaqueTrie Trie; - size_t Depth; - size_t MaxIndexSize; - - TVector<TLevel> Trace; - TOffsetIndex BackIndex; - TVector<TNode> CentralWord; - TTrieNodeSet ProcessedNodes; - - const bool Verbose; - - private: - bool IsVisited(size_t offset) const { - return ProcessedNodes.Has(offset); - } - - void AddCascade(size_t step) { - Y_ASSERT(!(step & (step - 1))); // Should be a power of 2. - while (step > 0) { - size_t root = Trace.back().Nodes.back(); - TLevel level(Trace.back().Depth + step); - Trace.push_back(level); - size_t actualStep = FindSupportingPowerOf2(FindDescendants(root, step, Trace.back().Nodes)); - if (actualStep != step) { - // Retry with a smaller step. - Y_ASSERT(actualStep < step); - step = actualStep; - Trace.pop_back(); - } else { - step /= 2; - } - } - } - - void FillCentralWord() { - CentralWord.clear(); - CentralWord.push_back(TNode(Trie.Data, Trace.back().Nodes.back(), Trie.SkipFunction)); - // Do not check for epsilon links, as the traversal order now is different. - while (CentralWord.back().GetForwardOffset() && !IsVisited(CentralWord.back().GetForwardOffset())) { - CentralWord.push_back(TNode(Trie.Data, CentralWord.back().GetForwardOffset(), Trie.SkipFunction)); - } - } - - bool MoveCentralWordStart() { - do { - if (Fresh) { - TLevel root(0); - Trace.push_back(root); - Trace.back().Nodes.push_back(0); - const size_t sectionDepth = FindSupportingPowerOf2(Depth); - AddCascade(sectionDepth); - Fresh = false; - } else { - Trace.back().Nodes.pop_back(); - if (Trace.back().Nodes.empty() && Trace.size() == 1) { - if (Verbose) { - Cerr << "Max index size: " << MaxIndexSize << Endl; - Cerr << "Current index size: " << BackIndex.Size() << Endl; - } - // We just popped the root. - return false; - } - size_t lastStep = Trace.back().Depth - Trace[Trace.size() - 2].Depth; - if (Trace.back().Nodes.empty()) { - Trace.pop_back(); - } - AddCascade(lastStep / 2); - } - } while (IsVisited(Trace.back().Nodes.back())); - FillCentralWord(); - return true; - } - - // Returns the maximal depth it has reached while searching. - // This is a method because it needs OffsetIndex to skip processed nodes. - size_t FindDescendants(size_t rootOffset, size_t depth, TLevelNodes& result) const { - if (depth == 0) { - result.push_back(rootOffset); - return 0; - } - size_t actualDepth = 0; - TNode node(Trie.Data, rootOffset, Trie.SkipFunction); - for (;;) { - if (node.GetLeftOffset() && !IsVisited(node.GetLeftOffset())) { - actualDepth = Max(actualDepth, - 1 + FindDescendants(node.GetLeftOffset(), depth - 1, result)); + + void TTrieMeasurer::Measure() { + if (Verbose) { + Cerr << "Measuring the trie..." << Endl; + } + NodeCount = 0; + UnminimizedNodeCount = 0; + Depth = MeasureSubtrie(0, true); + if (IsTree()) { + ParentCounts.SetTreeMode(); + } + if (Verbose) { + Cerr << "Unminimized node count: " << UnminimizedNodeCount << Endl; + Cerr << "Trie depth: " << Depth << Endl; + Cerr << "Node count: " << NodeCount << Endl; + } + } + + // A chain of nodes linked by forward links + // is considered one node with many left and right children + // for depth measuring here and in + // TVanEmdeBoasReverseNodeEnumerator::FindDescendants. + size_t TTrieMeasurer::MeasureSubtrie(size_t rootOffset, bool isNewPath) { + Y_ASSERT(rootOffset < Trie.Length); + TNode node(Trie.Data, rootOffset, Trie.SkipFunction); + size_t depth = 0; + for (;;) { + ++UnminimizedNodeCount; + if (Verbose) { + ShowProgress(UnminimizedNodeCount); + } + if (isNewPath) { + if (ParentCounts.Get(node.GetOffset()) > 0) { + isNewPath = false; + } else { + ++NodeCount; + } + ParentCounts.Inc(node.GetOffset()); + } + if (node.GetLeftOffset()) { + depth = Max(depth, 1 + MeasureSubtrie(node.GetLeftOffset(), isNewPath)); + } + if (node.GetRightOffset()) { + depth = Max(depth, 1 + MeasureSubtrie(node.GetRightOffset(), isNewPath)); + } + if (node.GetForwardOffset()) { + node = TNode(Trie.Data, node.GetForwardOffset(), Trie.SkipFunction); + } else { + break; + } + } + return depth; + } + + //-------------------------------------------------------------------------------------- + + using TLevelNodes = TVector<size_t>; + + struct TLevel { + size_t Depth; + TLevelNodes Nodes; + + explicit TLevel(size_t depth) + : Depth(depth) + { + } + }; + + //---------------------------------------------------------------------------------------- + + class TVanEmdeBoasReverseNodeEnumerator: public TReverseNodeEnumerator { + public: + TVanEmdeBoasReverseNodeEnumerator(TTrieMeasurer& measurer, bool verbose) + : Fresh(true) + , Trie(measurer.GetTrie()) + , Depth(measurer.GetDepth()) + , MaxIndexSize(0) + , BackIndex(measurer.GetParentCounts()) + , ProcessedNodes(measurer.GetTrie()) + , Verbose(verbose) + { + } + + bool Move() override { + if (!Fresh) { + CentralWord.pop_back(); + } + if (CentralWord.empty()) { + return MoveCentralWordStart(); + } + return true; + } + + const TNode& Get() const { + return CentralWord.back(); + } + + size_t GetLeafLength() const override { + return Get().GetLeafLength(); + } + + // Returns recalculated offset from the end of the current node. + size_t PrepareOffset(size_t absoffset, size_t resultLength) { + if (!absoffset) + return NPOS; + return resultLength - BackIndex.Get(absoffset); + } + + size_t RecreateNode(char* buffer, size_t resultLength) override { + TWriteableNode newNode(Get(), Trie.Data); + newNode.ForwardOffset = PrepareOffset(Get().GetForwardOffset(), resultLength); + newNode.LeftOffset = PrepareOffset(Get().GetLeftOffset(), resultLength); + newNode.RightOffset = PrepareOffset(Get().GetRightOffset(), resultLength); + + const size_t len = newNode.Pack(buffer); + ProcessedNodes.Add(Get().GetOffset()); + BackIndex.Add(Get().GetOffset(), resultLength + len); + MaxIndexSize = Max(MaxIndexSize, BackIndex.Size()); + return len; + } + + private: + bool Fresh; + TOpaqueTrie Trie; + size_t Depth; + size_t MaxIndexSize; + + TVector<TLevel> Trace; + TOffsetIndex BackIndex; + TVector<TNode> CentralWord; + TTrieNodeSet ProcessedNodes; + + const bool Verbose; + + private: + bool IsVisited(size_t offset) const { + return ProcessedNodes.Has(offset); + } + + void AddCascade(size_t step) { + Y_ASSERT(!(step & (step - 1))); // Should be a power of 2. + while (step > 0) { + size_t root = Trace.back().Nodes.back(); + TLevel level(Trace.back().Depth + step); + Trace.push_back(level); + size_t actualStep = FindSupportingPowerOf2(FindDescendants(root, step, Trace.back().Nodes)); + if (actualStep != step) { + // Retry with a smaller step. + Y_ASSERT(actualStep < step); + step = actualStep; + Trace.pop_back(); + } else { + step /= 2; } - if (node.GetRightOffset() && !IsVisited(node.GetRightOffset())) { - actualDepth = Max(actualDepth, - 1 + FindDescendants(node.GetRightOffset(), depth - 1, result)); - } - if (node.GetForwardOffset() && !IsVisited(node.GetForwardOffset())) { - node = TNode(Trie.Data, node.GetForwardOffset(), Trie.SkipFunction); - } else { - break; - } } - return actualDepth; } - }; - } // Anonymous namespace. - - //----------------------------------------------------------------------------------- - - size_t RawCompactTrieFastLayoutImpl(IOutputStream& os, const TOpaqueTrie& trie, bool verbose) { - if (!trie.Data || !trie.Length) { + void FillCentralWord() { + CentralWord.clear(); + CentralWord.push_back(TNode(Trie.Data, Trace.back().Nodes.back(), Trie.SkipFunction)); + // Do not check for epsilon links, as the traversal order now is different. + while (CentralWord.back().GetForwardOffset() && !IsVisited(CentralWord.back().GetForwardOffset())) { + CentralWord.push_back(TNode(Trie.Data, CentralWord.back().GetForwardOffset(), Trie.SkipFunction)); + } + } + + bool MoveCentralWordStart() { + do { + if (Fresh) { + TLevel root(0); + Trace.push_back(root); + Trace.back().Nodes.push_back(0); + const size_t sectionDepth = FindSupportingPowerOf2(Depth); + AddCascade(sectionDepth); + Fresh = false; + } else { + Trace.back().Nodes.pop_back(); + if (Trace.back().Nodes.empty() && Trace.size() == 1) { + if (Verbose) { + Cerr << "Max index size: " << MaxIndexSize << Endl; + Cerr << "Current index size: " << BackIndex.Size() << Endl; + } + // We just popped the root. + return false; + } + size_t lastStep = Trace.back().Depth - Trace[Trace.size() - 2].Depth; + if (Trace.back().Nodes.empty()) { + Trace.pop_back(); + } + AddCascade(lastStep / 2); + } + } while (IsVisited(Trace.back().Nodes.back())); + FillCentralWord(); + return true; + } + + // Returns the maximal depth it has reached while searching. + // This is a method because it needs OffsetIndex to skip processed nodes. + size_t FindDescendants(size_t rootOffset, size_t depth, TLevelNodes& result) const { + if (depth == 0) { + result.push_back(rootOffset); + return 0; + } + size_t actualDepth = 0; + TNode node(Trie.Data, rootOffset, Trie.SkipFunction); + for (;;) { + if (node.GetLeftOffset() && !IsVisited(node.GetLeftOffset())) { + actualDepth = Max(actualDepth, + 1 + FindDescendants(node.GetLeftOffset(), depth - 1, result)); + } + if (node.GetRightOffset() && !IsVisited(node.GetRightOffset())) { + actualDepth = Max(actualDepth, + 1 + FindDescendants(node.GetRightOffset(), depth - 1, result)); + } + if (node.GetForwardOffset() && !IsVisited(node.GetForwardOffset())) { + node = TNode(Trie.Data, node.GetForwardOffset(), Trie.SkipFunction); + } else { + break; + } + } + return actualDepth; + } + }; + + } // Anonymous namespace. + + //----------------------------------------------------------------------------------- + + size_t RawCompactTrieFastLayoutImpl(IOutputStream& os, const TOpaqueTrie& trie, bool verbose) { + if (!trie.Data || !trie.Length) { return 0; } - TTrieMeasurer mes(trie, verbose); - mes.Measure(); - TVanEmdeBoasReverseNodeEnumerator enumerator(mes, verbose); - return WriteTrieBackwards(os, enumerator, verbose); + TTrieMeasurer mes(trie, verbose); + mes.Measure(); + TVanEmdeBoasReverseNodeEnumerator enumerator(mes, verbose); + return WriteTrieBackwards(os, enumerator, verbose); } - + } diff --git a/library/cpp/containers/comptrie/make_fast_layout.h b/library/cpp/containers/comptrie/make_fast_layout.h index cb488ffaa5..b8fab5d65b 100644 --- a/library/cpp/containers/comptrie/make_fast_layout.h +++ b/library/cpp/containers/comptrie/make_fast_layout.h @@ -6,15 +6,15 @@ class IOutputStream; namespace NCompactTrie { - // Return value: size of the resulting trie. - size_t RawCompactTrieFastLayoutImpl(IOutputStream& os, const NCompactTrie::TOpaqueTrie& trie, bool verbose); + // Return value: size of the resulting trie. + size_t RawCompactTrieFastLayoutImpl(IOutputStream& os, const NCompactTrie::TOpaqueTrie& trie, bool verbose); + + // Return value: size of the resulting trie. + template <class TPacker> + size_t CompactTrieMakeFastLayoutImpl(IOutputStream& os, const char* data, size_t datalength, bool verbose, const TPacker* packer) { + TPackerLeafSkipper<TPacker> skipper(packer); + TOpaqueTrie trie(data, datalength, skipper); + return RawCompactTrieFastLayoutImpl(os, trie, verbose); + } - // Return value: size of the resulting trie. - template <class TPacker> - size_t CompactTrieMakeFastLayoutImpl(IOutputStream& os, const char* data, size_t datalength, bool verbose, const TPacker* packer) { - TPackerLeafSkipper<TPacker> skipper(packer); - TOpaqueTrie trie(data, datalength, skipper); - return RawCompactTrieFastLayoutImpl(os, trie, verbose); - } - } diff --git a/library/cpp/containers/comptrie/minimize.cpp b/library/cpp/containers/comptrie/minimize.cpp index f53511428f..80d0b25217 100644 --- a/library/cpp/containers/comptrie/minimize.cpp +++ b/library/cpp/containers/comptrie/minimize.cpp @@ -8,352 +8,352 @@ #include <util/generic/algorithm.h> namespace NCompactTrie { - // Minimize the trie. The result is equivalent to the original - // trie, except that it takes less space (and has marginally lower - // performance, because of eventual epsilon links). - // The algorithm is as follows: starting from the largest pieces, we find - // nodes that have identical continuations (Daciuk's right language), - // and repack the trie. Repacking is done in-place, so memory is less - // of an issue; however, it may take considerable time. - - // IMPORTANT: never try to reminimize an already minimized trie or a trie with fast layout. - // Because of non-local structure and epsilon links, it won't work - // as you expect it to, and can destroy the trie in the making. - - namespace { - using TOffsetList = TVector<size_t>; - using TPieceIndex = THashMap<size_t, TOffsetList>; - - using TSizePair = std::pair<size_t, size_t>; - using TSizePairVector = TVector<TSizePair>; - using TSizePairVectorVector = TVector<TSizePairVector>; - - class TOffsetMap { - protected: - TSizePairVectorVector Data; - - public: - TOffsetMap() { - Data.reserve(0x10000); - } - - void Add(size_t key, size_t value) { - size_t hikey = key & 0xFFFF; - - if (Data.size() <= hikey) - Data.resize(hikey + 1); - - TSizePairVector& sublist = Data[hikey]; - - for (auto& it : sublist) { - if (it.first == key) { - it.second = value; - - return; - } - } - - sublist.push_back(TSizePair(key, value)); - } - - bool Contains(size_t key) const { - return (Get(key) != 0); + // Minimize the trie. The result is equivalent to the original + // trie, except that it takes less space (and has marginally lower + // performance, because of eventual epsilon links). + // The algorithm is as follows: starting from the largest pieces, we find + // nodes that have identical continuations (Daciuk's right language), + // and repack the trie. Repacking is done in-place, so memory is less + // of an issue; however, it may take considerable time. + + // IMPORTANT: never try to reminimize an already minimized trie or a trie with fast layout. + // Because of non-local structure and epsilon links, it won't work + // as you expect it to, and can destroy the trie in the making. + + namespace { + using TOffsetList = TVector<size_t>; + using TPieceIndex = THashMap<size_t, TOffsetList>; + + using TSizePair = std::pair<size_t, size_t>; + using TSizePairVector = TVector<TSizePair>; + using TSizePairVectorVector = TVector<TSizePairVector>; + + class TOffsetMap { + protected: + TSizePairVectorVector Data; + + public: + TOffsetMap() { + Data.reserve(0x10000); } - - size_t Get(size_t key) const { - size_t hikey = key & 0xFFFF; - - if (Data.size() <= hikey) - return 0; - - const TSizePairVector& sublist = Data[hikey]; - - for (const auto& it : sublist) { - if (it.first == key) - return it.second; - } - - return 0; - } - }; - - class TOffsetDeltas { - protected: - TSizePairVector Data; - - public: - void Add(size_t key, size_t value) { - if (Data.empty()) { - if (key == value) - return; // no offset - } else { - TSizePair last = Data.back(); - - if (key <= last.first) { - Cerr << "Trouble: elements to offset delta list added in wrong order" << Endl; - - return; - } - - if (last.first + value == last.second + key) - return; // same offset - } - - Data.push_back(TSizePair(key, value)); + + void Add(size_t key, size_t value) { + size_t hikey = key & 0xFFFF; + + if (Data.size() <= hikey) + Data.resize(hikey + 1); + + TSizePairVector& sublist = Data[hikey]; + + for (auto& it : sublist) { + if (it.first == key) { + it.second = value; + + return; + } + } + + sublist.push_back(TSizePair(key, value)); + } + + bool Contains(size_t key) const { + return (Get(key) != 0); + } + + size_t Get(size_t key) const { + size_t hikey = key & 0xFFFF; + + if (Data.size() <= hikey) + return 0; + + const TSizePairVector& sublist = Data[hikey]; + + for (const auto& it : sublist) { + if (it.first == key) + return it.second; + } + + return 0; + } + }; + + class TOffsetDeltas { + protected: + TSizePairVector Data; + + public: + void Add(size_t key, size_t value) { + if (Data.empty()) { + if (key == value) + return; // no offset + } else { + TSizePair last = Data.back(); + + if (key <= last.first) { + Cerr << "Trouble: elements to offset delta list added in wrong order" << Endl; + + return; + } + + if (last.first + value == last.second + key) + return; // same offset + } + + Data.push_back(TSizePair(key, value)); + } + + size_t Get(size_t key) const { + if (Data.empty()) + return key; // difference is zero; + + if (key < Data.front().first) + return key; + + // Binary search for the highest entry in the list that does not exceed the key + size_t from = 0; + size_t to = Data.size() - 1; + + while (from < to) { + size_t midpoint = (from + to + 1) / 2; + + if (key < Data[midpoint].first) + to = midpoint - 1; + else + from = midpoint; + } + + TSizePair entry = Data[from]; + + return key - entry.first + entry.second; + } + }; + + class TPieceComparer { + private: + const char* Data; + const size_t Length; + + public: + TPieceComparer(const char* buf, size_t len) + : Data(buf) + , Length(len) + { } - - size_t Get(size_t key) const { - if (Data.empty()) - return key; // difference is zero; - - if (key < Data.front().first) - return key; - - // Binary search for the highest entry in the list that does not exceed the key - size_t from = 0; - size_t to = Data.size() - 1; - - while (from < to) { - size_t midpoint = (from + to + 1) / 2; - - if (key < Data[midpoint].first) - to = midpoint - 1; - else - from = midpoint; - } - - TSizePair entry = Data[from]; - - return key - entry.first + entry.second; - } - }; - - class TPieceComparer { - private: - const char* Data; - const size_t Length; - - public: - TPieceComparer(const char* buf, size_t len) - : Data(buf) - , Length(len) - { - } - - bool operator()(size_t p1, const size_t p2) { - int res = memcmp(Data + p1, Data + p2, Length); - - if (res) - return (res > 0); - - return (p1 > p2); // the pieces are sorted in the reverse order of appearance - } - }; - - struct TBranchPoint { - TNode Node; - int Selector; - - public: - TBranchPoint() - : Selector(0) - { - } - - TBranchPoint(const char* data, size_t offset, const ILeafSkipper& skipFunction) - : Node(data, offset, skipFunction) - , Selector(0) - { - } - - bool IsFinal() const { - return Node.IsFinal(); - } - - // NextNode returns child nodes, starting from the last node: Right, then Left, then Forward - size_t NextNode(const TOffsetMap& mergedNodes) { - while (Selector < 3) { - size_t nextOffset = 0; - - switch (++Selector) { - case 1: - if (Node.GetRightOffset()) - nextOffset = Node.GetRightOffset(); - break; - - case 2: - if (Node.GetLeftOffset()) - nextOffset = Node.GetLeftOffset(); - break; - - case 3: - if (Node.GetForwardOffset()) - nextOffset = Node.GetForwardOffset(); - break; - - default: - break; - } - - if (nextOffset && !mergedNodes.Contains(nextOffset)) - return nextOffset; - } - return 0; + + bool operator()(size_t p1, const size_t p2) { + int res = memcmp(Data + p1, Data + p2, Length); + + if (res) + return (res > 0); + + return (p1 > p2); // the pieces are sorted in the reverse order of appearance + } + }; + + struct TBranchPoint { + TNode Node; + int Selector; + + public: + TBranchPoint() + : Selector(0) + { } - }; - - class TMergingReverseNodeEnumerator: public TReverseNodeEnumerator { - private: - bool Fresh; - TOpaqueTrie Trie; - const TOffsetMap& MergeMap; - TVector<TBranchPoint> Trace; - TOffsetDeltas OffsetIndex; - - public: - TMergingReverseNodeEnumerator(const TOpaqueTrie& trie, const TOffsetMap& mergers) - : Fresh(true) - , Trie(trie) - , MergeMap(mergers) - { - } - - bool Move() override { - if (Fresh) { - Trace.push_back(TBranchPoint(Trie.Data, 0, Trie.SkipFunction)); - Fresh = false; - } else { - if (Trace.empty()) - return false; - - Trace.pop_back(); - - if (Trace.empty()) - return false; - } - - size_t nextnode = Trace.back().NextNode(MergeMap); - - while (nextnode) { - Trace.push_back(TBranchPoint(Trie.Data, nextnode, Trie.SkipFunction)); - nextnode = Trace.back().NextNode(MergeMap); - } - - return (!Trace.empty()); - } - - const TNode& Get() const { - return Trace.back().Node; - } - size_t GetLeafLength() const override { - return Get().GetLeafLength(); - } - - // Returns recalculated offset from the end of the current node - size_t PrepareOffset(size_t absoffset, size_t minilength) { - if (!absoffset) - return NPOS; - - if (MergeMap.Contains(absoffset)) - absoffset = MergeMap.Get(absoffset); - return minilength - OffsetIndex.Get(Trie.Length - absoffset); - } - - size_t RecreateNode(char* buffer, size_t resultLength) override { - TWriteableNode newNode(Get(), Trie.Data); - newNode.ForwardOffset = PrepareOffset(Get().GetForwardOffset(), resultLength); - newNode.LeftOffset = PrepareOffset(Get().GetLeftOffset(), resultLength); - newNode.RightOffset = PrepareOffset(Get().GetRightOffset(), resultLength); - - if (!buffer) - return newNode.Measure(); - - const size_t len = newNode.Pack(buffer); - OffsetIndex.Add(Trie.Length - Get().GetOffset(), resultLength + len); - - return len; - } - }; - + + TBranchPoint(const char* data, size_t offset, const ILeafSkipper& skipFunction) + : Node(data, offset, skipFunction) + , Selector(0) + { + } + + bool IsFinal() const { + return Node.IsFinal(); + } + + // NextNode returns child nodes, starting from the last node: Right, then Left, then Forward + size_t NextNode(const TOffsetMap& mergedNodes) { + while (Selector < 3) { + size_t nextOffset = 0; + + switch (++Selector) { + case 1: + if (Node.GetRightOffset()) + nextOffset = Node.GetRightOffset(); + break; + + case 2: + if (Node.GetLeftOffset()) + nextOffset = Node.GetLeftOffset(); + break; + + case 3: + if (Node.GetForwardOffset()) + nextOffset = Node.GetForwardOffset(); + break; + + default: + break; + } + + if (nextOffset && !mergedNodes.Contains(nextOffset)) + return nextOffset; + } + return 0; + } + }; + + class TMergingReverseNodeEnumerator: public TReverseNodeEnumerator { + private: + bool Fresh; + TOpaqueTrie Trie; + const TOffsetMap& MergeMap; + TVector<TBranchPoint> Trace; + TOffsetDeltas OffsetIndex; + + public: + TMergingReverseNodeEnumerator(const TOpaqueTrie& trie, const TOffsetMap& mergers) + : Fresh(true) + , Trie(trie) + , MergeMap(mergers) + { + } + + bool Move() override { + if (Fresh) { + Trace.push_back(TBranchPoint(Trie.Data, 0, Trie.SkipFunction)); + Fresh = false; + } else { + if (Trace.empty()) + return false; + + Trace.pop_back(); + + if (Trace.empty()) + return false; + } + + size_t nextnode = Trace.back().NextNode(MergeMap); + + while (nextnode) { + Trace.push_back(TBranchPoint(Trie.Data, nextnode, Trie.SkipFunction)); + nextnode = Trace.back().NextNode(MergeMap); + } + + return (!Trace.empty()); + } + + const TNode& Get() const { + return Trace.back().Node; + } + size_t GetLeafLength() const override { + return Get().GetLeafLength(); + } + + // Returns recalculated offset from the end of the current node + size_t PrepareOffset(size_t absoffset, size_t minilength) { + if (!absoffset) + return NPOS; + + if (MergeMap.Contains(absoffset)) + absoffset = MergeMap.Get(absoffset); + return minilength - OffsetIndex.Get(Trie.Length - absoffset); + } + + size_t RecreateNode(char* buffer, size_t resultLength) override { + TWriteableNode newNode(Get(), Trie.Data); + newNode.ForwardOffset = PrepareOffset(Get().GetForwardOffset(), resultLength); + newNode.LeftOffset = PrepareOffset(Get().GetLeftOffset(), resultLength); + newNode.RightOffset = PrepareOffset(Get().GetRightOffset(), resultLength); + + if (!buffer) + return newNode.Measure(); + + const size_t len = newNode.Pack(buffer); + OffsetIndex.Add(Trie.Length - Get().GetOffset(), resultLength + len); + + return len; + } + }; + } - static void AddPiece(TPieceIndex& index, size_t offset, size_t len) { - index[len].push_back(offset); - } - - static TOffsetMap FindEquivalentSubtries(const TOpaqueTrie& trie, bool verbose, size_t minMergeSize) { - // Tree nodes, arranged by span length. - // When all nodes of a given size are considered, they pop off the queue. - TPieceIndex subtries; - TOffsetMap merger; - // Start walking the trie from head. - AddPiece(subtries, 0, trie.Length); - - size_t counter = 0; - // Now consider all nodes with sizeable continuations - for (size_t curlen = trie.Length; curlen >= minMergeSize && !subtries.empty(); curlen--) { - TPieceIndex::iterator iit = subtries.find(curlen); - - if (iit == subtries.end()) - continue; // fast forward to the next available length value - - TOffsetList& batch = iit->second; - TPieceComparer comparer(trie.Data, curlen); - Sort(batch.begin(), batch.end(), comparer); - - TOffsetList::iterator it = batch.begin(); - while (it != batch.end()) { - if (verbose) - ShowProgress(++counter); - - size_t offset = *it; - - // Fill the array with the subnodes of the element - TNode node(trie.Data, offset, trie.SkipFunction); - size_t end = offset + curlen; - if (size_t rightOffset = node.GetRightOffset()) { - AddPiece(subtries, rightOffset, end - rightOffset); - end = rightOffset; - } - if (size_t leftOffset = node.GetLeftOffset()) { - AddPiece(subtries, leftOffset, end - leftOffset); - end = leftOffset; - } - if (size_t forwardOffset = node.GetForwardOffset()) { - AddPiece(subtries, forwardOffset, end - forwardOffset); - } - - while (++it != batch.end()) { - // Find next different; until then, just add the offsets to the list of merged nodes. - size_t nextoffset = *it; - - if (memcmp(trie.Data + offset, trie.Data + nextoffset, curlen)) - break; - - merger.Add(nextoffset, offset); - } - } - - subtries.erase(curlen); + static void AddPiece(TPieceIndex& index, size_t offset, size_t len) { + index[len].push_back(offset); + } + + static TOffsetMap FindEquivalentSubtries(const TOpaqueTrie& trie, bool verbose, size_t minMergeSize) { + // Tree nodes, arranged by span length. + // When all nodes of a given size are considered, they pop off the queue. + TPieceIndex subtries; + TOffsetMap merger; + // Start walking the trie from head. + AddPiece(subtries, 0, trie.Length); + + size_t counter = 0; + // Now consider all nodes with sizeable continuations + for (size_t curlen = trie.Length; curlen >= minMergeSize && !subtries.empty(); curlen--) { + TPieceIndex::iterator iit = subtries.find(curlen); + + if (iit == subtries.end()) + continue; // fast forward to the next available length value + + TOffsetList& batch = iit->second; + TPieceComparer comparer(trie.Data, curlen); + Sort(batch.begin(), batch.end(), comparer); + + TOffsetList::iterator it = batch.begin(); + while (it != batch.end()) { + if (verbose) + ShowProgress(++counter); + + size_t offset = *it; + + // Fill the array with the subnodes of the element + TNode node(trie.Data, offset, trie.SkipFunction); + size_t end = offset + curlen; + if (size_t rightOffset = node.GetRightOffset()) { + AddPiece(subtries, rightOffset, end - rightOffset); + end = rightOffset; + } + if (size_t leftOffset = node.GetLeftOffset()) { + AddPiece(subtries, leftOffset, end - leftOffset); + end = leftOffset; + } + if (size_t forwardOffset = node.GetForwardOffset()) { + AddPiece(subtries, forwardOffset, end - forwardOffset); + } + + while (++it != batch.end()) { + // Find next different; until then, just add the offsets to the list of merged nodes. + size_t nextoffset = *it; + + if (memcmp(trie.Data + offset, trie.Data + nextoffset, curlen)) + break; + + merger.Add(nextoffset, offset); + } + } + + subtries.erase(curlen); + } + if (verbose) { + Cerr << counter << Endl; } - if (verbose) { - Cerr << counter << Endl; - } - return merger; + return merger; } - - size_t RawCompactTrieMinimizeImpl(IOutputStream& os, TOpaqueTrie& trie, bool verbose, size_t minMergeSize, EMinimizeMode mode) { - if (!trie.Data || !trie.Length) { - return 0; - } - - TOffsetMap merger = FindEquivalentSubtries(trie, verbose, minMergeSize); - TMergingReverseNodeEnumerator enumerator(trie, merger); - - if (mode == MM_DEFAULT) - return WriteTrieBackwards(os, enumerator, verbose); - else - return WriteTrieBackwardsNoAlloc(os, enumerator, trie, mode); + + size_t RawCompactTrieMinimizeImpl(IOutputStream& os, TOpaqueTrie& trie, bool verbose, size_t minMergeSize, EMinimizeMode mode) { + if (!trie.Data || !trie.Length) { + return 0; + } + + TOffsetMap merger = FindEquivalentSubtries(trie, verbose, minMergeSize); + TMergingReverseNodeEnumerator enumerator(trie, merger); + + if (mode == MM_DEFAULT) + return WriteTrieBackwards(os, enumerator, verbose); + else + return WriteTrieBackwardsNoAlloc(os, enumerator, trie, mode); } } diff --git a/library/cpp/containers/comptrie/minimize.h b/library/cpp/containers/comptrie/minimize.h index 2464571437..baaa431d04 100644 --- a/library/cpp/containers/comptrie/minimize.h +++ b/library/cpp/containers/comptrie/minimize.h @@ -6,24 +6,24 @@ class IOutputStream; namespace NCompactTrie { - size_t MeasureOffset(size_t offset); + size_t MeasureOffset(size_t offset); - enum EMinimizeMode { - MM_DEFAULT, // alollocate new memory for minimized tree - MM_NOALLOC, // minimize tree in the same buffer - MM_INPLACE // do not write tree to the stream, but move to the buffer beginning - }; + enum EMinimizeMode { + MM_DEFAULT, // alollocate new memory for minimized tree + MM_NOALLOC, // minimize tree in the same buffer + MM_INPLACE // do not write tree to the stream, but move to the buffer beginning + }; - // Return value: size of the minimized trie. - size_t RawCompactTrieMinimizeImpl(IOutputStream& os, TOpaqueTrie& trie, bool verbose, size_t minMergeSize, EMinimizeMode mode); + // Return value: size of the minimized trie. + size_t RawCompactTrieMinimizeImpl(IOutputStream& os, TOpaqueTrie& trie, bool verbose, size_t minMergeSize, EMinimizeMode mode); - // Return value: size of the minimized trie. - template <class TPacker> - size_t CompactTrieMinimizeImpl(IOutputStream& os, const char* data, size_t datalength, bool verbose, const TPacker* packer, EMinimizeMode mode) { - TPackerLeafSkipper<TPacker> skipper(packer); - size_t minmerge = MeasureOffset(datalength); - TOpaqueTrie trie(data, datalength, skipper); - return RawCompactTrieMinimizeImpl(os, trie, verbose, minmerge, mode); - } + // Return value: size of the minimized trie. + template <class TPacker> + size_t CompactTrieMinimizeImpl(IOutputStream& os, const char* data, size_t datalength, bool verbose, const TPacker* packer, EMinimizeMode mode) { + TPackerLeafSkipper<TPacker> skipper(packer); + size_t minmerge = MeasureOffset(datalength); + TOpaqueTrie trie(data, datalength, skipper); + return RawCompactTrieMinimizeImpl(os, trie, verbose, minmerge, mode); + } } diff --git a/library/cpp/containers/comptrie/node.cpp b/library/cpp/containers/comptrie/node.cpp index cd98e6b4d6..5fd22f15ec 100644 --- a/library/cpp/containers/comptrie/node.cpp +++ b/library/cpp/containers/comptrie/node.cpp @@ -6,74 +6,74 @@ #include <util/generic/yexception.h> namespace NCompactTrie { - TNode::TNode() - : Offset(0) - , LeafLength(0) - , CoreLength(0) - , Label(0) - { - for (auto& offset : Offsets) { - offset = 0; - } + TNode::TNode() + : Offset(0) + , LeafLength(0) + , CoreLength(0) + , Label(0) + { + for (auto& offset : Offsets) { + offset = 0; + } } - // We believe that epsilon links are found only on the forward-position and that afer jumping an epsilon link you come to an ordinary node. - - TNode::TNode(const char* data, size_t offset, const ILeafSkipper& skipFunction) - : Offset(offset) - , LeafLength(0) - , CoreLength(0) - , Label(0) - { - for (auto& anOffset : Offsets) { - anOffset = 0; - } - if (!data) - return; // empty constructor - - const char* datapos = data + offset; - char flags = *(datapos++); - Y_ASSERT(!IsEpsilonLink(flags)); - Label = *(datapos++); + // We believe that epsilon links are found only on the forward-position and that afer jumping an epsilon link you come to an ordinary node. - size_t leftsize = LeftOffsetLen(flags); - size_t& leftOffset = Offsets[D_LEFT]; - leftOffset = UnpackOffset(datapos, leftsize); - if (leftOffset) { - leftOffset += Offset; - } - datapos += leftsize; + TNode::TNode(const char* data, size_t offset, const ILeafSkipper& skipFunction) + : Offset(offset) + , LeafLength(0) + , CoreLength(0) + , Label(0) + { + for (auto& anOffset : Offsets) { + anOffset = 0; + } + if (!data) + return; // empty constructor - size_t rightsize = RightOffsetLen(flags); - size_t& rightOffset = Offsets[D_RIGHT]; - rightOffset = UnpackOffset(datapos, rightsize); - if (rightOffset) { - rightOffset += Offset; - } - datapos += rightsize; - - if (flags & MT_FINAL) { - Offsets[D_FINAL] = datapos - data; - LeafLength = skipFunction.SkipLeaf(datapos); - } + const char* datapos = data + offset; + char flags = *(datapos++); + Y_ASSERT(!IsEpsilonLink(flags)); + Label = *(datapos++); - CoreLength = 2 + leftsize + rightsize + LeafLength; - if (flags & MT_NEXT) { - size_t& forwardOffset = Offsets[D_NEXT]; - forwardOffset = Offset + CoreLength; - // There might be an epsilon link at the forward position. - // If so, set the ForwardOffset to the value that points to the link's end. - const char* forwardPos = data + forwardOffset; - const char forwardFlags = *forwardPos; - if (IsEpsilonLink(forwardFlags)) { - // Jump through the epsilon link. - size_t epsilonOffset = UnpackOffset(forwardPos + 1, forwardFlags & MT_SIZEMASK); - if (!epsilonOffset) { - ythrow yexception() << "Corrupted epsilon link"; - } - forwardOffset += epsilonOffset; + size_t leftsize = LeftOffsetLen(flags); + size_t& leftOffset = Offsets[D_LEFT]; + leftOffset = UnpackOffset(datapos, leftsize); + if (leftOffset) { + leftOffset += Offset; + } + datapos += leftsize; + + size_t rightsize = RightOffsetLen(flags); + size_t& rightOffset = Offsets[D_RIGHT]; + rightOffset = UnpackOffset(datapos, rightsize); + if (rightOffset) { + rightOffset += Offset; + } + datapos += rightsize; + + if (flags & MT_FINAL) { + Offsets[D_FINAL] = datapos - data; + LeafLength = skipFunction.SkipLeaf(datapos); + } + + CoreLength = 2 + leftsize + rightsize + LeafLength; + if (flags & MT_NEXT) { + size_t& forwardOffset = Offsets[D_NEXT]; + forwardOffset = Offset + CoreLength; + // There might be an epsilon link at the forward position. + // If so, set the ForwardOffset to the value that points to the link's end. + const char* forwardPos = data + forwardOffset; + const char forwardFlags = *forwardPos; + if (IsEpsilonLink(forwardFlags)) { + // Jump through the epsilon link. + size_t epsilonOffset = UnpackOffset(forwardPos + 1, forwardFlags & MT_SIZEMASK); + if (!epsilonOffset) { + ythrow yexception() << "Corrupted epsilon link"; + } + forwardOffset += epsilonOffset; } } } - + } diff --git a/library/cpp/containers/comptrie/node.h b/library/cpp/containers/comptrie/node.h index 9a936998b5..d6f4317db0 100644 --- a/library/cpp/containers/comptrie/node.h +++ b/library/cpp/containers/comptrie/node.h @@ -3,78 +3,78 @@ #include <cstddef> namespace NCompactTrie { - class ILeafSkipper; + class ILeafSkipper; - enum TDirection { - D_LEFT, - D_FINAL, - D_NEXT, - D_RIGHT, - D_MAX - }; - - inline TDirection& operator++(TDirection& direction) { - direction = static_cast<TDirection>(direction + 1); - return direction; - } + enum TDirection { + D_LEFT, + D_FINAL, + D_NEXT, + D_RIGHT, + D_MAX + }; - inline TDirection& operator--(TDirection& direction) { - direction = static_cast<TDirection>(direction - 1); - return direction; - } + inline TDirection& operator++(TDirection& direction) { + direction = static_cast<TDirection>(direction + 1); + return direction; + } - class TNode { - public: - TNode(); - // Processes epsilon links and sets ForwardOffset to correct value. Assumes an epsilon link doesn't point to an epsilon link. - TNode(const char* data, size_t offset, const ILeafSkipper& skipFunction); + inline TDirection& operator--(TDirection& direction) { + direction = static_cast<TDirection>(direction - 1); + return direction; + } - size_t GetOffset() const { - return Offset; - } + class TNode { + public: + TNode(); + // Processes epsilon links and sets ForwardOffset to correct value. Assumes an epsilon link doesn't point to an epsilon link. + TNode(const char* data, size_t offset, const ILeafSkipper& skipFunction); - size_t GetLeafOffset() const { - return Offsets[D_FINAL]; - } - size_t GetLeafLength() const { - return LeafLength; - } - size_t GetCoreLength() const { - return CoreLength; - } + size_t GetOffset() const { + return Offset; + } - size_t GetOffsetByDirection(TDirection direction) const { - return Offsets[direction]; - } + size_t GetLeafOffset() const { + return Offsets[D_FINAL]; + } + size_t GetLeafLength() const { + return LeafLength; + } + size_t GetCoreLength() const { + return CoreLength; + } - size_t GetForwardOffset() const { - return Offsets[D_NEXT]; - } - size_t GetLeftOffset() const { - return Offsets[D_LEFT]; - } - size_t GetRightOffset() const { - return Offsets[D_RIGHT]; - } - char GetLabel() const { - return Label; - } + size_t GetOffsetByDirection(TDirection direction) const { + return Offsets[direction]; + } - bool IsFinal() const { - return GetLeafOffset() != 0; - } + size_t GetForwardOffset() const { + return Offsets[D_NEXT]; + } + size_t GetLeftOffset() const { + return Offsets[D_LEFT]; + } + size_t GetRightOffset() const { + return Offsets[D_RIGHT]; + } + char GetLabel() const { + return Label; + } - bool HasEpsilonLinkForward() const { - return GetForwardOffset() > Offset + CoreLength; - } - - private: - size_t Offsets[D_MAX]; - size_t Offset; - size_t LeafLength; - size_t CoreLength; + bool IsFinal() const { + return GetLeafOffset() != 0; + } - char Label; - }; + bool HasEpsilonLinkForward() const { + return GetForwardOffset() > Offset + CoreLength; + } -} + private: + size_t Offsets[D_MAX]; + size_t Offset; + size_t LeafLength; + size_t CoreLength; + + char Label; + }; + +} diff --git a/library/cpp/containers/comptrie/opaque_trie_iterator.cpp b/library/cpp/containers/comptrie/opaque_trie_iterator.cpp index d1916358aa..5fd3914be6 100644 --- a/library/cpp/containers/comptrie/opaque_trie_iterator.cpp +++ b/library/cpp/containers/comptrie/opaque_trie_iterator.cpp @@ -3,229 +3,229 @@ #include "node.h" namespace NCompactTrie { - TOpaqueTrieIterator::TOpaqueTrieIterator(const TOpaqueTrie& trie, const char* emptyValue, bool atend, - size_t maxKeyLength) - : Trie(trie) - , EmptyValue(emptyValue) - , AtEmptyValue(emptyValue && !atend) - , MaxKeyLength(maxKeyLength) - { - if (!AtEmptyValue && !atend) - Forward(); - } - - bool TOpaqueTrieIterator::operator==(const TOpaqueTrieIterator& rhs) const { - return (Trie == rhs.Trie && - Forks == rhs.Forks && - EmptyValue == rhs.EmptyValue && - AtEmptyValue == rhs.AtEmptyValue && - MaxKeyLength == rhs.MaxKeyLength); - } - - bool TOpaqueTrieIterator::HasMaxKeyLength() const { - return MaxKeyLength != size_t(-1) && MeasureNarrowKey() == MaxKeyLength; - } - - bool TOpaqueTrieIterator::Forward() { - if (AtEmptyValue) { - AtEmptyValue = false; - bool res = Forward(); // TODO delete this after format change - if (res && MeasureNarrowKey() != 0) { - return res; // there was not "\0" key - } - // otherwise we are skipping "\0" key - } - - if (!Trie.Length) - return false; - - if (Forks.Empty()) { - TFork fork(Trie.Data, 0, Trie.Length, Trie.SkipFunction); - Forks.Push(fork); - } else { - TFork* topFork = &Forks.Top(); - while (!topFork->NextDirection()) { - if (topFork->Node.GetOffset() >= Trie.Length) - return false; - Forks.Pop(); - if (Forks.Empty()) - return false; - topFork = &Forks.Top(); - } - } - - Y_ASSERT(!Forks.Empty()); - while (Forks.Top().CurrentDirection != D_FINAL && !HasMaxKeyLength()) { - TFork nextFork = Forks.Top().NextFork(Trie.SkipFunction); - Forks.Push(nextFork); - } - TFork& top = Forks.Top(); - static_assert(D_FINAL < D_NEXT, "relative order of NEXT and FINAL directions has changed"); - if (HasMaxKeyLength() && top.CurrentDirection == D_FINAL && top.HasDirection(D_NEXT)) { - top.NextDirection(); - } - return true; - } - - bool TOpaqueTrieIterator::Backward() { - if (AtEmptyValue) + TOpaqueTrieIterator::TOpaqueTrieIterator(const TOpaqueTrie& trie, const char* emptyValue, bool atend, + size_t maxKeyLength) + : Trie(trie) + , EmptyValue(emptyValue) + , AtEmptyValue(emptyValue && !atend) + , MaxKeyLength(maxKeyLength) + { + if (!AtEmptyValue && !atend) + Forward(); + } + + bool TOpaqueTrieIterator::operator==(const TOpaqueTrieIterator& rhs) const { + return (Trie == rhs.Trie && + Forks == rhs.Forks && + EmptyValue == rhs.EmptyValue && + AtEmptyValue == rhs.AtEmptyValue && + MaxKeyLength == rhs.MaxKeyLength); + } + + bool TOpaqueTrieIterator::HasMaxKeyLength() const { + return MaxKeyLength != size_t(-1) && MeasureNarrowKey() == MaxKeyLength; + } + + bool TOpaqueTrieIterator::Forward() { + if (AtEmptyValue) { + AtEmptyValue = false; + bool res = Forward(); // TODO delete this after format change + if (res && MeasureNarrowKey() != 0) { + return res; // there was not "\0" key + } + // otherwise we are skipping "\0" key + } + + if (!Trie.Length) return false; - if (!Trie.Length) { - if (EmptyValue) { - // A trie that has only the empty value; - // we are not at the empty value, so move to it. + if (Forks.Empty()) { + TFork fork(Trie.Data, 0, Trie.Length, Trie.SkipFunction); + Forks.Push(fork); + } else { + TFork* topFork = &Forks.Top(); + while (!topFork->NextDirection()) { + if (topFork->Node.GetOffset() >= Trie.Length) + return false; + Forks.Pop(); + if (Forks.Empty()) + return false; + topFork = &Forks.Top(); + } + } + + Y_ASSERT(!Forks.Empty()); + while (Forks.Top().CurrentDirection != D_FINAL && !HasMaxKeyLength()) { + TFork nextFork = Forks.Top().NextFork(Trie.SkipFunction); + Forks.Push(nextFork); + } + TFork& top = Forks.Top(); + static_assert(D_FINAL < D_NEXT, "relative order of NEXT and FINAL directions has changed"); + if (HasMaxKeyLength() && top.CurrentDirection == D_FINAL && top.HasDirection(D_NEXT)) { + top.NextDirection(); + } + return true; + } + + bool TOpaqueTrieIterator::Backward() { + if (AtEmptyValue) + return false; + + if (!Trie.Length) { + if (EmptyValue) { + // A trie that has only the empty value; + // we are not at the empty value, so move to it. AtEmptyValue = true; return true; - } else { - // Empty trie. - return false; + } else { + // Empty trie. + return false; + } + } + + if (Forks.Empty()) { + TFork fork(Trie.Data, 0, Trie.Length, Trie.SkipFunction); + fork.LastDirection(); + Forks.Push(fork); + } else { + TFork* topFork = &Forks.Top(); + while (!topFork->PrevDirection()) { + if (topFork->Node.GetOffset() >= Trie.Length) + return false; + Forks.Pop(); + if (!Forks.Empty()) { + topFork = &Forks.Top(); + } else { + // When there are no more forks, + // we have to iterate over the empty value. + if (!EmptyValue) + return false; + AtEmptyValue = true; + return true; + } } } - if (Forks.Empty()) { - TFork fork(Trie.Data, 0, Trie.Length, Trie.SkipFunction); - fork.LastDirection(); - Forks.Push(fork); - } else { - TFork* topFork = &Forks.Top(); - while (!topFork->PrevDirection()) { - if (topFork->Node.GetOffset() >= Trie.Length) - return false; - Forks.Pop(); - if (!Forks.Empty()) { - topFork = &Forks.Top(); - } else { - // When there are no more forks, - // we have to iterate over the empty value. - if (!EmptyValue) - return false; - AtEmptyValue = true; - return true; - } - } - } - - Y_ASSERT(!Forks.Empty()); - while (Forks.Top().CurrentDirection != D_FINAL && !HasMaxKeyLength()) { - TFork nextFork = Forks.Top().NextFork(Trie.SkipFunction); - nextFork.LastDirection(); - Forks.Push(nextFork); - } - TFork& top = Forks.Top(); - static_assert(D_FINAL < D_NEXT, "relative order of NEXT and FINAL directions has changed"); - if (HasMaxKeyLength() && top.CurrentDirection == D_NEXT && top.HasDirection(D_FINAL)) { - top.PrevDirection(); - } - if (MeasureNarrowKey() == 0) { - // This is the '\0' key, skip it and get to the EmptyValue. - AtEmptyValue = true; - Forks.Clear(); - } - return true; - } - - const char* TOpaqueTrieIterator::GetValuePtr() const { - if (!Forks.Empty()) { - const TFork& lastFork = Forks.Top(); - Y_ASSERT(lastFork.Node.IsFinal() && lastFork.CurrentDirection == D_FINAL); - return Trie.Data + lastFork.GetValueOffset(); - } - Y_ASSERT(AtEmptyValue); - return EmptyValue; - } - - //------------------------------------------------------------------------- - - TString TForkStack::GetKey() const { - if (HasEmptyKey()) { - return TString(); - } - - TString result(Key); - if (TopHasLabelInKey()) { - result.append(Top().GetLabel()); - } - return result; - } - - bool TForkStack::HasEmptyKey() const { - // Special case: if we get a single zero label, treat it as an empty key - // TODO delete this after format change - if (TopHasLabelInKey()) { - return Key.size() == 0 && Top().GetLabel() == '\0'; - } else { - return Key.size() == 1 && Key[0] == '\0'; - } - } - - size_t TForkStack::MeasureKey() const { - size_t result = Key.size() + (TopHasLabelInKey() ? 1 : 0); - if (result == 1 && HasEmptyKey()) { - return 0; - } - return result; - } - - //------------------------------------------------------------------------- - - TFork::TFork(const char* data, size_t offset, size_t limit, const ILeafSkipper& skipper) - : Node(data, offset, skipper) - , Data(data) - , Limit(limit) - , CurrentDirection(TDirection(0)) - { + Y_ASSERT(!Forks.Empty()); + while (Forks.Top().CurrentDirection != D_FINAL && !HasMaxKeyLength()) { + TFork nextFork = Forks.Top().NextFork(Trie.SkipFunction); + nextFork.LastDirection(); + Forks.Push(nextFork); + } + TFork& top = Forks.Top(); + static_assert(D_FINAL < D_NEXT, "relative order of NEXT and FINAL directions has changed"); + if (HasMaxKeyLength() && top.CurrentDirection == D_NEXT && top.HasDirection(D_FINAL)) { + top.PrevDirection(); + } + if (MeasureNarrowKey() == 0) { + // This is the '\0' key, skip it and get to the EmptyValue. + AtEmptyValue = true; + Forks.Clear(); + } + return true; + } + + const char* TOpaqueTrieIterator::GetValuePtr() const { + if (!Forks.Empty()) { + const TFork& lastFork = Forks.Top(); + Y_ASSERT(lastFork.Node.IsFinal() && lastFork.CurrentDirection == D_FINAL); + return Trie.Data + lastFork.GetValueOffset(); + } + Y_ASSERT(AtEmptyValue); + return EmptyValue; + } + + //------------------------------------------------------------------------- + + TString TForkStack::GetKey() const { + if (HasEmptyKey()) { + return TString(); + } + + TString result(Key); + if (TopHasLabelInKey()) { + result.append(Top().GetLabel()); + } + return result; + } + + bool TForkStack::HasEmptyKey() const { + // Special case: if we get a single zero label, treat it as an empty key + // TODO delete this after format change + if (TopHasLabelInKey()) { + return Key.size() == 0 && Top().GetLabel() == '\0'; + } else { + return Key.size() == 1 && Key[0] == '\0'; + } + } + + size_t TForkStack::MeasureKey() const { + size_t result = Key.size() + (TopHasLabelInKey() ? 1 : 0); + if (result == 1 && HasEmptyKey()) { + return 0; + } + return result; + } + + //------------------------------------------------------------------------- + + TFork::TFork(const char* data, size_t offset, size_t limit, const ILeafSkipper& skipper) + : Node(data, offset, skipper) + , Data(data) + , Limit(limit) + , CurrentDirection(TDirection(0)) + { #if COMPTRIE_DATA_CHECK - if (Node.GetOffset() >= Limit - 1) - ythrow yexception() << "gone beyond the limit, data is corrupted"; + if (Node.GetOffset() >= Limit - 1) + ythrow yexception() << "gone beyond the limit, data is corrupted"; #endif - while (CurrentDirection < D_MAX && !HasDirection(CurrentDirection)) { - ++CurrentDirection; - } - } - - bool TFork::operator==(const TFork& rhs) const { - return (Data == rhs.Data && - Node.GetOffset() == rhs.Node.GetOffset() && - CurrentDirection == rhs.CurrentDirection); - } - - inline bool TFork::NextDirection() { - do { - ++CurrentDirection; - } while (CurrentDirection < D_MAX && !HasDirection(CurrentDirection)); - return CurrentDirection < D_MAX; - } - - inline bool TFork::PrevDirection() { - if (CurrentDirection == TDirection(0)) { - return false; - } - do { - --CurrentDirection; - } while (CurrentDirection > 0 && !HasDirection(CurrentDirection)); - return HasDirection(CurrentDirection); - } - - void TFork::LastDirection() { - CurrentDirection = D_MAX; - PrevDirection(); - } - - bool TFork::SetDirection(TDirection direction) { - if (!HasDirection(direction)) { - return false; - } - CurrentDirection = direction; - return true; - } - - char TFork::GetLabel() const { - return Node.GetLabel(); - } - - size_t TFork::GetValueOffset() const { - return Node.GetLeafOffset(); + while (CurrentDirection < D_MAX && !HasDirection(CurrentDirection)) { + ++CurrentDirection; + } + } + + bool TFork::operator==(const TFork& rhs) const { + return (Data == rhs.Data && + Node.GetOffset() == rhs.Node.GetOffset() && + CurrentDirection == rhs.CurrentDirection); + } + + inline bool TFork::NextDirection() { + do { + ++CurrentDirection; + } while (CurrentDirection < D_MAX && !HasDirection(CurrentDirection)); + return CurrentDirection < D_MAX; + } + + inline bool TFork::PrevDirection() { + if (CurrentDirection == TDirection(0)) { + return false; + } + do { + --CurrentDirection; + } while (CurrentDirection > 0 && !HasDirection(CurrentDirection)); + return HasDirection(CurrentDirection); + } + + void TFork::LastDirection() { + CurrentDirection = D_MAX; + PrevDirection(); + } + + bool TFork::SetDirection(TDirection direction) { + if (!HasDirection(direction)) { + return false; + } + CurrentDirection = direction; + return true; + } + + char TFork::GetLabel() const { + return Node.GetLabel(); + } + + size_t TFork::GetValueOffset() const { + return Node.GetLeafOffset(); } } diff --git a/library/cpp/containers/comptrie/opaque_trie_iterator.h b/library/cpp/containers/comptrie/opaque_trie_iterator.h index 8e615d7e70..195da3c191 100644 --- a/library/cpp/containers/comptrie/opaque_trie_iterator.h +++ b/library/cpp/containers/comptrie/opaque_trie_iterator.h @@ -9,258 +9,258 @@ #include <util/generic/yexception.h> namespace NCompactTrie { - class ILeafSkipper; - - class TFork { // Auxiliary class for a branching point in the iterator - public: - TNode Node; - const char* Data; - size_t Limit; // valid data is in range [Data + Node.GetOffset(), Data + Limit) - TDirection CurrentDirection; - - public: - TFork(const char* data, size_t offset, size_t limit, const ILeafSkipper& skipper); - - bool operator==(const TFork& rhs) const; - - bool HasLabelInKey() const { - return CurrentDirection == D_NEXT || CurrentDirection == D_FINAL; - } - - bool NextDirection(); - bool PrevDirection(); - void LastDirection(); - - bool HasDirection(TDirection direction) const { - return Node.GetOffsetByDirection(direction); - } - // If the fork doesn't have the specified direction, - // leaves the direction intact and returns false. - // Otherwise returns true. - bool SetDirection(TDirection direction); - TFork NextFork(const ILeafSkipper& skipper) const; - - char GetLabel() const; - size_t GetValueOffset() const; - }; - - inline TFork TFork::NextFork(const ILeafSkipper& skipper) const { - Y_ASSERT(CurrentDirection != D_FINAL); - size_t offset = Node.GetOffsetByDirection(CurrentDirection); - return TFork(Data, offset, Limit, skipper); + class ILeafSkipper; + + class TFork { // Auxiliary class for a branching point in the iterator + public: + TNode Node; + const char* Data; + size_t Limit; // valid data is in range [Data + Node.GetOffset(), Data + Limit) + TDirection CurrentDirection; + + public: + TFork(const char* data, size_t offset, size_t limit, const ILeafSkipper& skipper); + + bool operator==(const TFork& rhs) const; + + bool HasLabelInKey() const { + return CurrentDirection == D_NEXT || CurrentDirection == D_FINAL; + } + + bool NextDirection(); + bool PrevDirection(); + void LastDirection(); + + bool HasDirection(TDirection direction) const { + return Node.GetOffsetByDirection(direction); + } + // If the fork doesn't have the specified direction, + // leaves the direction intact and returns false. + // Otherwise returns true. + bool SetDirection(TDirection direction); + TFork NextFork(const ILeafSkipper& skipper) const; + + char GetLabel() const; + size_t GetValueOffset() const; + }; + + inline TFork TFork::NextFork(const ILeafSkipper& skipper) const { + Y_ASSERT(CurrentDirection != D_FINAL); + size_t offset = Node.GetOffsetByDirection(CurrentDirection); + return TFork(Data, offset, Limit, skipper); } - //------------------------------------------------------------------------------------------------ - class TForkStack { - public: - void Push(const TFork& fork) { - if (TopHasLabelInKey()) { - Key.push_back(Top().GetLabel()); - } - Forks.push_back(fork); - } - - void Pop() { - Forks.pop_back(); - if (TopHasLabelInKey()) { - Key.pop_back(); - } - } - - TFork& Top() { - return Forks.back(); + //------------------------------------------------------------------------------------------------ + class TForkStack { + public: + void Push(const TFork& fork) { + if (TopHasLabelInKey()) { + Key.push_back(Top().GetLabel()); + } + Forks.push_back(fork); + } + + void Pop() { + Forks.pop_back(); + if (TopHasLabelInKey()) { + Key.pop_back(); + } + } + + TFork& Top() { + return Forks.back(); + } + const TFork& Top() const { + return Forks.back(); + } + + bool Empty() const { + return Forks.empty(); + } + + void Clear() { + Forks.clear(); + Key.clear(); + } + + bool operator==(const TForkStack& other) const { + return Forks == other.Forks; + } + bool operator!=(const TForkStack& other) const { + return !(*this == other); + } + + TString GetKey() const; + size_t MeasureKey() const; + + private: + TVector<TFork> Forks; + TString Key; + + private: + bool TopHasLabelInKey() const { + return !Empty() && Top().HasLabelInKey(); + } + bool HasEmptyKey() const; + }; + + //------------------------------------------------------------------------------------------------ + + template <class TSymbol> + struct TConvertRawKey { + typedef typename TCompactTrieKeySelector<TSymbol>::TKey TKey; + static TKey Get(const TString& rawkey) { + TKey result; + const size_t sz = rawkey.size(); + result.reserve(sz / sizeof(TSymbol)); + for (size_t i = 0; i < sz; i += sizeof(TSymbol)) { + TSymbol sym = 0; + for (size_t j = 0; j < sizeof(TSymbol); j++) { + if (sizeof(TSymbol) <= 1) + sym = 0; + else + sym <<= 8; + if (i + j < sz) + sym |= TSymbol(0x00FF & rawkey[i + j]); + } + result.push_back(sym); + } + return result; + } + + static size_t Size(size_t rawsize) { + return rawsize / sizeof(TSymbol); + } + }; + + template <> + struct TConvertRawKey<char> { + static TString Get(const TString& rawkey) { + return rawkey; } - const TFork& Top() const { - return Forks.back(); - } - bool Empty() const { - return Forks.empty(); - } + static size_t Size(size_t rawsize) { + return rawsize; + } + }; + + //------------------------------------------------------------------------------------------------ + class TOpaqueTrieIterator { // Iterator stuff. Stores a stack of visited forks. + public: + TOpaqueTrieIterator(const TOpaqueTrie& trie, const char* emptyValue, bool atend, + size_t maxKeyLength = size_t(-1)); + + bool operator==(const TOpaqueTrieIterator& rhs) const; + bool operator!=(const TOpaqueTrieIterator& rhs) const { + return !(*this == rhs); + } + + bool Forward(); + bool Backward(); + + template <class TSymbol> + bool UpperBound(const typename TCompactTrieKeySelector<TSymbol>::TKeyBuf& key); // True if matched exactly. - void Clear() { - Forks.clear(); - Key.clear(); + template <class TSymbol> + typename TCompactTrieKeySelector<TSymbol>::TKey GetKey() const { + return TConvertRawKey<TSymbol>::Get(GetNarrowKey()); } - bool operator==(const TForkStack& other) const { - return Forks == other.Forks; - } - bool operator!=(const TForkStack& other) const { - return !(*this == other); - } - - TString GetKey() const; - size_t MeasureKey() const; - - private: - TVector<TFork> Forks; - TString Key; - - private: - bool TopHasLabelInKey() const { - return !Empty() && Top().HasLabelInKey(); - } - bool HasEmptyKey() const; - }; - - //------------------------------------------------------------------------------------------------ - - template <class TSymbol> - struct TConvertRawKey { - typedef typename TCompactTrieKeySelector<TSymbol>::TKey TKey; - static TKey Get(const TString& rawkey) { - TKey result; - const size_t sz = rawkey.size(); - result.reserve(sz / sizeof(TSymbol)); - for (size_t i = 0; i < sz; i += sizeof(TSymbol)) { - TSymbol sym = 0; - for (size_t j = 0; j < sizeof(TSymbol); j++) { - if (sizeof(TSymbol) <= 1) - sym = 0; - else - sym <<= 8; - if (i + j < sz) - sym |= TSymbol(0x00FF & rawkey[i + j]); - } - result.push_back(sym); - } - return result; - } - - static size_t Size(size_t rawsize) { - return rawsize / sizeof(TSymbol); - } - }; - - template <> - struct TConvertRawKey<char> { - static TString Get(const TString& rawkey) { - return rawkey; - } - - static size_t Size(size_t rawsize) { - return rawsize; + template <class TSymbol> + size_t MeasureKey() const { + return TConvertRawKey<TSymbol>::Size(MeasureNarrowKey()); } - }; - - //------------------------------------------------------------------------------------------------ - class TOpaqueTrieIterator { // Iterator stuff. Stores a stack of visited forks. - public: - TOpaqueTrieIterator(const TOpaqueTrie& trie, const char* emptyValue, bool atend, - size_t maxKeyLength = size_t(-1)); - - bool operator==(const TOpaqueTrieIterator& rhs) const; - bool operator!=(const TOpaqueTrieIterator& rhs) const { - return !(*this == rhs); - } - - bool Forward(); - bool Backward(); - - template <class TSymbol> - bool UpperBound(const typename TCompactTrieKeySelector<TSymbol>::TKeyBuf& key); // True if matched exactly. - - template <class TSymbol> - typename TCompactTrieKeySelector<TSymbol>::TKey GetKey() const { - return TConvertRawKey<TSymbol>::Get(GetNarrowKey()); - } - - template <class TSymbol> - size_t MeasureKey() const { - return TConvertRawKey<TSymbol>::Size(MeasureNarrowKey()); - } - - TString GetNarrowKey() const { - return Forks.GetKey(); - } - size_t MeasureNarrowKey() const { - return Forks.MeasureKey(); - } - - const char* GetValuePtr() const; // 0 if none - const TNode& GetNode() const { // Could be called for non-empty key and not AtEnd. - return Forks.Top().Node; - } - const TOpaqueTrie& GetTrie() const { - return Trie; - } - - private: - TOpaqueTrie Trie; - TForkStack Forks; - const char* const EmptyValue; - bool AtEmptyValue; - const size_t MaxKeyLength; - - private: - bool HasMaxKeyLength() const; - - template <class TSymbol> - int LongestPrefix(const typename TCompactTrieKeySelector<TSymbol>::TKeyBuf& key); // Used in UpperBound. - }; + + TString GetNarrowKey() const { + return Forks.GetKey(); + } + size_t MeasureNarrowKey() const { + return Forks.MeasureKey(); + } + + const char* GetValuePtr() const; // 0 if none + const TNode& GetNode() const { // Could be called for non-empty key and not AtEnd. + return Forks.Top().Node; + } + const TOpaqueTrie& GetTrie() const { + return Trie; + } + + private: + TOpaqueTrie Trie; + TForkStack Forks; + const char* const EmptyValue; + bool AtEmptyValue; + const size_t MaxKeyLength; + + private: + bool HasMaxKeyLength() const; + + template <class TSymbol> + int LongestPrefix(const typename TCompactTrieKeySelector<TSymbol>::TKeyBuf& key); // Used in UpperBound. + }; template <class TSymbol> - int TOpaqueTrieIterator::LongestPrefix(const typename TCompactTrieKeySelector<TSymbol>::TKeyBuf& key) { - Forks.Clear(); - TFork next(Trie.Data, 0, Trie.Length, Trie.SkipFunction); - for (size_t i = 0; i < key.size(); i++) { - TSymbol symbol = key[i]; - const bool isLastSymbol = (i + 1 == key.size()); - for (i64 shift = (i64)NCompactTrie::ExtraBits<TSymbol>(); shift >= 0; shift -= 8) { - const unsigned char label = (unsigned char)(symbol >> shift); - const bool isLastByte = (isLastSymbol && shift == 0); - do { - Forks.Push(next); - TFork& top = Forks.Top(); - if (label < (unsigned char)top.GetLabel()) { - if (!top.SetDirection(D_LEFT)) - return 1; - } else if (label > (unsigned char)top.GetLabel()) { - if (!top.SetDirection(D_RIGHT)) { - Forks.Pop(); // We don't pass this fork on the way to the upper bound. - return -1; - } - } else if (isLastByte) { // Here and below label == top.GetLabel(). - if (top.SetDirection(D_FINAL)) { - return 0; // Skip the NextFork() call at the end of the cycle. - } else { - top.SetDirection(D_NEXT); - return 1; - } - } else if (!top.SetDirection(D_NEXT)) { - top.SetDirection(D_FINAL); + int TOpaqueTrieIterator::LongestPrefix(const typename TCompactTrieKeySelector<TSymbol>::TKeyBuf& key) { + Forks.Clear(); + TFork next(Trie.Data, 0, Trie.Length, Trie.SkipFunction); + for (size_t i = 0; i < key.size(); i++) { + TSymbol symbol = key[i]; + const bool isLastSymbol = (i + 1 == key.size()); + for (i64 shift = (i64)NCompactTrie::ExtraBits<TSymbol>(); shift >= 0; shift -= 8) { + const unsigned char label = (unsigned char)(symbol >> shift); + const bool isLastByte = (isLastSymbol && shift == 0); + do { + Forks.Push(next); + TFork& top = Forks.Top(); + if (label < (unsigned char)top.GetLabel()) { + if (!top.SetDirection(D_LEFT)) + return 1; + } else if (label > (unsigned char)top.GetLabel()) { + if (!top.SetDirection(D_RIGHT)) { + Forks.Pop(); // We don't pass this fork on the way to the upper bound. + return -1; + } + } else if (isLastByte) { // Here and below label == top.GetLabel(). + if (top.SetDirection(D_FINAL)) { + return 0; // Skip the NextFork() call at the end of the cycle. + } else { + top.SetDirection(D_NEXT); + return 1; + } + } else if (!top.SetDirection(D_NEXT)) { + top.SetDirection(D_FINAL); return -1; } - next = top.NextFork(Trie.SkipFunction); - } while (Forks.Top().CurrentDirection != D_NEXT); // Proceed to the next byte. - } + next = top.NextFork(Trie.SkipFunction); + } while (Forks.Top().CurrentDirection != D_NEXT); // Proceed to the next byte. + } } - // We get here only if the key was empty. - Forks.Push(next); - return 1; + // We get here only if the key was empty. + Forks.Push(next); + return 1; } - template <class TSymbol> - bool TOpaqueTrieIterator::UpperBound(const typename TCompactTrieKeySelector<TSymbol>::TKeyBuf& key) { - Forks.Clear(); - if (key.empty() && EmptyValue) { - AtEmptyValue = true; - return true; - } else { - AtEmptyValue = false; + template <class TSymbol> + bool TOpaqueTrieIterator::UpperBound(const typename TCompactTrieKeySelector<TSymbol>::TKeyBuf& key) { + Forks.Clear(); + if (key.empty() && EmptyValue) { + AtEmptyValue = true; + return true; + } else { + AtEmptyValue = false; + } + const int defect = LongestPrefix<TSymbol>(key); + if (defect > 0) { + // Continue the constructed forks with the smallest key possible. + while (Forks.Top().CurrentDirection != D_FINAL) { + TFork next = Forks.Top().NextFork(Trie.SkipFunction); + Forks.Push(next); + } + } else if (defect < 0) { + Forward(); } - const int defect = LongestPrefix<TSymbol>(key); - if (defect > 0) { - // Continue the constructed forks with the smallest key possible. - while (Forks.Top().CurrentDirection != D_FINAL) { - TFork next = Forks.Top().NextFork(Trie.SkipFunction); - Forks.Push(next); - } - } else if (defect < 0) { - Forward(); - } - return defect == 0; + return defect == 0; } - + } diff --git a/library/cpp/containers/comptrie/prefix_iterator.h b/library/cpp/containers/comptrie/prefix_iterator.h index eb2b2d6878..b369bb4f42 100644 --- a/library/cpp/containers/comptrie/prefix_iterator.h +++ b/library/cpp/containers/comptrie/prefix_iterator.h @@ -1,5 +1,5 @@ #pragma once - + #include "comptrie_trie.h" // Iterates over all prefixes of the given key in the trie. @@ -39,11 +39,11 @@ public: result = Next(); } - operator bool() const { + operator bool() const { return result; } - TPrefixIterator& operator++() { + TPrefixIterator& operator++() { result = Next(); return *this; } diff --git a/library/cpp/containers/comptrie/protopacker.h b/library/cpp/containers/comptrie/protopacker.h index 5bedde270d..3e15866dc5 100644 --- a/library/cpp/containers/comptrie/protopacker.h +++ b/library/cpp/containers/comptrie/protopacker.h @@ -3,7 +3,7 @@ #include <util/stream/mem.h> #include <util/ysaveload.h> -template <class Proto> +template <class Proto> class TProtoPacker { public: TProtoPacker() = default; diff --git a/library/cpp/containers/comptrie/search_iterator.h b/library/cpp/containers/comptrie/search_iterator.h index ad6bcfdf60..247f7e5936 100644 --- a/library/cpp/containers/comptrie/search_iterator.h +++ b/library/cpp/containers/comptrie/search_iterator.h @@ -1,5 +1,5 @@ #pragma once - + #include "comptrie_trie.h" #include "first_symbol_iterator.h" @@ -74,7 +74,7 @@ private: const char* ValuePos = nullptr; }; -template <class TTrie> +template <class TTrie> inline TSearchIterator<TTrie> MakeSearchIterator(const TTrie& trie) { return TSearchIterator<TTrie>(trie); } diff --git a/library/cpp/containers/comptrie/set.h b/library/cpp/containers/comptrie/set.h index ffea92485c..acd43338f0 100644 --- a/library/cpp/containers/comptrie/set.h +++ b/library/cpp/containers/comptrie/set.h @@ -1,16 +1,16 @@ -#pragma once - +#pragma once + #include "comptrie_trie.h" template <typename T = char> -class TCompactTrieSet: public TCompactTrie<T, ui8, TNullPacker<ui8>> { +class TCompactTrieSet: public TCompactTrie<T, ui8, TNullPacker<ui8>> { public: - typedef TCompactTrie<T, ui8, TNullPacker<ui8>> TBase; + typedef TCompactTrie<T, ui8, TNullPacker<ui8>> TBase; - using typename TBase::TBuilder; + using typename TBase::TBuilder; using typename TBase::TKey; using typename TBase::TKeyBuf; - using typename TBase::TSymbol; + using typename TBase::TSymbol; TCompactTrieSet() = default; @@ -20,8 +20,8 @@ public: } template <typename D> - explicit TCompactTrieSet(const TCompactTrie<T, D, TNullPacker<D>>& trie) - : TBase(trie.Data()) // should be binary compatible for any D + explicit TCompactTrieSet(const TCompactTrie<T, D, TNullPacker<D>>& trie) + : TBase(trie.Data()) // should be binary compatible for any D { } diff --git a/library/cpp/containers/comptrie/write_trie_backwards.cpp b/library/cpp/containers/comptrie/write_trie_backwards.cpp index f7459b1c49..fd8c28b0ed 100644 --- a/library/cpp/containers/comptrie/write_trie_backwards.cpp +++ b/library/cpp/containers/comptrie/write_trie_backwards.cpp @@ -7,104 +7,104 @@ #include <util/generic/vector.h> namespace NCompactTrie { - size_t WriteTrieBackwards(IOutputStream& os, TReverseNodeEnumerator& enumerator, bool verbose) { - if (verbose) { - Cerr << "Writing down the trie..." << Endl; - } - - // Rewrite everything from the back, removing unused pieces. - const size_t chunksize = 0x10000; - TVector<char*> resultData; - - resultData.push_back(new char[chunksize]); - char* chunkend = resultData.back() + chunksize; - - size_t resultLength = 0; - size_t chunkLength = 0; - - size_t counter = 0; - TBuffer bufferHolder; - while (enumerator.Move()) { - if (verbose) - ShowProgress(++counter); - - size_t bufferLength = 64 + enumerator.GetLeafLength(); // never know how big leaf data can be - bufferHolder.Clear(); - bufferHolder.Resize(bufferLength); - char* buffer = bufferHolder.Data(); - - size_t nodelength = enumerator.RecreateNode(buffer, resultLength); - Y_ASSERT(nodelength <= bufferLength); - - resultLength += nodelength; - - if (chunkLength + nodelength <= chunksize) { - chunkLength += nodelength; - memcpy(chunkend - chunkLength, buffer, nodelength); - } else { // allocate a new chunk - memcpy(chunkend - chunksize, buffer + nodelength - (chunksize - chunkLength), chunksize - chunkLength); - chunkLength = chunkLength + nodelength - chunksize; - - resultData.push_back(new char[chunksize]); - chunkend = resultData.back() + chunksize; - - while (chunkLength > chunksize) { // allocate a new chunks - chunkLength -= chunksize; - memcpy(chunkend - chunksize, buffer + chunkLength, chunksize); - - resultData.push_back(new char[chunksize]); - chunkend = resultData.back() + chunksize; - } - - memcpy(chunkend - chunkLength, buffer, chunkLength); + size_t WriteTrieBackwards(IOutputStream& os, TReverseNodeEnumerator& enumerator, bool verbose) { + if (verbose) { + Cerr << "Writing down the trie..." << Endl; + } + + // Rewrite everything from the back, removing unused pieces. + const size_t chunksize = 0x10000; + TVector<char*> resultData; + + resultData.push_back(new char[chunksize]); + char* chunkend = resultData.back() + chunksize; + + size_t resultLength = 0; + size_t chunkLength = 0; + + size_t counter = 0; + TBuffer bufferHolder; + while (enumerator.Move()) { + if (verbose) + ShowProgress(++counter); + + size_t bufferLength = 64 + enumerator.GetLeafLength(); // never know how big leaf data can be + bufferHolder.Clear(); + bufferHolder.Resize(bufferLength); + char* buffer = bufferHolder.Data(); + + size_t nodelength = enumerator.RecreateNode(buffer, resultLength); + Y_ASSERT(nodelength <= bufferLength); + + resultLength += nodelength; + + if (chunkLength + nodelength <= chunksize) { + chunkLength += nodelength; + memcpy(chunkend - chunkLength, buffer, nodelength); + } else { // allocate a new chunk + memcpy(chunkend - chunksize, buffer + nodelength - (chunksize - chunkLength), chunksize - chunkLength); + chunkLength = chunkLength + nodelength - chunksize; + + resultData.push_back(new char[chunksize]); + chunkend = resultData.back() + chunksize; + + while (chunkLength > chunksize) { // allocate a new chunks + chunkLength -= chunksize; + memcpy(chunkend - chunksize, buffer + chunkLength, chunksize); + + resultData.push_back(new char[chunksize]); + chunkend = resultData.back() + chunksize; + } + + memcpy(chunkend - chunkLength, buffer, chunkLength); } - } - - if (verbose) - Cerr << counter << Endl; - - // Write the whole thing down - while (!resultData.empty()) { - char* chunk = resultData.back(); - os.Write(chunk + chunksize - chunkLength, chunkLength); - chunkLength = chunksize; - delete[] chunk; - resultData.pop_back(); } - - return resultLength; + + if (verbose) + Cerr << counter << Endl; + + // Write the whole thing down + while (!resultData.empty()) { + char* chunk = resultData.back(); + os.Write(chunk + chunksize - chunkLength, chunkLength); + chunkLength = chunksize; + delete[] chunk; + resultData.pop_back(); + } + + return resultLength; } - size_t WriteTrieBackwardsNoAlloc(IOutputStream& os, TReverseNodeEnumerator& enumerator, TOpaqueTrie& trie, EMinimizeMode mode) { - char* data = const_cast<char*>(trie.Data); - char* end = data + trie.Length; - char* pos = end; - - TVector<char> buf(64); - while (enumerator.Move()) { - size_t nodeLength = enumerator.RecreateNode(nullptr, end - pos); - if (nodeLength > buf.size()) - buf.resize(nodeLength); - - size_t realLength = enumerator.RecreateNode(buf.data(), end - pos); - Y_ASSERT(realLength == nodeLength); - - pos -= nodeLength; - memcpy(pos, buf.data(), nodeLength); - } - - switch (mode) { - case MM_NOALLOC: - os.Write(pos, end - pos); - break; - case MM_INPLACE: - memmove(data, pos, end - pos); - break; - default: - Y_VERIFY(false); - } - - return end - pos; + size_t WriteTrieBackwardsNoAlloc(IOutputStream& os, TReverseNodeEnumerator& enumerator, TOpaqueTrie& trie, EMinimizeMode mode) { + char* data = const_cast<char*>(trie.Data); + char* end = data + trie.Length; + char* pos = end; + + TVector<char> buf(64); + while (enumerator.Move()) { + size_t nodeLength = enumerator.RecreateNode(nullptr, end - pos); + if (nodeLength > buf.size()) + buf.resize(nodeLength); + + size_t realLength = enumerator.RecreateNode(buf.data(), end - pos); + Y_ASSERT(realLength == nodeLength); + + pos -= nodeLength; + memcpy(pos, buf.data(), nodeLength); + } + + switch (mode) { + case MM_NOALLOC: + os.Write(pos, end - pos); + break; + case MM_INPLACE: + memmove(data, pos, end - pos); + break; + default: + Y_VERIFY(false); + } + + return end - pos; } } diff --git a/library/cpp/containers/comptrie/writeable_node.cpp b/library/cpp/containers/comptrie/writeable_node.cpp index d0e986f99a..404003dbbd 100644 --- a/library/cpp/containers/comptrie/writeable_node.cpp +++ b/library/cpp/containers/comptrie/writeable_node.cpp @@ -3,94 +3,94 @@ #include "comptrie_impl.h" namespace NCompactTrie { - TWriteableNode::TWriteableNode() - : LeafPos(nullptr) - , LeafLength(0) - , ForwardOffset(NPOS) - , LeftOffset(NPOS) - , RightOffset(NPOS) - , Label(0) - { - } + TWriteableNode::TWriteableNode() + : LeafPos(nullptr) + , LeafLength(0) + , ForwardOffset(NPOS) + , LeftOffset(NPOS) + , RightOffset(NPOS) + , Label(0) + { + } + + static size_t GetOffsetFromEnd(const TNode& node, size_t absOffset) { + return absOffset ? absOffset - node.GetOffset() - node.GetCoreLength() : NPOS; + } - static size_t GetOffsetFromEnd(const TNode& node, size_t absOffset) { - return absOffset ? absOffset - node.GetOffset() - node.GetCoreLength() : NPOS; - } - - TWriteableNode::TWriteableNode(const TNode& node, const char* data) - : LeafPos(node.IsFinal() ? data + node.GetLeafOffset() : nullptr) - , LeafLength(node.GetLeafLength()) - , ForwardOffset(GetOffsetFromEnd(node, node.GetForwardOffset())) - , LeftOffset(GetOffsetFromEnd(node, node.GetLeftOffset())) - , RightOffset(GetOffsetFromEnd(node, node.GetRightOffset())) - , Label(node.GetLabel()) - { - } + TWriteableNode::TWriteableNode(const TNode& node, const char* data) + : LeafPos(node.IsFinal() ? data + node.GetLeafOffset() : nullptr) + , LeafLength(node.GetLeafLength()) + , ForwardOffset(GetOffsetFromEnd(node, node.GetForwardOffset())) + , LeftOffset(GetOffsetFromEnd(node, node.GetLeftOffset())) + , RightOffset(GetOffsetFromEnd(node, node.GetRightOffset())) + , Label(node.GetLabel()) + { + } - size_t TWriteableNode::Measure() const { - size_t len = 2 + LeafLength; - size_t fwdLen = 0; - size_t lastLen = 0; - size_t lastFwdLen = 0; - // Now, increase all the offsets by the length and recalculate everything, until it converges - do { - lastLen = len; - lastFwdLen = fwdLen; + size_t TWriteableNode::Measure() const { + size_t len = 2 + LeafLength; + size_t fwdLen = 0; + size_t lastLen = 0; + size_t lastFwdLen = 0; + // Now, increase all the offsets by the length and recalculate everything, until it converges + do { + lastLen = len; + lastFwdLen = fwdLen; - len = 2 + LeafLength; - len += MeasureOffset(LeftOffset != NPOS ? LeftOffset + lastLen : 0); - len += MeasureOffset(RightOffset != NPOS ? RightOffset + lastLen : 0); - - // Relative forward offset of 0 means we don't need extra length for an epsilon link. - // But an epsilon link means we need an extra 1 for the flags and the forward offset is measured - // from the start of the epsilon link, not from the start of our node. - if (ForwardOffset != NPOS && ForwardOffset != 0) { - fwdLen = MeasureOffset(ForwardOffset + lastFwdLen) + 1; - len += fwdLen; - } + len = 2 + LeafLength; + len += MeasureOffset(LeftOffset != NPOS ? LeftOffset + lastLen : 0); + len += MeasureOffset(RightOffset != NPOS ? RightOffset + lastLen : 0); - } while (lastLen != len || lastFwdLen != fwdLen); + // Relative forward offset of 0 means we don't need extra length for an epsilon link. + // But an epsilon link means we need an extra 1 for the flags and the forward offset is measured + // from the start of the epsilon link, not from the start of our node. + if (ForwardOffset != NPOS && ForwardOffset != 0) { + fwdLen = MeasureOffset(ForwardOffset + lastFwdLen) + 1; + len += fwdLen; + } + + } while (lastLen != len || lastFwdLen != fwdLen); + + return len; + } - return len; - } + size_t TWriteableNode::Pack(char* buffer) const { + const size_t length = Measure(); - size_t TWriteableNode::Pack(char* buffer) const { - const size_t length = Measure(); + char flags = 0; + if (LeafPos) { + flags |= MT_FINAL; + } + if (ForwardOffset != NPOS) { + flags |= MT_NEXT; + } - char flags = 0; - if (LeafPos) { - flags |= MT_FINAL; - } - if (ForwardOffset != NPOS) { - flags |= MT_NEXT; - } + const size_t leftOffset = LeftOffset != NPOS ? LeftOffset + length : 0; + const size_t rightOffset = RightOffset != NPOS ? RightOffset + length : 0; + const size_t leftOffsetSize = MeasureOffset(leftOffset); + const size_t rightOffsetSize = MeasureOffset(rightOffset); + flags |= (leftOffsetSize << MT_LEFTSHIFT); + flags |= (rightOffsetSize << MT_RIGHTSHIFT); - const size_t leftOffset = LeftOffset != NPOS ? LeftOffset + length : 0; - const size_t rightOffset = RightOffset != NPOS ? RightOffset + length : 0; - const size_t leftOffsetSize = MeasureOffset(leftOffset); - const size_t rightOffsetSize = MeasureOffset(rightOffset); - flags |= (leftOffsetSize << MT_LEFTSHIFT); - flags |= (rightOffsetSize << MT_RIGHTSHIFT); + buffer[0] = flags; + buffer[1] = Label; + size_t usedLen = 2; + usedLen += PackOffset(buffer + usedLen, leftOffset); + usedLen += PackOffset(buffer + usedLen, rightOffset); - buffer[0] = flags; - buffer[1] = Label; - size_t usedLen = 2; - usedLen += PackOffset(buffer + usedLen, leftOffset); - usedLen += PackOffset(buffer + usedLen, rightOffset); + if (LeafPos && LeafLength) { + memcpy(buffer + usedLen, LeafPos, LeafLength); + usedLen += LeafLength; + } - if (LeafPos && LeafLength) { - memcpy(buffer + usedLen, LeafPos, LeafLength); - usedLen += LeafLength; - } - - if (ForwardOffset != NPOS && ForwardOffset != 0) { - const size_t fwdOffset = ForwardOffset + length - usedLen; - size_t fwdOffsetSize = MeasureOffset(fwdOffset); - buffer[usedLen++] = (char)(fwdOffsetSize & MT_SIZEMASK); - usedLen += PackOffset(buffer + usedLen, fwdOffset); - } - Y_ASSERT(usedLen == length); - return usedLen; + if (ForwardOffset != NPOS && ForwardOffset != 0) { + const size_t fwdOffset = ForwardOffset + length - usedLen; + size_t fwdOffsetSize = MeasureOffset(fwdOffset); + buffer[usedLen++] = (char)(fwdOffsetSize & MT_SIZEMASK); + usedLen += PackOffset(buffer + usedLen, fwdOffset); + } + Y_ASSERT(usedLen == length); + return usedLen; } } diff --git a/library/cpp/containers/comptrie/writeable_node.h b/library/cpp/containers/comptrie/writeable_node.h index 585ef0a5e4..5454e579ef 100644 --- a/library/cpp/containers/comptrie/writeable_node.h +++ b/library/cpp/containers/comptrie/writeable_node.h @@ -3,24 +3,24 @@ #include <cstddef> namespace NCompactTrie { - class TNode; + class TNode; - class TWriteableNode { - public: - const char* LeafPos; - size_t LeafLength; + class TWriteableNode { + public: + const char* LeafPos; + size_t LeafLength; - size_t ForwardOffset; - size_t LeftOffset; - size_t RightOffset; - char Label; + size_t ForwardOffset; + size_t LeftOffset; + size_t RightOffset; + char Label; - TWriteableNode(); - TWriteableNode(const TNode& node, const char* data); + TWriteableNode(); + TWriteableNode(const TNode& node, const char* data); - // When you call this, the offsets should be relative to the end of the node. Use NPOS to indicate an absent offset. - size_t Pack(char* buffer) const; - size_t Measure() const; - }; + // When you call this, the offsets should be relative to the end of the node. Use NPOS to indicate an absent offset. + size_t Pack(char* buffer) const; + size_t Measure() const; + }; } diff --git a/library/cpp/containers/comptrie/ya.make b/library/cpp/containers/comptrie/ya.make index 43d6534634..81352da4b2 100644 --- a/library/cpp/containers/comptrie/ya.make +++ b/library/cpp/containers/comptrie/ya.make @@ -1,4 +1,4 @@ -LIBRARY() +LIBRARY() OWNER(velavokr) @@ -12,9 +12,9 @@ SRCS( key_selector.h leaf_skipper.h set.h - comptrie.cpp + comptrie.cpp comptrie_builder.cpp - comptrie_impl.cpp + comptrie_impl.cpp make_fast_layout.cpp minimize.cpp node.cpp diff --git a/library/cpp/containers/intrusive_avl_tree/avltree.cpp b/library/cpp/containers/intrusive_avl_tree/avltree.cpp index 05cbea330c..dd27c7df41 100644 --- a/library/cpp/containers/intrusive_avl_tree/avltree.cpp +++ b/library/cpp/containers/intrusive_avl_tree/avltree.cpp @@ -1 +1 @@ -#include "avltree.h" +#include "avltree.h" diff --git a/library/cpp/containers/intrusive_avl_tree/avltree.h b/library/cpp/containers/intrusive_avl_tree/avltree.h index 596917a0e2..a58c63b07c 100644 --- a/library/cpp/containers/intrusive_avl_tree/avltree.h +++ b/library/cpp/containers/intrusive_avl_tree/avltree.h @@ -1,158 +1,158 @@ #pragma once - -#include <util/generic/noncopyable.h> - -template <class T, class C> -struct TAvlTreeItem; - -template <class T, class C> -class TAvlTree: public TNonCopyable { + +#include <util/generic/noncopyable.h> + +template <class T, class C> +struct TAvlTreeItem; + +template <class T, class C> +class TAvlTree: public TNonCopyable { using TTreeItem = TAvlTreeItem<T, C>; - friend struct TAvlTreeItem<T, C>; - + friend struct TAvlTreeItem<T, C>; + static inline const T* AsT(const TTreeItem* item) noexcept { return (const T*)item; } static inline T* AsT(TTreeItem* item) noexcept { - return (T*)item; - } - + return (T*)item; + } + template <class TTreeItem, class TValue> class TIteratorBase { - public: + public: inline TIteratorBase(TTreeItem* p, const TAvlTree* t) noexcept - : Ptr_(p) - , Tree_(t) - { - } - + : Ptr_(p) + , Tree_(t) + { + } + inline bool IsEnd() const noexcept { return Ptr_ == nullptr; - } - + } + inline bool IsBegin() const noexcept { return Ptr_ == nullptr; - } - + } + inline bool IsFirst() const noexcept { - return Ptr_ && Ptr_ == Tree_->Head_; - } - + return Ptr_ && Ptr_ == Tree_->Head_; + } + inline bool IsLast() const noexcept { - return Ptr_ && Ptr_ == Tree_->Tail_; - } - + return Ptr_ && Ptr_ == Tree_->Tail_; + } + inline TValue& operator*() const noexcept { - return *AsT(Ptr_); - } - + return *AsT(Ptr_); + } + inline TValue* operator->() const noexcept { - return AsT(Ptr_); - } - + return AsT(Ptr_); + } + inline TTreeItem* Inc() noexcept { - return Ptr_ = FindNext(Ptr_); - } - + return Ptr_ = FindNext(Ptr_); + } + inline TTreeItem* Dec() noexcept { - return Ptr_ = FindPrev(Ptr_); - } - + return Ptr_ = FindPrev(Ptr_); + } + inline TIteratorBase& operator++() noexcept { - Inc(); - return *this; - } - + Inc(); + return *this; + } + inline TIteratorBase operator++(int) noexcept { TIteratorBase ret(*this); - Inc(); - return ret; - } - + Inc(); + return ret; + } + inline TIteratorBase& operator--() noexcept { - Dec(); - return *this; - } - + Dec(); + return *this; + } + inline TIteratorBase operator--(int) noexcept { TIteratorBase ret(*this); - Dec(); - return ret; - } - + Dec(); + return ret; + } + inline TIteratorBase Next() const noexcept { - return ConstructNext(*this); - } - + return ConstructNext(*this); + } + inline TIteratorBase Prev() const noexcept { - return ConstructPrev(*this); - } - + return ConstructPrev(*this); + } + inline bool operator==(const TIteratorBase& r) const noexcept { - return Ptr_ == r.Ptr_; - } - + return Ptr_ == r.Ptr_; + } + inline bool operator!=(const TIteratorBase& r) const noexcept { - return Ptr_ != r.Ptr_; - } - - private: + return Ptr_ != r.Ptr_; + } + + private: inline static TIteratorBase ConstructNext(const TIteratorBase& i) noexcept { - return TIterator(FindNext(i.Ptr_), i.Tree_); - } - + return TIterator(FindNext(i.Ptr_), i.Tree_); + } + inline static TIteratorBase ConstructPrev(const TIteratorBase& i) noexcept { - return TIterator(FindPrev(i.Ptr_), i.Tree_); - } - + return TIterator(FindPrev(i.Ptr_), i.Tree_); + } + inline static TIteratorBase FindPrev(TTreeItem* el) noexcept { if (el->Left_ != nullptr) { - el = el->Left_; - + el = el->Left_; + while (el->Right_ != nullptr) { - el = el->Right_; - } - } else { - while (true) { - TTreeItem* last = el; - el = el->Parent_; - + el = el->Right_; + } + } else { + while (true) { + TTreeItem* last = el; + el = el->Parent_; + if (el == nullptr || el->Right_ == last) { - break; - } - } - } - - return el; - } - - static TTreeItem* FindNext(TTreeItem* el) { + break; + } + } + } + + return el; + } + + static TTreeItem* FindNext(TTreeItem* el) { if (el->Right_ != nullptr) { - el = el->Right_; - - while (el->Left_) { - el = el->Left_; - } - } else { - while (true) { - TTreeItem* last = el; - el = el->Parent_; - + el = el->Right_; + + while (el->Left_) { + el = el->Left_; + } + } else { + while (true) { + TTreeItem* last = el; + el = el->Parent_; + if (el == nullptr || el->Left_ == last) { - break; - } - } - } - - return el; - } - - private: - TTreeItem* Ptr_; - const TAvlTree* Tree_; - }; - + break; + } + } + } + + return el; + } + + private: + TTreeItem* Ptr_; + const TAvlTree* Tree_; + }; + using TConstIterator = TIteratorBase<const TTreeItem, const T>; using TIterator = TIteratorBase<TTreeItem, T>; @@ -161,222 +161,222 @@ class TAvlTree: public TNonCopyable { } static inline TIterator ConstructFirst(const TAvlTree* t) noexcept { - return TIterator(t->Head_, t); - } - + return TIterator(t->Head_, t); + } + static inline TConstIterator ConstructLastConst(const TAvlTree* t) noexcept { return TConstIterator(t->Tail_, t); } static inline TIterator ConstructLast(const TAvlTree* t) noexcept { - return TIterator(t->Tail_, t); - } - - static inline bool Compare(const TTreeItem& l, const TTreeItem& r) { - return C::Compare(*AsT(&l), *AsT(&r)); - } - -public: + return TIterator(t->Tail_, t); + } + + static inline bool Compare(const TTreeItem& l, const TTreeItem& r) { + return C::Compare(*AsT(&l), *AsT(&r)); + } + +public: using const_iterator = TConstIterator; using iterator = TIterator; - + inline TAvlTree() noexcept - : Root_(nullptr) - , Head_(nullptr) - , Tail_(nullptr) - { - } - + : Root_(nullptr) + , Head_(nullptr) + , Tail_(nullptr) + { + } + inline ~TAvlTree() noexcept { Clear(); } inline void Clear() noexcept { - for (iterator it = Begin(); it != End();) { - (it++)->TTreeItem::Unlink(); - } - } - + for (iterator it = Begin(); it != End();) { + (it++)->TTreeItem::Unlink(); + } + } + inline T* Insert(TTreeItem* el, TTreeItem** lastFound = nullptr) noexcept { - el->Unlink(); - el->Tree_ = this; - - TTreeItem* curEl = Root_; + el->Unlink(); + el->Tree_ = this; + + TTreeItem* curEl = Root_; TTreeItem* parentEl = nullptr; TTreeItem* lastLess = nullptr; - - while (true) { + + while (true) { if (curEl == nullptr) { - AttachRebal(el, parentEl, lastLess); - + AttachRebal(el, parentEl, lastLess); + if (lastFound != nullptr) { - *lastFound = el; - } - - return AsT(el); - } - - if (Compare(*el, *curEl)) { - parentEl = lastLess = curEl; - curEl = curEl->Left_; - } else if (Compare(*curEl, *el)) { - parentEl = curEl; - curEl = curEl->Right_; - } else { + *lastFound = el; + } + + return AsT(el); + } + + if (Compare(*el, *curEl)) { + parentEl = lastLess = curEl; + curEl = curEl->Left_; + } else if (Compare(*curEl, *el)) { + parentEl = curEl; + curEl = curEl->Right_; + } else { if (lastFound != nullptr) { - *lastFound = curEl; - } - + *lastFound = curEl; + } + return nullptr; - } - } - } - + } + } + } + inline T* Find(const TTreeItem* el) const noexcept { - TTreeItem* curEl = Root_; - - while (curEl) { - if (Compare(*el, *curEl)) { - curEl = curEl->Left_; - } else if (Compare(*curEl, *el)) { - curEl = curEl->Right_; - } else { - return AsT(curEl); - } - } - + TTreeItem* curEl = Root_; + + while (curEl) { + if (Compare(*el, *curEl)) { + curEl = curEl->Left_; + } else if (Compare(*curEl, *el)) { + curEl = curEl->Right_; + } else { + return AsT(curEl); + } + } + return nullptr; - } + } inline T* LowerBound(const TTreeItem* el) const noexcept { - TTreeItem* curEl = Root_; + TTreeItem* curEl = Root_; TTreeItem* lowerBound = nullptr; - - while (curEl) { - if (Compare(*el, *curEl)) { - lowerBound = curEl; - curEl = curEl->Left_; - } else if (Compare(*curEl, *el)) { - curEl = curEl->Right_; - } else { - return AsT(curEl); + + while (curEl) { + if (Compare(*el, *curEl)) { + lowerBound = curEl; + curEl = curEl->Left_; + } else if (Compare(*curEl, *el)) { + curEl = curEl->Right_; + } else { + return AsT(curEl); } } - return AsT(lowerBound); - } - + return AsT(lowerBound); + } + inline T* Erase(TTreeItem* el) noexcept { - if (el->Tree_ == this) { - return this->EraseImpl(el); - } - + if (el->Tree_ == this) { + return this->EraseImpl(el); + } + return nullptr; - } - + } + inline T* EraseImpl(TTreeItem* el) noexcept { el->Tree_ = nullptr; - - TTreeItem* replacement; - TTreeItem* fixfrom; - long lheight, rheight; - - if (el->Right_) { - replacement = el->Right_; - - while (replacement->Left_) { - replacement = replacement->Left_; - } - - if (replacement->Parent_ == el) { - fixfrom = replacement; - } else { - fixfrom = replacement->Parent_; - } - - if (el == Head_) { - Head_ = replacement; - } - - RemoveEl(replacement, replacement->Right_); - ReplaceEl(el, replacement); - } else if (el->Left_) { - replacement = el->Left_; - - while (replacement->Right_) { - replacement = replacement->Right_; - } - - if (replacement->Parent_ == el) { - fixfrom = replacement; - } else { - fixfrom = replacement->Parent_; - } - - if (el == Tail_) { - Tail_ = replacement; - } - - RemoveEl(replacement, replacement->Left_); - ReplaceEl(el, replacement); - } else { - fixfrom = el->Parent_; - - if (el == Head_) { - Head_ = el->Parent_; - } - - if (el == Tail_) { - Tail_ = el->Parent_; - } - + + TTreeItem* replacement; + TTreeItem* fixfrom; + long lheight, rheight; + + if (el->Right_) { + replacement = el->Right_; + + while (replacement->Left_) { + replacement = replacement->Left_; + } + + if (replacement->Parent_ == el) { + fixfrom = replacement; + } else { + fixfrom = replacement->Parent_; + } + + if (el == Head_) { + Head_ = replacement; + } + + RemoveEl(replacement, replacement->Right_); + ReplaceEl(el, replacement); + } else if (el->Left_) { + replacement = el->Left_; + + while (replacement->Right_) { + replacement = replacement->Right_; + } + + if (replacement->Parent_ == el) { + fixfrom = replacement; + } else { + fixfrom = replacement->Parent_; + } + + if (el == Tail_) { + Tail_ = replacement; + } + + RemoveEl(replacement, replacement->Left_); + ReplaceEl(el, replacement); + } else { + fixfrom = el->Parent_; + + if (el == Head_) { + Head_ = el->Parent_; + } + + if (el == Tail_) { + Tail_ = el->Parent_; + } + RemoveEl(el, nullptr); - } - + } + if (fixfrom == nullptr) { - return AsT(el); - } - - RecalcHeights(fixfrom); - - TTreeItem* ub = FindFirstUnbalEl(fixfrom); - - while (ub) { - lheight = ub->Left_ ? ub->Left_->Height_ : 0; - rheight = ub->Right_ ? ub->Right_->Height_ : 0; - - if (rheight > lheight) { - ub = ub->Right_; - lheight = ub->Left_ ? ub->Left_->Height_ : 0; - rheight = ub->Right_ ? ub->Right_->Height_ : 0; - - if (rheight > lheight) { - ub = ub->Right_; - } else if (rheight < lheight) { - ub = ub->Left_; - } else { - ub = ub->Right_; - } - } else { - ub = ub->Left_; - lheight = ub->Left_ ? ub->Left_->Height_ : 0; - rheight = ub->Right_ ? ub->Right_->Height_ : 0; - if (rheight > lheight) { - ub = ub->Right_; - } else if (rheight < lheight) { - ub = ub->Left_; - } else { - ub = ub->Left_; - } - } - - fixfrom = Rebalance(ub); - ub = FindFirstUnbalEl(fixfrom); - } - - return AsT(el); - } - + return AsT(el); + } + + RecalcHeights(fixfrom); + + TTreeItem* ub = FindFirstUnbalEl(fixfrom); + + while (ub) { + lheight = ub->Left_ ? ub->Left_->Height_ : 0; + rheight = ub->Right_ ? ub->Right_->Height_ : 0; + + if (rheight > lheight) { + ub = ub->Right_; + lheight = ub->Left_ ? ub->Left_->Height_ : 0; + rheight = ub->Right_ ? ub->Right_->Height_ : 0; + + if (rheight > lheight) { + ub = ub->Right_; + } else if (rheight < lheight) { + ub = ub->Left_; + } else { + ub = ub->Right_; + } + } else { + ub = ub->Left_; + lheight = ub->Left_ ? ub->Left_->Height_ : 0; + rheight = ub->Right_ ? ub->Right_->Height_ : 0; + if (rheight > lheight) { + ub = ub->Right_; + } else if (rheight < lheight) { + ub = ub->Left_; + } else { + ub = ub->Left_; + } + } + + fixfrom = Rebalance(ub); + ub = FindFirstUnbalEl(fixfrom); + } + + return AsT(el); + } + inline const_iterator First() const noexcept { return ConstructFirstConst(this); } @@ -410,21 +410,21 @@ public: } inline iterator First() noexcept { - return ConstructFirst(this); - } - + return ConstructFirst(this); + } + inline iterator Last() noexcept { - return ConstructLast(this); - } - + return ConstructLast(this); + } + inline iterator Begin() noexcept { - return First(); - } - + return First(); + } + inline iterator End() noexcept { return iterator(nullptr, this); - } - + } + inline iterator begin() noexcept { return Begin(); } @@ -434,321 +434,321 @@ public: } inline bool Empty() const noexcept { - return const_cast<TAvlTree*>(this)->Begin() == const_cast<TAvlTree*>(this)->End(); - } - + return const_cast<TAvlTree*>(this)->Begin() == const_cast<TAvlTree*>(this)->End(); + } + inline explicit operator bool() const noexcept { - return !this->Empty(); - } - - template <class Functor> - inline void ForEach(Functor& f) { - iterator it = Begin(); - - while (!it.IsEnd()) { - iterator next = it; - ++next; - f(*it); - it = next; - } - } - -private: + return !this->Empty(); + } + + template <class Functor> + inline void ForEach(Functor& f) { + iterator it = Begin(); + + while (!it.IsEnd()) { + iterator next = it; + ++next; + f(*it); + it = next; + } + } + +private: inline TTreeItem* Rebalance(TTreeItem* n) noexcept { - long lheight, rheight; - - TTreeItem* a; - TTreeItem* b; - TTreeItem* c; - TTreeItem* t1; - TTreeItem* t2; - TTreeItem* t3; - TTreeItem* t4; - - TTreeItem* p = n->Parent_; - TTreeItem* gp = p->Parent_; - TTreeItem* ggp = gp->Parent_; - - if (gp->Right_ == p) { - if (p->Right_ == n) { - a = gp; - b = p; - c = n; - t1 = gp->Left_; - t2 = p->Left_; - t3 = n->Left_; - t4 = n->Right_; - } else { - a = gp; - b = n; - c = p; - t1 = gp->Left_; - t2 = n->Left_; - t3 = n->Right_; - t4 = p->Right_; - } - } else { - if (p->Right_ == n) { - a = p; - b = n; - c = gp; - t1 = p->Left_; - t2 = n->Left_; - t3 = n->Right_; - t4 = gp->Right_; - } else { - a = n; - b = p; - c = gp; - t1 = n->Left_; - t2 = n->Right_; - t3 = p->Right_; - t4 = gp->Right_; - } - } - + long lheight, rheight; + + TTreeItem* a; + TTreeItem* b; + TTreeItem* c; + TTreeItem* t1; + TTreeItem* t2; + TTreeItem* t3; + TTreeItem* t4; + + TTreeItem* p = n->Parent_; + TTreeItem* gp = p->Parent_; + TTreeItem* ggp = gp->Parent_; + + if (gp->Right_ == p) { + if (p->Right_ == n) { + a = gp; + b = p; + c = n; + t1 = gp->Left_; + t2 = p->Left_; + t3 = n->Left_; + t4 = n->Right_; + } else { + a = gp; + b = n; + c = p; + t1 = gp->Left_; + t2 = n->Left_; + t3 = n->Right_; + t4 = p->Right_; + } + } else { + if (p->Right_ == n) { + a = p; + b = n; + c = gp; + t1 = p->Left_; + t2 = n->Left_; + t3 = n->Right_; + t4 = gp->Right_; + } else { + a = n; + b = p; + c = gp; + t1 = n->Left_; + t2 = n->Right_; + t3 = p->Right_; + t4 = gp->Right_; + } + } + if (ggp == nullptr) { - Root_ = b; - } else if (ggp->Left_ == gp) { - ggp->Left_ = b; - } else { - ggp->Right_ = b; - } - - b->Parent_ = ggp; - b->Left_ = a; - a->Parent_ = b; - b->Right_ = c; - c->Parent_ = b; - a->Left_ = t1; - + Root_ = b; + } else if (ggp->Left_ == gp) { + ggp->Left_ = b; + } else { + ggp->Right_ = b; + } + + b->Parent_ = ggp; + b->Left_ = a; + a->Parent_ = b; + b->Right_ = c; + c->Parent_ = b; + a->Left_ = t1; + if (t1 != nullptr) { - t1->Parent_ = a; - } - - a->Right_ = t2; - + t1->Parent_ = a; + } + + a->Right_ = t2; + if (t2 != nullptr) { - t2->Parent_ = a; - } - - c->Left_ = t3; - + t2->Parent_ = a; + } + + c->Left_ = t3; + if (t3 != nullptr) { - t3->Parent_ = c; - } - - c->Right_ = t4; - + t3->Parent_ = c; + } + + c->Right_ = t4; + if (t4 != nullptr) { - t4->Parent_ = c; - } - - lheight = a->Left_ ? a->Left_->Height_ : 0; - rheight = a->Right_ ? a->Right_->Height_ : 0; - a->Height_ = (lheight > rheight ? lheight : rheight) + 1; - - lheight = c->Left_ ? c->Left_->Height_ : 0; - rheight = c->Right_ ? c->Right_->Height_ : 0; - c->Height_ = (lheight > rheight ? lheight : rheight) + 1; - - lheight = a->Height_; - rheight = c->Height_; - b->Height_ = (lheight > rheight ? lheight : rheight) + 1; - - RecalcHeights(ggp); - - return ggp; - } - + t4->Parent_ = c; + } + + lheight = a->Left_ ? a->Left_->Height_ : 0; + rheight = a->Right_ ? a->Right_->Height_ : 0; + a->Height_ = (lheight > rheight ? lheight : rheight) + 1; + + lheight = c->Left_ ? c->Left_->Height_ : 0; + rheight = c->Right_ ? c->Right_->Height_ : 0; + c->Height_ = (lheight > rheight ? lheight : rheight) + 1; + + lheight = a->Height_; + rheight = c->Height_; + b->Height_ = (lheight > rheight ? lheight : rheight) + 1; + + RecalcHeights(ggp); + + return ggp; + } + inline void RecalcHeights(TTreeItem* el) noexcept { - long lheight, rheight, new_height; - - while (el) { - lheight = el->Left_ ? el->Left_->Height_ : 0; - rheight = el->Right_ ? el->Right_->Height_ : 0; - - new_height = (lheight > rheight ? lheight : rheight) + 1; - - if (new_height == el->Height_) { - return; - } else { - el->Height_ = new_height; - } - - el = el->Parent_; - } - } - + long lheight, rheight, new_height; + + while (el) { + lheight = el->Left_ ? el->Left_->Height_ : 0; + rheight = el->Right_ ? el->Right_->Height_ : 0; + + new_height = (lheight > rheight ? lheight : rheight) + 1; + + if (new_height == el->Height_) { + return; + } else { + el->Height_ = new_height; + } + + el = el->Parent_; + } + } + inline TTreeItem* FindFirstUnbalGP(TTreeItem* el) noexcept { - long lheight, rheight, balanceProp; - TTreeItem* gp; - + long lheight, rheight, balanceProp; + TTreeItem* gp; + if (el == nullptr || el->Parent_ == nullptr || el->Parent_->Parent_ == nullptr) { return nullptr; - } - - gp = el->Parent_->Parent_; - + } + + gp = el->Parent_->Parent_; + while (gp != nullptr) { - lheight = gp->Left_ ? gp->Left_->Height_ : 0; - rheight = gp->Right_ ? gp->Right_->Height_ : 0; - balanceProp = lheight - rheight; - - if (balanceProp < -1 || balanceProp > 1) { - return el; - } - - el = el->Parent_; - gp = gp->Parent_; - } - + lheight = gp->Left_ ? gp->Left_->Height_ : 0; + rheight = gp->Right_ ? gp->Right_->Height_ : 0; + balanceProp = lheight - rheight; + + if (balanceProp < -1 || balanceProp > 1) { + return el; + } + + el = el->Parent_; + gp = gp->Parent_; + } + return nullptr; - } - + } + inline TTreeItem* FindFirstUnbalEl(TTreeItem* el) noexcept { if (el == nullptr) { return nullptr; - } - - while (el) { - const long lheight = el->Left_ ? el->Left_->Height_ : 0; - const long rheight = el->Right_ ? el->Right_->Height_ : 0; - const long balanceProp = lheight - rheight; - - if (balanceProp < -1 || balanceProp > 1) { - return el; - } - - el = el->Parent_; - } - + } + + while (el) { + const long lheight = el->Left_ ? el->Left_->Height_ : 0; + const long rheight = el->Right_ ? el->Right_->Height_ : 0; + const long balanceProp = lheight - rheight; + + if (balanceProp < -1 || balanceProp > 1) { + return el; + } + + el = el->Parent_; + } + return nullptr; - } - + } + inline void ReplaceEl(TTreeItem* el, TTreeItem* replacement) noexcept { - TTreeItem* parent = el->Parent_; - TTreeItem* left = el->Left_; - TTreeItem* right = el->Right_; - - replacement->Left_ = left; - - if (left) { - left->Parent_ = replacement; - } - - replacement->Right_ = right; - - if (right) { - right->Parent_ = replacement; - } - - replacement->Parent_ = parent; - - if (parent) { - if (parent->Left_ == el) { - parent->Left_ = replacement; - } else { - parent->Right_ = replacement; - } - } else { - Root_ = replacement; - } - - replacement->Height_ = el->Height_; - } - + TTreeItem* parent = el->Parent_; + TTreeItem* left = el->Left_; + TTreeItem* right = el->Right_; + + replacement->Left_ = left; + + if (left) { + left->Parent_ = replacement; + } + + replacement->Right_ = right; + + if (right) { + right->Parent_ = replacement; + } + + replacement->Parent_ = parent; + + if (parent) { + if (parent->Left_ == el) { + parent->Left_ = replacement; + } else { + parent->Right_ = replacement; + } + } else { + Root_ = replacement; + } + + replacement->Height_ = el->Height_; + } + inline void RemoveEl(TTreeItem* el, TTreeItem* filler) noexcept { - TTreeItem* parent = el->Parent_; - - if (parent) { - if (parent->Left_ == el) { - parent->Left_ = filler; - } else { - parent->Right_ = filler; - } - } else { - Root_ = filler; - } - - if (filler) { - filler->Parent_ = parent; - } - - return; - } - - inline void AttachRebal(TTreeItem* el, TTreeItem* parentEl, TTreeItem* lastLess) { - el->Parent_ = parentEl; + TTreeItem* parent = el->Parent_; + + if (parent) { + if (parent->Left_ == el) { + parent->Left_ = filler; + } else { + parent->Right_ = filler; + } + } else { + Root_ = filler; + } + + if (filler) { + filler->Parent_ = parent; + } + + return; + } + + inline void AttachRebal(TTreeItem* el, TTreeItem* parentEl, TTreeItem* lastLess) { + el->Parent_ = parentEl; el->Left_ = nullptr; el->Right_ = nullptr; - el->Height_ = 1; - + el->Height_ = 1; + if (parentEl != nullptr) { - if (lastLess == parentEl) { - parentEl->Left_ = el; - } else { - parentEl->Right_ = el; - } - - if (Head_->Left_ == el) { - Head_ = el; - } - - if (Tail_->Right_ == el) { - Tail_ = el; - } - } else { - Root_ = el; - Head_ = Tail_ = el; - } - - RecalcHeights(parentEl); - - TTreeItem* ub = FindFirstUnbalGP(el); - + if (lastLess == parentEl) { + parentEl->Left_ = el; + } else { + parentEl->Right_ = el; + } + + if (Head_->Left_ == el) { + Head_ = el; + } + + if (Tail_->Right_ == el) { + Tail_ = el; + } + } else { + Root_ = el; + Head_ = Tail_ = el; + } + + RecalcHeights(parentEl); + + TTreeItem* ub = FindFirstUnbalGP(el); + if (ub != nullptr) { - Rebalance(ub); - } - } - -private: - TTreeItem* Root_; - TTreeItem* Head_; - TTreeItem* Tail_; -}; - -template <class T, class C> -struct TAvlTreeItem: public TNonCopyable { -public: + Rebalance(ub); + } + } + +private: + TTreeItem* Root_; + TTreeItem* Head_; + TTreeItem* Tail_; +}; + +template <class T, class C> +struct TAvlTreeItem: public TNonCopyable { +public: using TTree = TAvlTree<T, C>; - friend class TAvlTree<T, C>; + friend class TAvlTree<T, C>; friend typename TAvlTree<T, C>::TConstIterator; friend typename TAvlTree<T, C>::TIterator; - + inline TAvlTreeItem() noexcept - : Left_(nullptr) - , Right_(nullptr) - , Parent_(nullptr) - , Height_(0) - , Tree_(nullptr) - { - } - + : Left_(nullptr) + , Right_(nullptr) + , Parent_(nullptr) + , Height_(0) + , Tree_(nullptr) + { + } + inline ~TAvlTreeItem() noexcept { - Unlink(); - } - + Unlink(); + } + inline void Unlink() noexcept { - if (Tree_) { - Tree_->EraseImpl(this); - } - } - -private: - TAvlTreeItem* Left_; - TAvlTreeItem* Right_; - TAvlTreeItem* Parent_; - long Height_; - TTree* Tree_; -}; + if (Tree_) { + Tree_->EraseImpl(this); + } + } + +private: + TAvlTreeItem* Left_; + TAvlTreeItem* Right_; + TAvlTreeItem* Parent_; + long Height_; + TTree* Tree_; +}; diff --git a/library/cpp/containers/intrusive_avl_tree/ut/avltree_ut.cpp b/library/cpp/containers/intrusive_avl_tree/ut/avltree_ut.cpp index 256738c50a..cab2365cce 100644 --- a/library/cpp/containers/intrusive_avl_tree/ut/avltree_ut.cpp +++ b/library/cpp/containers/intrusive_avl_tree/ut/avltree_ut.cpp @@ -3,29 +3,29 @@ #include <library/cpp/containers/intrusive_avl_tree/avltree.h> class TAvlTreeTest: public TTestBase { - UNIT_TEST_SUITE(TAvlTreeTest); - UNIT_TEST(TestLowerBound); + UNIT_TEST_SUITE(TAvlTreeTest); + UNIT_TEST(TestLowerBound); UNIT_TEST(TestIterator); - UNIT_TEST_SUITE_END(); + UNIT_TEST_SUITE_END(); -private: - void TestLowerBound(); +private: + void TestLowerBound(); void TestIterator(); - class TIt; - struct TItCompare { + class TIt; + struct TItCompare { static inline bool Compare(const TIt& l, const TIt& r) noexcept; - }; + }; - class TIt: public TAvlTreeItem<TIt, TItCompare> { - public: - TIt(int val = 0) - : Val(val) - { - } + class TIt: public TAvlTreeItem<TIt, TItCompare> { + public: + TIt(int val = 0) + : Val(val) + { + } - int Val; - }; + int Val; + }; using TIts = TAvlTree<TIt, TItCompare>; }; diff --git a/library/cpp/containers/intrusive_avl_tree/ut/ya.make b/library/cpp/containers/intrusive_avl_tree/ut/ya.make index ef8fb95b6e..87920306d7 100644 --- a/library/cpp/containers/intrusive_avl_tree/ut/ya.make +++ b/library/cpp/containers/intrusive_avl_tree/ut/ya.make @@ -1,12 +1,12 @@ UNITTEST_FOR(library/cpp/containers/intrusive_avl_tree) - + OWNER( pg g:util ) - -SRCS( - avltree_ut.cpp -) - -END() + +SRCS( + avltree_ut.cpp +) + +END() diff --git a/library/cpp/containers/intrusive_avl_tree/ya.make b/library/cpp/containers/intrusive_avl_tree/ya.make index a8e3211340..6b061f2760 100644 --- a/library/cpp/containers/intrusive_avl_tree/ya.make +++ b/library/cpp/containers/intrusive_avl_tree/ya.make @@ -1,12 +1,12 @@ -LIBRARY() - +LIBRARY() + OWNER( pg g:util ) - -SRCS( - avltree.cpp -) - -END() + +SRCS( + avltree.cpp +) + +END() diff --git a/library/cpp/containers/intrusive_rb_tree/fuzz/rb_tree_fuzzing.cpp b/library/cpp/containers/intrusive_rb_tree/fuzz/rb_tree_fuzzing.cpp index 3bf84258c1..92370760b5 100644 --- a/library/cpp/containers/intrusive_rb_tree/fuzz/rb_tree_fuzzing.cpp +++ b/library/cpp/containers/intrusive_rb_tree/fuzz/rb_tree_fuzzing.cpp @@ -11,31 +11,31 @@ struct TCmp { } template <class T> - static inline bool Compare(const T& l, ui8 r) { + static inline bool Compare(const T& l, ui8 r) { return l.N < r; } template <class T> - static inline bool Compare(ui8 l, const T& r) { + static inline bool Compare(ui8 l, const T& r) { return l < r.N; } }; class TNode: public TRbTreeItem<TNode, TCmp> { public: - inline TNode(ui8 n) noexcept + inline TNode(ui8 n) noexcept : N(n) { } - ui8 N; + ui8 N; }; using TTree = TRbTree<TNode, TCmp>; -extern "C" int LLVMFuzzerTestOneInput(const ui8* data, size_t size) { +extern "C" int LLVMFuzzerTestOneInput(const ui8* data, size_t size) { TDeque<TNode> records; - const ui8 half = 128u; + const ui8 half = 128u; TTree tree; for (size_t i = 0; i < size; ++i) { if (data[i] / half == 0) { diff --git a/library/cpp/containers/intrusive_rb_tree/rb_tree.cpp b/library/cpp/containers/intrusive_rb_tree/rb_tree.cpp index 85b35e2634..535b536c41 100644 --- a/library/cpp/containers/intrusive_rb_tree/rb_tree.cpp +++ b/library/cpp/containers/intrusive_rb_tree/rb_tree.cpp @@ -1 +1 @@ -#include "rb_tree.h" +#include "rb_tree.h" diff --git a/library/cpp/containers/intrusive_rb_tree/rb_tree.h b/library/cpp/containers/intrusive_rb_tree/rb_tree.h index ed94b1794d..0259452a14 100644 --- a/library/cpp/containers/intrusive_rb_tree/rb_tree.h +++ b/library/cpp/containers/intrusive_rb_tree/rb_tree.h @@ -1,48 +1,48 @@ #pragma once - -#include <util/generic/utility.h> -#include <util/generic/yexception.h> - + +#include <util/generic/utility.h> +#include <util/generic/yexception.h> + using TRbTreeColorType = bool; - -#define RBTreeRed false -#define RBTreeBlack true - -struct TRbTreeNodeBase { + +#define RBTreeRed false +#define RBTreeBlack true + +struct TRbTreeNodeBase { using TColorType = TRbTreeColorType; using TBasePtr = TRbTreeNodeBase*; - - TColorType Color_; - TBasePtr Parent_; - TBasePtr Left_; - TBasePtr Right_; + + TColorType Color_; + TBasePtr Parent_; + TBasePtr Left_; + TBasePtr Right_; size_t Children_; - + inline TRbTreeNodeBase() noexcept { - ReInitNode(); - } - + ReInitNode(); + } + inline void ReInitNode() noexcept { - Color_ = RBTreeBlack; + Color_ = RBTreeBlack; Parent_ = nullptr; Left_ = nullptr; Right_ = nullptr; Children_ = 1; - } - - static TBasePtr MinimumNode(TBasePtr x) { + } + + static TBasePtr MinimumNode(TBasePtr x) { while (x->Left_ != nullptr) - x = x->Left_; - - return x; - } - - static TBasePtr MaximumNode(TBasePtr x) { + x = x->Left_; + + return x; + } + + static TBasePtr MaximumNode(TBasePtr x) { while (x->Right_ != nullptr) - x = x->Right_; - - return x; - } + x = x->Right_; + + return x; + } static TBasePtr ByIndex(TBasePtr x, size_t index) { if (x->Left_ != nullptr) { @@ -56,300 +56,300 @@ struct TRbTreeNodeBase { ythrow yexception() << "index not found"; return ByIndex(x->Right_, index - 1); } -}; - -struct TRbTreeBaseIterator; - -template <class TDummy> -class TRbGlobal { -public: +}; + +struct TRbTreeBaseIterator; + +template <class TDummy> +class TRbGlobal { +public: using TBasePtr = TRbTreeNodeBase*; - - static void Rebalance(TBasePtr x, TBasePtr& root); - static TBasePtr RebalanceForErase(TBasePtr z, TBasePtr& root, TBasePtr& leftmost, TBasePtr& rightmost); + + static void Rebalance(TBasePtr x, TBasePtr& root); + static TBasePtr RebalanceForErase(TBasePtr z, TBasePtr& root, TBasePtr& leftmost, TBasePtr& rightmost); static void DecrementChildrenUntilRoot(TBasePtr x, TBasePtr root); static void RecalcChildren(TBasePtr x); - - static TBasePtr IncrementNode(TBasePtr); - static TBasePtr DecrementNode(TBasePtr); - static void RotateLeft(TBasePtr x, TBasePtr& root); - static void RotateRight(TBasePtr x, TBasePtr& root); -}; - + + static TBasePtr IncrementNode(TBasePtr); + static TBasePtr DecrementNode(TBasePtr); + static void RotateLeft(TBasePtr x, TBasePtr& root); + static void RotateRight(TBasePtr x, TBasePtr& root); +}; + using TRbGlobalInst = TRbGlobal<bool>; - -struct TRbTreeBaseIterator { + +struct TRbTreeBaseIterator { using TBasePtr = TRbTreeNodeBase*; - TBasePtr Node_; - + TBasePtr Node_; + inline TRbTreeBaseIterator(TBasePtr x = nullptr) noexcept - : Node_(x) - { - } -}; - -template <class TValue, class TTraits> -struct TRbTreeIterator: public TRbTreeBaseIterator { + : Node_(x) + { + } +}; + +template <class TValue, class TTraits> +struct TRbTreeIterator: public TRbTreeBaseIterator { using TReference = typename TTraits::TReference; using TPointer = typename TTraits::TPointer; using TSelf = TRbTreeIterator<TValue, TTraits>; using TBasePtr = TRbTreeNodeBase*; - + inline TRbTreeIterator() noexcept = default; - - template <class T1> + + template <class T1> inline TRbTreeIterator(const T1& x) noexcept - : TRbTreeBaseIterator(x) - { - } - + : TRbTreeBaseIterator(x) + { + } + inline TReference operator*() const noexcept { - return *static_cast<TValue*>(Node_); - } - + return *static_cast<TValue*>(Node_); + } + inline TPointer operator->() const noexcept { - return static_cast<TValue*>(Node_); - } - + return static_cast<TValue*>(Node_); + } + inline TSelf& operator++() noexcept { - Node_ = TRbGlobalInst::IncrementNode(Node_); - return *this; - } - + Node_ = TRbGlobalInst::IncrementNode(Node_); + return *this; + } + inline TSelf operator++(int) noexcept { - TSelf tmp = *this; - ++(*this); - return tmp; - } - + TSelf tmp = *this; + ++(*this); + return tmp; + } + inline TSelf& operator--() noexcept { - Node_ = TRbGlobalInst::DecrementNode(Node_); - return *this; - } - + Node_ = TRbGlobalInst::DecrementNode(Node_); + return *this; + } + inline TSelf operator--(int) noexcept { - TSelf tmp = *this; - --(*this); - return tmp; - } - - template <class T1> + TSelf tmp = *this; + --(*this); + return tmp; + } + + template <class T1> inline bool operator==(const T1& rhs) const noexcept { - return Node_ == rhs.Node_; - } - - template <class T1> + return Node_ == rhs.Node_; + } + + template <class T1> inline bool operator!=(const T1& rhs) const noexcept { - return Node_ != rhs.Node_; - } -}; - -template <class TValue, class TCmp> -class TRbTree { - struct TCmpAdaptor: public TCmp { + return Node_ != rhs.Node_; + } +}; + +template <class TValue, class TCmp> +class TRbTree { + struct TCmpAdaptor: public TCmp { inline TCmpAdaptor() noexcept = default; - + inline TCmpAdaptor(const TCmp& cmp) noexcept - : TCmp(cmp) - { - } - - template <class T1, class T2> - inline bool operator()(const T1& l, const T2& r) const { - return TCmp::Compare(l, r); - } - }; - - struct TNonConstTraits { + : TCmp(cmp) + { + } + + template <class T1, class T2> + inline bool operator()(const T1& l, const T2& r) const { + return TCmp::Compare(l, r); + } + }; + + struct TNonConstTraits { using TReference = TValue&; using TPointer = TValue*; - }; - - struct TConstTraits { + }; + + struct TConstTraits { using TReference = const TValue&; using TPointer = const TValue*; - }; - + }; + using TNodeBase = TRbTreeNodeBase; using TBasePtr = TRbTreeNodeBase*; using TColorType = TRbTreeColorType; - -public: - class TRealNode: public TNodeBase { - public: - inline TRealNode() + +public: + class TRealNode: public TNodeBase { + public: + inline TRealNode() : Tree_(nullptr) - { - } - + { + } + inline ~TRealNode() { - UnLink(); - } - + UnLink(); + } + inline void UnLink() noexcept { - if (Tree_) { - Tree_->EraseImpl(this); - ReInitNode(); + if (Tree_) { + Tree_->EraseImpl(this); + ReInitNode(); Tree_ = nullptr; - } - } - + } + } + inline void SetRbTreeParent(TRbTree* parent) noexcept { - Tree_ = parent; - } - + Tree_ = parent; + } + inline TRbTree* ParentTree() const noexcept { - return Tree_; - } - - private: - TRbTree* Tree_; - }; - + return Tree_; + } + + private: + TRbTree* Tree_; + }; + using TIterator = TRbTreeIterator<TValue, TNonConstTraits>; using TConstIterator = TRbTreeIterator<TValue, TConstTraits>; - + inline TRbTree() noexcept { - Init(); - } - + Init(); + } + inline TRbTree(const TCmp& cmp) noexcept - : KeyCompare_(cmp) - { - Init(); - } - + : KeyCompare_(cmp) + { + Init(); + } + inline void Init() noexcept { - Data_.Color_ = RBTreeRed; + Data_.Color_ = RBTreeRed; Data_.Parent_ = nullptr; - Data_.Left_ = &Data_; - Data_.Right_ = &Data_; - Data_.Children_ = 0; - } - - struct TDestroy { + Data_.Left_ = &Data_; + Data_.Right_ = &Data_; + Data_.Children_ = 0; + } + + struct TDestroy { inline void operator()(TValue& v) const noexcept { v.SetRbTreeParent(nullptr); - v.ReInitNode(); - } - }; - + v.ReInitNode(); + } + }; + inline ~TRbTree() { - ForEachNoOrder(TDestroy()); - } - + ForEachNoOrder(TDestroy()); + } + inline void Clear() noexcept { - ForEachNoOrder(TDestroy()); - Init(); - } - - template <class F> - inline void ForEachNoOrder(const F& f) { - ForEachNoOrder(Root(), f); - } - - template <class F> - inline void ForEachNoOrder(TNodeBase* n, const F& f) { - if (n && n != &Data_) { - ForEachNoOrder(n->Left_, f); - ForEachNoOrder(n->Right_, f); - f(ValueNode(n)); - } - } - + ForEachNoOrder(TDestroy()); + Init(); + } + + template <class F> + inline void ForEachNoOrder(const F& f) { + ForEachNoOrder(Root(), f); + } + + template <class F> + inline void ForEachNoOrder(TNodeBase* n, const F& f) { + if (n && n != &Data_) { + ForEachNoOrder(n->Left_, f); + ForEachNoOrder(n->Right_, f); + f(ValueNode(n)); + } + } + inline TIterator Begin() noexcept { - return LeftMost(); - } - + return LeftMost(); + } + inline TConstIterator Begin() const noexcept { - return LeftMost(); - } - + return LeftMost(); + } + inline TIterator End() noexcept { - return &this->Data_; - } - + return &this->Data_; + } + inline TConstIterator End() const noexcept { - return const_cast<TBasePtr>(&this->Data_); - } - + return const_cast<TBasePtr>(&this->Data_); + } + inline bool Empty() const noexcept { - return this->Begin() == this->End(); - } - + return this->Begin() == this->End(); + } + inline explicit operator bool() const noexcept { - return !this->Empty(); - } - - inline TIterator Insert(TValue* val) { - return Insert(*val); - } - - inline TIterator Insert(TValue& val) { - val.UnLink(); - - TBasePtr y = &this->Data_; - TBasePtr x = Root(); - + return !this->Empty(); + } + + inline TIterator Insert(TValue* val) { + return Insert(*val); + } + + inline TIterator Insert(TValue& val) { + val.UnLink(); + + TBasePtr y = &this->Data_; + TBasePtr x = Root(); + while (x != nullptr) { - ++(x->Children_); - y = x; - - if (KeyCompare_(ValueNode(&val), ValueNode(x))) { - x = LeftNode(x); - } else { - x = RightNode(x); - } - } - - return InsertImpl(y, &val, x); - } - - template <class F> - inline void ForEach(F& f) { - TIterator it = Begin(); - - while (it != End()) { - f(*it++); - } - } - + ++(x->Children_); + y = x; + + if (KeyCompare_(ValueNode(&val), ValueNode(x))) { + x = LeftNode(x); + } else { + x = RightNode(x); + } + } + + return InsertImpl(y, &val, x); + } + + template <class F> + inline void ForEach(F& f) { + TIterator it = Begin(); + + while (it != End()) { + f(*it++); + } + } + inline void Erase(TValue& val) noexcept { - val.UnLink(); - } - + val.UnLink(); + } + inline void Erase(TValue* val) noexcept { - Erase(*val); - } - + Erase(*val); + } + inline void Erase(TIterator pos) noexcept { - Erase(*pos); - } - + Erase(*pos); + } + inline void EraseImpl(TNodeBase* val) noexcept { - TRbGlobalInst::RebalanceForErase(val, this->Data_.Parent_, this->Data_.Left_, this->Data_.Right_); - } - - template <class T1> - inline TValue* Find(const T1& k) const { + TRbGlobalInst::RebalanceForErase(val, this->Data_.Parent_, this->Data_.Left_, this->Data_.Right_); + } + + template <class T1> + inline TValue* Find(const T1& k) const { TBasePtr y = nullptr; - TBasePtr x = Root(); // Current node. - + TBasePtr x = Root(); // Current node. + while (x != nullptr) - if (!KeyCompare_(ValueNode(x), k)) - y = x, x = LeftNode(x); - else - x = RightNode(x); - - if (y) { - if (KeyCompare_(k, ValueNode(y))) { + if (!KeyCompare_(ValueNode(x), k)) + y = x, x = LeftNode(x); + else + x = RightNode(x); + + if (y) { + if (KeyCompare_(k, ValueNode(y))) { y = nullptr; - } - } - - return static_cast<TValue*>(y); - } - + } + } + + return static_cast<TValue*>(y); + } + size_t GetIndex(TBasePtr x) const { size_t index = 0; @@ -370,33 +370,33 @@ public: return index; } - template <class T1> - inline TBasePtr LowerBound(const T1& k) const { - TBasePtr y = const_cast<TBasePtr>(&this->Data_); /* Last node which is not less than k. */ - TBasePtr x = Root(); /* Current node. */ - + template <class T1> + inline TBasePtr LowerBound(const T1& k) const { + TBasePtr y = const_cast<TBasePtr>(&this->Data_); /* Last node which is not less than k. */ + TBasePtr x = Root(); /* Current node. */ + while (x != nullptr) - if (!KeyCompare_(ValueNode(x), k)) - y = x, x = LeftNode(x); - else - x = RightNode(x); - - return y; - } - - template <class T1> - inline TBasePtr UpperBound(const T1& k) const { - TBasePtr y = const_cast<TBasePtr>(&this->Data_); /* Last node which is greater than k. */ - TBasePtr x = Root(); /* Current node. */ - + if (!KeyCompare_(ValueNode(x), k)) + y = x, x = LeftNode(x); + else + x = RightNode(x); + + return y; + } + + template <class T1> + inline TBasePtr UpperBound(const T1& k) const { + TBasePtr y = const_cast<TBasePtr>(&this->Data_); /* Last node which is greater than k. */ + TBasePtr x = Root(); /* Current node. */ + while (x != nullptr) - if (KeyCompare_(k, ValueNode(x))) - y = x, x = LeftNode(x); - else - x = RightNode(x); - - return y; - } + if (KeyCompare_(k, ValueNode(x))) + y = x, x = LeftNode(x); + else + x = RightNode(x); + + return y; + } template <class T1> inline size_t LessCount(const T1& k) const { @@ -432,184 +432,184 @@ public: return Root()->Children_ - GreaterCount<T1>(k); } - TValue* ByIndex(size_t index) { - return static_cast<TValue*>(TRbTreeNodeBase::ByIndex(Root(), index)); - } - -private: - // CRP 7/10/00 inserted argument on_right, which is another hint (meant to - // act like on_left and ignore a portion of the if conditions -- specify + TValue* ByIndex(size_t index) { + return static_cast<TValue*>(TRbTreeNodeBase::ByIndex(Root(), index)); + } + +private: + // CRP 7/10/00 inserted argument on_right, which is another hint (meant to + // act like on_left and ignore a portion of the if conditions -- specify // on_right != nullptr to bypass comparison as false or on_left != nullptr to bypass - // comparison as true) + // comparison as true) TIterator InsertImpl(TRbTreeNodeBase* parent, TRbTreeNodeBase* val, TRbTreeNodeBase* on_left = nullptr, TRbTreeNodeBase* on_right = nullptr) { - ValueNode(val).SetRbTreeParent(this); - TBasePtr new_node = val; - - if (parent == &this->Data_) { - LeftNode(parent) = new_node; - // also makes LeftMost() = new_node - Root() = new_node; - RightMost() = new_node; + ValueNode(val).SetRbTreeParent(this); + TBasePtr new_node = val; + + if (parent == &this->Data_) { + LeftNode(parent) = new_node; + // also makes LeftMost() = new_node + Root() = new_node; + RightMost() = new_node; } else if (on_right == nullptr && // If on_right != nullptr, the remainder fails to false (on_left != nullptr || // If on_left != nullptr, the remainder succeeds to true - KeyCompare_(ValueNode(val), ValueNode(parent)))) - { - LeftNode(parent) = new_node; - if (parent == LeftMost()) - // maintain LeftMost() pointing to min node - LeftMost() = new_node; - } else { - RightNode(parent) = new_node; - if (parent == RightMost()) - // maintain RightMost() pointing to max node - RightMost() = new_node; - } - ParentNode(new_node) = parent; - TRbGlobalInst::Rebalance(new_node, this->Data_.Parent_); - return new_node; - } - - TBasePtr Root() const { - return this->Data_.Parent_; - } - - TBasePtr LeftMost() const { - return this->Data_.Left_; - } - - TBasePtr RightMost() const { - return this->Data_.Right_; - } - - TBasePtr& Root() { - return this->Data_.Parent_; - } - - TBasePtr& LeftMost() { - return this->Data_.Left_; - } - - TBasePtr& RightMost() { - return this->Data_.Right_; - } - - static TBasePtr& LeftNode(TBasePtr x) { - return x->Left_; - } - - static TBasePtr& RightNode(TBasePtr x) { - return x->Right_; - } - - static TBasePtr& ParentNode(TBasePtr x) { - return x->Parent_; - } - - static TValue& ValueNode(TBasePtr x) { - return *static_cast<TValue*>(x); - } - - static TBasePtr MinimumNode(TBasePtr x) { - return TRbTreeNodeBase::MinimumNode(x); - } - - static TBasePtr MaximumNode(TBasePtr x) { - return TRbTreeNodeBase::MaximumNode(x); - } - -private: - TCmpAdaptor KeyCompare_; - TNodeBase Data_; -}; - -template <class TValue, class TCmp> -class TRbTreeItem: public TRbTree<TValue, TCmp>::TRealNode { -}; - -template <class TDummy> -void TRbGlobal<TDummy>::RotateLeft(TRbTreeNodeBase* x, TRbTreeNodeBase*& root) { - TRbTreeNodeBase* y = x->Right_; - x->Right_ = y->Left_; + KeyCompare_(ValueNode(val), ValueNode(parent)))) + { + LeftNode(parent) = new_node; + if (parent == LeftMost()) + // maintain LeftMost() pointing to min node + LeftMost() = new_node; + } else { + RightNode(parent) = new_node; + if (parent == RightMost()) + // maintain RightMost() pointing to max node + RightMost() = new_node; + } + ParentNode(new_node) = parent; + TRbGlobalInst::Rebalance(new_node, this->Data_.Parent_); + return new_node; + } + + TBasePtr Root() const { + return this->Data_.Parent_; + } + + TBasePtr LeftMost() const { + return this->Data_.Left_; + } + + TBasePtr RightMost() const { + return this->Data_.Right_; + } + + TBasePtr& Root() { + return this->Data_.Parent_; + } + + TBasePtr& LeftMost() { + return this->Data_.Left_; + } + + TBasePtr& RightMost() { + return this->Data_.Right_; + } + + static TBasePtr& LeftNode(TBasePtr x) { + return x->Left_; + } + + static TBasePtr& RightNode(TBasePtr x) { + return x->Right_; + } + + static TBasePtr& ParentNode(TBasePtr x) { + return x->Parent_; + } + + static TValue& ValueNode(TBasePtr x) { + return *static_cast<TValue*>(x); + } + + static TBasePtr MinimumNode(TBasePtr x) { + return TRbTreeNodeBase::MinimumNode(x); + } + + static TBasePtr MaximumNode(TBasePtr x) { + return TRbTreeNodeBase::MaximumNode(x); + } + +private: + TCmpAdaptor KeyCompare_; + TNodeBase Data_; +}; + +template <class TValue, class TCmp> +class TRbTreeItem: public TRbTree<TValue, TCmp>::TRealNode { +}; + +template <class TDummy> +void TRbGlobal<TDummy>::RotateLeft(TRbTreeNodeBase* x, TRbTreeNodeBase*& root) { + TRbTreeNodeBase* y = x->Right_; + x->Right_ = y->Left_; if (y->Left_ != nullptr) - y->Left_->Parent_ = x; - y->Parent_ = x->Parent_; - - if (x == root) - root = y; - else if (x == x->Parent_->Left_) - x->Parent_->Left_ = y; - else - x->Parent_->Right_ = y; - y->Left_ = x; - x->Parent_ = y; + y->Left_->Parent_ = x; + y->Parent_ = x->Parent_; + + if (x == root) + root = y; + else if (x == x->Parent_->Left_) + x->Parent_->Left_ = y; + else + x->Parent_->Right_ = y; + y->Left_ = x; + x->Parent_ = y; y->Children_ = x->Children_; x->Children_ = ((x->Left_) ? x->Left_->Children_ : 0) + ((x->Right_) ? x->Right_->Children_ : 0) + 1; -} - -template <class TDummy> -void TRbGlobal<TDummy>::RotateRight(TRbTreeNodeBase* x, TRbTreeNodeBase*& root) { - TRbTreeNodeBase* y = x->Left_; - x->Left_ = y->Right_; +} + +template <class TDummy> +void TRbGlobal<TDummy>::RotateRight(TRbTreeNodeBase* x, TRbTreeNodeBase*& root) { + TRbTreeNodeBase* y = x->Left_; + x->Left_ = y->Right_; if (y->Right_ != nullptr) - y->Right_->Parent_ = x; - y->Parent_ = x->Parent_; - - if (x == root) - root = y; - else if (x == x->Parent_->Right_) - x->Parent_->Right_ = y; - else - x->Parent_->Left_ = y; - y->Right_ = x; - x->Parent_ = y; + y->Right_->Parent_ = x; + y->Parent_ = x->Parent_; + + if (x == root) + root = y; + else if (x == x->Parent_->Right_) + x->Parent_->Right_ = y; + else + x->Parent_->Left_ = y; + y->Right_ = x; + x->Parent_ = y; y->Children_ = x->Children_; x->Children_ = ((x->Left_) ? x->Left_->Children_ : 0) + ((x->Right_) ? x->Right_->Children_ : 0) + 1; -} - -template <class TDummy> -void TRbGlobal<TDummy>::Rebalance(TRbTreeNodeBase* x, TRbTreeNodeBase*& root) { - x->Color_ = RBTreeRed; - while (x != root && x->Parent_->Color_ == RBTreeRed) { - if (x->Parent_ == x->Parent_->Parent_->Left_) { - TRbTreeNodeBase* y = x->Parent_->Parent_->Right_; - if (y && y->Color_ == RBTreeRed) { - x->Parent_->Color_ = RBTreeBlack; - y->Color_ = RBTreeBlack; - x->Parent_->Parent_->Color_ = RBTreeRed; - x = x->Parent_->Parent_; - } else { - if (x == x->Parent_->Right_) { - x = x->Parent_; - RotateLeft(x, root); - } - x->Parent_->Color_ = RBTreeBlack; - x->Parent_->Parent_->Color_ = RBTreeRed; - RotateRight(x->Parent_->Parent_, root); - } - } else { - TRbTreeNodeBase* y = x->Parent_->Parent_->Left_; - if (y && y->Color_ == RBTreeRed) { - x->Parent_->Color_ = RBTreeBlack; - y->Color_ = RBTreeBlack; - x->Parent_->Parent_->Color_ = RBTreeRed; - x = x->Parent_->Parent_; - } else { - if (x == x->Parent_->Left_) { - x = x->Parent_; - RotateRight(x, root); - } - x->Parent_->Color_ = RBTreeBlack; - x->Parent_->Parent_->Color_ = RBTreeRed; - RotateLeft(x->Parent_->Parent_, root); - } - } - } - root->Color_ = RBTreeBlack; -} - -template <class TDummy> +} + +template <class TDummy> +void TRbGlobal<TDummy>::Rebalance(TRbTreeNodeBase* x, TRbTreeNodeBase*& root) { + x->Color_ = RBTreeRed; + while (x != root && x->Parent_->Color_ == RBTreeRed) { + if (x->Parent_ == x->Parent_->Parent_->Left_) { + TRbTreeNodeBase* y = x->Parent_->Parent_->Right_; + if (y && y->Color_ == RBTreeRed) { + x->Parent_->Color_ = RBTreeBlack; + y->Color_ = RBTreeBlack; + x->Parent_->Parent_->Color_ = RBTreeRed; + x = x->Parent_->Parent_; + } else { + if (x == x->Parent_->Right_) { + x = x->Parent_; + RotateLeft(x, root); + } + x->Parent_->Color_ = RBTreeBlack; + x->Parent_->Parent_->Color_ = RBTreeRed; + RotateRight(x->Parent_->Parent_, root); + } + } else { + TRbTreeNodeBase* y = x->Parent_->Parent_->Left_; + if (y && y->Color_ == RBTreeRed) { + x->Parent_->Color_ = RBTreeBlack; + y->Color_ = RBTreeBlack; + x->Parent_->Parent_->Color_ = RBTreeRed; + x = x->Parent_->Parent_; + } else { + if (x == x->Parent_->Left_) { + x = x->Parent_; + RotateRight(x, root); + } + x->Parent_->Color_ = RBTreeBlack; + x->Parent_->Parent_->Color_ = RBTreeRed; + RotateLeft(x->Parent_->Parent_, root); + } + } + } + root->Color_ = RBTreeBlack; +} + +template <class TDummy> void TRbGlobal<TDummy>::RecalcChildren(TRbTreeNodeBase* x) { x->Children_ = ((x->Left_) ? x->Left_->Children_ : 0) + ((x->Right_) ? x->Right_->Children_ : 0) + 1; } @@ -625,46 +625,46 @@ void TRbGlobal<TDummy>::DecrementChildrenUntilRoot(TRbTreeNodeBase* x, TRbTreeNo } template <class TDummy> -TRbTreeNodeBase* TRbGlobal<TDummy>::RebalanceForErase(TRbTreeNodeBase* z, - TRbTreeNodeBase*& root, - TRbTreeNodeBase*& leftmost, - TRbTreeNodeBase*& rightmost) { - TRbTreeNodeBase* y = z; - TRbTreeNodeBase* x; - TRbTreeNodeBase* x_parent; - +TRbTreeNodeBase* TRbGlobal<TDummy>::RebalanceForErase(TRbTreeNodeBase* z, + TRbTreeNodeBase*& root, + TRbTreeNodeBase*& leftmost, + TRbTreeNodeBase*& rightmost) { + TRbTreeNodeBase* y = z; + TRbTreeNodeBase* x; + TRbTreeNodeBase* x_parent; + if (y->Left_ == nullptr) // z has at most one non-null child. y == z. - x = y->Right_; // x might be null. - else { - if (y->Right_ == nullptr) // z has exactly one non-null child. y == z. - x = y->Left_; // x is not null. - else { // z has two non-null children. Set y to - y = TRbTreeNodeBase::MinimumNode(y->Right_); // z's successor. x might be null. - x = y->Right_; - } - } - - if (y != z) { - // relink y in place of z. y is z's successor - z->Left_->Parent_ = y; - y->Left_ = z->Left_; - if (y != z->Right_) { - x_parent = y->Parent_; - if (x) - x->Parent_ = y->Parent_; - y->Parent_->Left_ = x; // y must be a child of mLeft - y->Right_ = z->Right_; - z->Right_->Parent_ = y; - } else - x_parent = y; - if (root == z) - root = y; - else if (z->Parent_->Left_ == z) - z->Parent_->Left_ = y; - else - z->Parent_->Right_ = y; - y->Parent_ = z->Parent_; - DoSwap(y->Color_, z->Color_); + x = y->Right_; // x might be null. + else { + if (y->Right_ == nullptr) // z has exactly one non-null child. y == z. + x = y->Left_; // x is not null. + else { // z has two non-null children. Set y to + y = TRbTreeNodeBase::MinimumNode(y->Right_); // z's successor. x might be null. + x = y->Right_; + } + } + + if (y != z) { + // relink y in place of z. y is z's successor + z->Left_->Parent_ = y; + y->Left_ = z->Left_; + if (y != z->Right_) { + x_parent = y->Parent_; + if (x) + x->Parent_ = y->Parent_; + y->Parent_->Left_ = x; // y must be a child of mLeft + y->Right_ = z->Right_; + z->Right_->Parent_ = y; + } else + x_parent = y; + if (root == z) + root = y; + else if (z->Parent_->Left_ == z) + z->Parent_->Left_ = y; + else + z->Parent_->Right_ = y; + y->Parent_ = z->Parent_; + DoSwap(y->Color_, z->Color_); RecalcChildren(y); if (x_parent != y) { @@ -673,146 +673,146 @@ TRbTreeNodeBase* TRbGlobal<TDummy>::RebalanceForErase(TRbTreeNodeBase* z, if (x_parent != root) { DecrementChildrenUntilRoot(x_parent->Parent_, root); } - y = z; - // y now points to node to be actually deleted - } else { - // y == z - x_parent = y->Parent_; - if (x) - x->Parent_ = y->Parent_; - if (root == z) - root = x; - else { - if (z->Parent_->Left_ == z) - z->Parent_->Left_ = x; - else - z->Parent_->Right_ = x; - DecrementChildrenUntilRoot(z->Parent_, root); // we lost y - } - - if (leftmost == z) { + y = z; + // y now points to node to be actually deleted + } else { + // y == z + x_parent = y->Parent_; + if (x) + x->Parent_ = y->Parent_; + if (root == z) + root = x; + else { + if (z->Parent_->Left_ == z) + z->Parent_->Left_ = x; + else + z->Parent_->Right_ = x; + DecrementChildrenUntilRoot(z->Parent_, root); // we lost y + } + + if (leftmost == z) { if (z->Right_ == nullptr) // z->mLeft must be null also - leftmost = z->Parent_; - // makes leftmost == _M_header if z == root - else - leftmost = TRbTreeNodeBase::MinimumNode(x); - } - if (rightmost == z) { + leftmost = z->Parent_; + // makes leftmost == _M_header if z == root + else + leftmost = TRbTreeNodeBase::MinimumNode(x); + } + if (rightmost == z) { if (z->Left_ == nullptr) // z->mRight must be null also - rightmost = z->Parent_; - // makes rightmost == _M_header if z == root - else // x == z->mLeft - rightmost = TRbTreeNodeBase::MaximumNode(x); - } - } - - if (y->Color_ != RBTreeRed) { + rightmost = z->Parent_; + // makes rightmost == _M_header if z == root + else // x == z->mLeft + rightmost = TRbTreeNodeBase::MaximumNode(x); + } + } + + if (y->Color_ != RBTreeRed) { while (x != root && (x == nullptr || x->Color_ == RBTreeBlack)) - if (x == x_parent->Left_) { - TRbTreeNodeBase* w = x_parent->Right_; - if (w->Color_ == RBTreeRed) { - w->Color_ = RBTreeBlack; - x_parent->Color_ = RBTreeRed; - RotateLeft(x_parent, root); - w = x_parent->Right_; - } + if (x == x_parent->Left_) { + TRbTreeNodeBase* w = x_parent->Right_; + if (w->Color_ == RBTreeRed) { + w->Color_ = RBTreeBlack; + x_parent->Color_ = RBTreeRed; + RotateLeft(x_parent, root); + w = x_parent->Right_; + } if ((w->Left_ == nullptr || - w->Left_->Color_ == RBTreeBlack) && + w->Left_->Color_ == RBTreeBlack) && (w->Right_ == nullptr || - w->Right_->Color_ == RBTreeBlack)) - { - w->Color_ = RBTreeRed; - x = x_parent; - x_parent = x_parent->Parent_; - } else { - if (w->Right_ == nullptr || w->Right_->Color_ == RBTreeBlack) { - if (w->Left_) - w->Left_->Color_ = RBTreeBlack; - w->Color_ = RBTreeRed; - RotateRight(w, root); - w = x_parent->Right_; - } - w->Color_ = x_parent->Color_; - x_parent->Color_ = RBTreeBlack; - if (w->Right_) - w->Right_->Color_ = RBTreeBlack; - RotateLeft(x_parent, root); - break; - } - } else { - // same as above, with mRight <-> mLeft. - TRbTreeNodeBase* w = x_parent->Left_; - if (w->Color_ == RBTreeRed) { - w->Color_ = RBTreeBlack; - x_parent->Color_ = RBTreeRed; - RotateRight(x_parent, root); - w = x_parent->Left_; - } + w->Right_->Color_ == RBTreeBlack)) + { + w->Color_ = RBTreeRed; + x = x_parent; + x_parent = x_parent->Parent_; + } else { + if (w->Right_ == nullptr || w->Right_->Color_ == RBTreeBlack) { + if (w->Left_) + w->Left_->Color_ = RBTreeBlack; + w->Color_ = RBTreeRed; + RotateRight(w, root); + w = x_parent->Right_; + } + w->Color_ = x_parent->Color_; + x_parent->Color_ = RBTreeBlack; + if (w->Right_) + w->Right_->Color_ = RBTreeBlack; + RotateLeft(x_parent, root); + break; + } + } else { + // same as above, with mRight <-> mLeft. + TRbTreeNodeBase* w = x_parent->Left_; + if (w->Color_ == RBTreeRed) { + w->Color_ = RBTreeBlack; + x_parent->Color_ = RBTreeRed; + RotateRight(x_parent, root); + w = x_parent->Left_; + } if ((w->Right_ == nullptr || - w->Right_->Color_ == RBTreeBlack) && + w->Right_->Color_ == RBTreeBlack) && (w->Left_ == nullptr || - w->Left_->Color_ == RBTreeBlack)) - { - w->Color_ = RBTreeRed; - x = x_parent; - x_parent = x_parent->Parent_; - } else { - if (w->Left_ == nullptr || w->Left_->Color_ == RBTreeBlack) { - if (w->Right_) - w->Right_->Color_ = RBTreeBlack; - w->Color_ = RBTreeRed; - RotateLeft(w, root); - w = x_parent->Left_; - } - w->Color_ = x_parent->Color_; - x_parent->Color_ = RBTreeBlack; - if (w->Left_) - w->Left_->Color_ = RBTreeBlack; - RotateRight(x_parent, root); - break; - } - } - if (x) - x->Color_ = RBTreeBlack; - } - return y; -} - -template <class TDummy> -TRbTreeNodeBase* TRbGlobal<TDummy>::DecrementNode(TRbTreeNodeBase* Node_) { - if (Node_->Color_ == RBTreeRed && Node_->Parent_->Parent_ == Node_) - Node_ = Node_->Right_; + w->Left_->Color_ == RBTreeBlack)) + { + w->Color_ = RBTreeRed; + x = x_parent; + x_parent = x_parent->Parent_; + } else { + if (w->Left_ == nullptr || w->Left_->Color_ == RBTreeBlack) { + if (w->Right_) + w->Right_->Color_ = RBTreeBlack; + w->Color_ = RBTreeRed; + RotateLeft(w, root); + w = x_parent->Left_; + } + w->Color_ = x_parent->Color_; + x_parent->Color_ = RBTreeBlack; + if (w->Left_) + w->Left_->Color_ = RBTreeBlack; + RotateRight(x_parent, root); + break; + } + } + if (x) + x->Color_ = RBTreeBlack; + } + return y; +} + +template <class TDummy> +TRbTreeNodeBase* TRbGlobal<TDummy>::DecrementNode(TRbTreeNodeBase* Node_) { + if (Node_->Color_ == RBTreeRed && Node_->Parent_->Parent_ == Node_) + Node_ = Node_->Right_; else if (Node_->Left_ != nullptr) { - Node_ = TRbTreeNodeBase::MaximumNode(Node_->Left_); - } else { - TBasePtr y = Node_->Parent_; - while (Node_ == y->Left_) { - Node_ = y; - y = y->Parent_; - } - Node_ = y; - } - return Node_; -} - -template <class TDummy> -TRbTreeNodeBase* TRbGlobal<TDummy>::IncrementNode(TRbTreeNodeBase* Node_) { + Node_ = TRbTreeNodeBase::MaximumNode(Node_->Left_); + } else { + TBasePtr y = Node_->Parent_; + while (Node_ == y->Left_) { + Node_ = y; + y = y->Parent_; + } + Node_ = y; + } + return Node_; +} + +template <class TDummy> +TRbTreeNodeBase* TRbGlobal<TDummy>::IncrementNode(TRbTreeNodeBase* Node_) { if (Node_->Right_ != nullptr) { - Node_ = TRbTreeNodeBase::MinimumNode(Node_->Right_); - } else { - TBasePtr y = Node_->Parent_; - while (Node_ == y->Right_) { - Node_ = y; - y = y->Parent_; - } - // check special case: This is necessary if mNode is the - // _M_head and the tree contains only a single node y. In - // that case parent, left and right all point to y! - if (Node_->Right_ != y) - Node_ = y; - } - return Node_; -} - -#undef RBTreeRed -#undef RBTreeBlack + Node_ = TRbTreeNodeBase::MinimumNode(Node_->Right_); + } else { + TBasePtr y = Node_->Parent_; + while (Node_ == y->Right_) { + Node_ = y; + y = y->Parent_; + } + // check special case: This is necessary if mNode is the + // _M_head and the tree contains only a single node y. In + // that case parent, left and right all point to y! + if (Node_->Right_ != y) + Node_ = y; + } + return Node_; +} + +#undef RBTreeRed +#undef RBTreeBlack diff --git a/library/cpp/containers/intrusive_rb_tree/rb_tree_ut.cpp b/library/cpp/containers/intrusive_rb_tree/rb_tree_ut.cpp index cea3ab4421..c34ed1fd9b 100644 --- a/library/cpp/containers/intrusive_rb_tree/rb_tree_ut.cpp +++ b/library/cpp/containers/intrusive_rb_tree/rb_tree_ut.cpp @@ -1,82 +1,82 @@ -#include "rb_tree.h" - +#include "rb_tree.h" + #include <library/cpp/testing/unittest/registar.h> - -#include <util/random/fast.h> -#include <util/random/easy.h> + +#include <util/random/fast.h> +#include <util/random/easy.h> #include <util/random/shuffle.h> - -class TRedBlackTreeTest: public TTestBase { - struct TCmp { - template <class T> - static inline bool Compare(const T& l, const T& r) { - return l.N < r.N; - } - - template <class T> - static inline bool Compare(const T& l, int r) { - return l.N < r; - } - - template <class T> - static inline bool Compare(int l, const T& r) { - return l < r.N; - } - }; - - class TNode: public TRbTreeItem<TNode, TCmp> { - public: + +class TRedBlackTreeTest: public TTestBase { + struct TCmp { + template <class T> + static inline bool Compare(const T& l, const T& r) { + return l.N < r.N; + } + + template <class T> + static inline bool Compare(const T& l, int r) { + return l.N < r; + } + + template <class T> + static inline bool Compare(int l, const T& r) { + return l < r.N; + } + }; + + class TNode: public TRbTreeItem<TNode, TCmp> { + public: inline TNode(int n) noexcept - : N(n) - { - } - - int N; - }; - + : N(n) + { + } + + int N; + }; + using TTree = TRbTree<TNode, TCmp>; - - UNIT_TEST_SUITE(TRedBlackTreeTest); - UNIT_TEST(TestEmpty) - UNIT_TEST(TestInsert) - UNIT_TEST(TestErase) - UNIT_TEST(TestFind) - UNIT_TEST(TestStress) + + UNIT_TEST_SUITE(TRedBlackTreeTest); + UNIT_TEST(TestEmpty) + UNIT_TEST(TestInsert) + UNIT_TEST(TestErase) + UNIT_TEST(TestFind) + UNIT_TEST(TestStress) UNIT_TEST(TestGettingIndexWithDifferentValues) UNIT_TEST(TestCheckChildrenAfterErase) UNIT_TEST(TestGettingIndexWithDifferentValuesAfterErase) UNIT_TEST(TestGettingIndexWithEqualValues) UNIT_TEST(TestLessCountOnEmptyTree) - UNIT_TEST_SUITE_END(); - -private: - inline void TestStress() { + UNIT_TEST_SUITE_END(); + +private: + inline void TestStress() { TVector<TSimpleSharedPtr<TNode>> nodes; - - for (int i = 0; i < 1000; ++i) { - nodes.push_back(new TNode(i)); - } - - TTree tree; - TReallyFastRng32 rnd(Random()); - - for (size_t i = 0; i < 1000000; ++i) { - tree.Insert(nodes[rnd.Uniform(nodes.size())].Get()); - } - - for (TTree::TConstIterator it = tree.Begin(); it != tree.End();) { - const int v1 = it->N; - - if (++it == tree.End()) { - break; - } - - const int v2 = it->N; - - UNIT_ASSERT(v1 < v2); - } - } - + + for (int i = 0; i < 1000; ++i) { + nodes.push_back(new TNode(i)); + } + + TTree tree; + TReallyFastRng32 rnd(Random()); + + for (size_t i = 0; i < 1000000; ++i) { + tree.Insert(nodes[rnd.Uniform(nodes.size())].Get()); + } + + for (TTree::TConstIterator it = tree.Begin(); it != tree.End();) { + const int v1 = it->N; + + if (++it == tree.End()) { + break; + } + + const int v2 = it->N; + + UNIT_ASSERT(v1 < v2); + } + } + inline void TestGettingIndexWithDifferentValues() { TVector<TSimpleSharedPtr<TNode>> nodes; size_t N = 1000; @@ -202,97 +202,97 @@ private: } } - inline void TestFind() { - TTree tree; - - { - TNode n1(1); - TNode n2(2); - TNode n3(3); - - tree.Insert(n1); - tree.Insert(n2); - tree.Insert(n3); - - UNIT_ASSERT_EQUAL(tree.Find(1)->N, 1); - UNIT_ASSERT_EQUAL(tree.Find(2)->N, 2); - UNIT_ASSERT_EQUAL(tree.Find(3)->N, 3); - - UNIT_ASSERT(!tree.Find(0)); - UNIT_ASSERT(!tree.Find(4)); - UNIT_ASSERT(!tree.Find(1234567)); - } - - UNIT_ASSERT(tree.Empty()); - } - - inline void TestEmpty() { - TTree tree; - - UNIT_ASSERT(tree.Empty()); - UNIT_ASSERT_EQUAL(tree.Begin(), tree.End()); - } - - inline void TestInsert() { - TTree tree; - - { - TNode n1(1); - TNode n2(2); - TNode n3(3); - - tree.Insert(n1); - tree.Insert(n2); - tree.Insert(n3); - - TTree::TConstIterator it = tree.Begin(); - - UNIT_ASSERT_EQUAL((it++)->N, 1); - UNIT_ASSERT_EQUAL((it++)->N, 2); - UNIT_ASSERT_EQUAL((it++)->N, 3); - UNIT_ASSERT_EQUAL(it, tree.End()); - } - - UNIT_ASSERT(tree.Empty()); - } - - inline void TestErase() { - TTree tree; - - { - TNode n1(1); - TNode n2(2); - TNode n3(3); - - tree.Insert(n1); - tree.Insert(n2); - tree.Insert(n3); - - TTree::TIterator it = tree.Begin(); - - tree.Erase(it++); - - UNIT_ASSERT_EQUAL(it, tree.Begin()); - UNIT_ASSERT_EQUAL(it->N, 2); - - tree.Erase(it++); - - UNIT_ASSERT_EQUAL(it, tree.Begin()); - UNIT_ASSERT_EQUAL(it->N, 3); - - tree.Erase(it++); - - UNIT_ASSERT_EQUAL(it, tree.Begin()); - UNIT_ASSERT_EQUAL(it, tree.End()); - } - - UNIT_ASSERT(tree.Empty()); - } + inline void TestFind() { + TTree tree; + + { + TNode n1(1); + TNode n2(2); + TNode n3(3); + + tree.Insert(n1); + tree.Insert(n2); + tree.Insert(n3); + + UNIT_ASSERT_EQUAL(tree.Find(1)->N, 1); + UNIT_ASSERT_EQUAL(tree.Find(2)->N, 2); + UNIT_ASSERT_EQUAL(tree.Find(3)->N, 3); + + UNIT_ASSERT(!tree.Find(0)); + UNIT_ASSERT(!tree.Find(4)); + UNIT_ASSERT(!tree.Find(1234567)); + } + + UNIT_ASSERT(tree.Empty()); + } + + inline void TestEmpty() { + TTree tree; + + UNIT_ASSERT(tree.Empty()); + UNIT_ASSERT_EQUAL(tree.Begin(), tree.End()); + } + + inline void TestInsert() { + TTree tree; + + { + TNode n1(1); + TNode n2(2); + TNode n3(3); + + tree.Insert(n1); + tree.Insert(n2); + tree.Insert(n3); + + TTree::TConstIterator it = tree.Begin(); + + UNIT_ASSERT_EQUAL((it++)->N, 1); + UNIT_ASSERT_EQUAL((it++)->N, 2); + UNIT_ASSERT_EQUAL((it++)->N, 3); + UNIT_ASSERT_EQUAL(it, tree.End()); + } + + UNIT_ASSERT(tree.Empty()); + } + + inline void TestErase() { + TTree tree; + + { + TNode n1(1); + TNode n2(2); + TNode n3(3); + + tree.Insert(n1); + tree.Insert(n2); + tree.Insert(n3); + + TTree::TIterator it = tree.Begin(); + + tree.Erase(it++); + + UNIT_ASSERT_EQUAL(it, tree.Begin()); + UNIT_ASSERT_EQUAL(it->N, 2); + + tree.Erase(it++); + + UNIT_ASSERT_EQUAL(it, tree.Begin()); + UNIT_ASSERT_EQUAL(it->N, 3); + + tree.Erase(it++); + + UNIT_ASSERT_EQUAL(it, tree.Begin()); + UNIT_ASSERT_EQUAL(it, tree.End()); + } + + UNIT_ASSERT(tree.Empty()); + } inline void TestLessCountOnEmptyTree() { TTree tree; UNIT_ASSERT_VALUES_EQUAL(0, tree.LessCount(TNode(1))); } -}; - -UNIT_TEST_SUITE_REGISTRATION(TRedBlackTreeTest); +}; + +UNIT_TEST_SUITE_REGISTRATION(TRedBlackTreeTest); diff --git a/library/cpp/containers/intrusive_rb_tree/ut/ya.make b/library/cpp/containers/intrusive_rb_tree/ut/ya.make index 15c74020dc..6f1e3b38ee 100644 --- a/library/cpp/containers/intrusive_rb_tree/ut/ya.make +++ b/library/cpp/containers/intrusive_rb_tree/ut/ya.make @@ -1,12 +1,12 @@ UNITTEST_FOR(library/cpp/containers/intrusive_rb_tree) - + OWNER( pg g:util ) - -SRCS( - rb_tree_ut.cpp -) - -END() + +SRCS( + rb_tree_ut.cpp +) + +END() diff --git a/library/cpp/containers/intrusive_rb_tree/ya.make b/library/cpp/containers/intrusive_rb_tree/ya.make index ff2c0b5adf..2e5eddcfbe 100644 --- a/library/cpp/containers/intrusive_rb_tree/ya.make +++ b/library/cpp/containers/intrusive_rb_tree/ya.make @@ -1,12 +1,12 @@ -LIBRARY() - +LIBRARY() + OWNER( pg g:util ) - -SRCS( - rb_tree.cpp -) - -END() + +SRCS( + rb_tree.cpp +) + +END() diff --git a/library/cpp/containers/paged_vector/paged_vector.cpp b/library/cpp/containers/paged_vector/paged_vector.cpp index 52f91880bf..e354caf09d 100644 --- a/library/cpp/containers/paged_vector/paged_vector.cpp +++ b/library/cpp/containers/paged_vector/paged_vector.cpp @@ -1 +1 @@ -#include "paged_vector.h" +#include "paged_vector.h" diff --git a/library/cpp/containers/paged_vector/paged_vector.h b/library/cpp/containers/paged_vector/paged_vector.h index dbd1486a71..6a3657d3ea 100644 --- a/library/cpp/containers/paged_vector/paged_vector.h +++ b/library/cpp/containers/paged_vector/paged_vector.h @@ -4,429 +4,429 @@ #include <util/generic/vector.h> #include <util/generic/yexception.h> -#include <iterator> - +#include <iterator> + namespace NPagedVector { - template <class T, ui32 PageSize = 1u << 20, 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) { - TSelf res = *this; - res += off; - return res; - } - - TSelf operator-(ptrdiff_t off) { - return this->operator+(-off); - } - - size_t GetOffset() { - return Offset; - } - }; + template <class T, ui32 PageSize = 1u << 20, 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) { + TSelf res = *this; + res += off; + return res; + } + + TSelf operator-(ptrdiff_t off) { + return this->operator+(-off); + } + + size_t GetOffset() { + 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 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() { + //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(); - } - - void emplace_back() { - PrepareAppend(); - CurrentPage().emplace_back(); - } - - void push_back(const_reference t) { + 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(); + } + + void emplace_back() { + PrepareAppend(); + CurrentPage().emplace_back(); + } + + 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(); - 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_VERIFY(sz == size(), "%" PRIu64 " %" PRIu64, (ui64)sz, (ui64)size()); - } - reference at(size_t idx) { - return TPages::at(PageNumber(idx))->at(InPageIndex(idx)); - } + for (size_t p = NPages() - 1; p > pnum; --p) { + PageAt(p).insert(PageAt(p).begin(), PageAt(p - 1).back()); + PageAt(p - 1).pop_back(); + } - const_reference at(size_t idx) const { - return TPages::at(PageNumber(idx))->at(InPageIndex(idx)); - } + PageAt(pnum).insert(PageAt(pnum).begin() + pidx, v); + return it; + } - reference operator[](size_t idx) { - return TPages::operator[](PageNumber(idx))->operator[](InPageIndex(idx)); - } + template <typename TIter> + void insert(iterator it, TIter b, TIter e) { + // todo : suboptimal! + for (; b != e; ++b, ++it) + it = insert(it, *b); + } - const_reference operator[](size_t idx) const { - return TPages::operator[](PageNumber(idx))->operator[](InPageIndex(idx)); - } + reference front() { + return TPages::front()->front(); + } - friend bool operator==(const TSelf& a, const TSelf& b) { - return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); - } + const_reference front() const { + return TPages::front()->front(); + } - friend bool operator<(const TSelf& a, const TSelf& b) { - return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); - } - }; + 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_VERIFY(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"); + 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"); } } diff --git a/library/cpp/containers/paged_vector/ut/paged_vector_ut.cpp b/library/cpp/containers/paged_vector/ut/paged_vector_ut.cpp index 2904a1d05e..e867808ee4 100644 --- a/library/cpp/containers/paged_vector/ut/paged_vector_ut.cpp +++ b/library/cpp/containers/paged_vector/ut/paged_vector_ut.cpp @@ -1,378 +1,378 @@ #include <library/cpp/containers/paged_vector/paged_vector.h> #include <library/cpp/testing/unittest/registar.h> - -#include <stdexcept> + +#include <stdexcept> class TPagedVectorTest: public TTestBase { - UNIT_TEST_SUITE(TPagedVectorTest); - UNIT_TEST(Test0) - UNIT_TEST(Test1) - UNIT_TEST(Test2) - UNIT_TEST(Test3) - UNIT_TEST(Test4) - UNIT_TEST(Test5) - UNIT_TEST(Test6) - UNIT_TEST(Test7) - UNIT_TEST(TestAt) - UNIT_TEST(TestAutoRef) - UNIT_TEST(TestIterators) - //UNIT_TEST(TestEbo) - UNIT_TEST_SUITE_END(); - -private: - // Copy-paste of STLPort tests - void Test0() { - using NPagedVector::TPagedVector; - TPagedVector<int, 16> v1; // Empty vector of integers. - - UNIT_ASSERT(v1.empty() == true); - UNIT_ASSERT(v1.size() == 0); - - for (size_t i = 0; i < 256; ++i) { - v1.resize(i + 1); - UNIT_ASSERT_VALUES_EQUAL(v1.size(), i + 1); - } - - for (size_t i = 256; i-- > 0;) { - v1.resize(i); - UNIT_ASSERT_VALUES_EQUAL(v1.size(), i); + UNIT_TEST_SUITE(TPagedVectorTest); + UNIT_TEST(Test0) + UNIT_TEST(Test1) + UNIT_TEST(Test2) + UNIT_TEST(Test3) + UNIT_TEST(Test4) + UNIT_TEST(Test5) + UNIT_TEST(Test6) + UNIT_TEST(Test7) + UNIT_TEST(TestAt) + UNIT_TEST(TestAutoRef) + UNIT_TEST(TestIterators) + //UNIT_TEST(TestEbo) + UNIT_TEST_SUITE_END(); + +private: + // Copy-paste of STLPort tests + void Test0() { + using NPagedVector::TPagedVector; + TPagedVector<int, 16> v1; // Empty vector of integers. + + UNIT_ASSERT(v1.empty() == true); + UNIT_ASSERT(v1.size() == 0); + + for (size_t i = 0; i < 256; ++i) { + v1.resize(i + 1); + UNIT_ASSERT_VALUES_EQUAL(v1.size(), i + 1); + } + + for (size_t i = 256; i-- > 0;) { + v1.resize(i); + UNIT_ASSERT_VALUES_EQUAL(v1.size(), i); } - } + } - void Test1() { - using NPagedVector::TPagedVector; - TPagedVector<int, 3> v1; // Empty vector of integers. + void Test1() { + using NPagedVector::TPagedVector; + TPagedVector<int, 3> v1; // Empty vector of integers. - UNIT_ASSERT(v1.empty() == true); - UNIT_ASSERT(v1.size() == 0); + UNIT_ASSERT(v1.empty() == true); + UNIT_ASSERT(v1.size() == 0); - // UNIT_ASSERT(v1.max_size() == INT_MAX / sizeof(int)); - // cout << "max_size = " << v1.max_size() << endl; - v1.push_back(42); // Add an integer to the vector. + // UNIT_ASSERT(v1.max_size() == INT_MAX / sizeof(int)); + // cout << "max_size = " << v1.max_size() << endl; + v1.push_back(42); // Add an integer to the vector. - UNIT_ASSERT(v1.size() == 1); + UNIT_ASSERT(v1.size() == 1); - UNIT_ASSERT(v1[0] == 42); + UNIT_ASSERT(v1[0] == 42); - { - TPagedVector<TPagedVector<int, 3>, 3> vect; - vect.resize(10); - UNIT_ASSERT(vect.size() == 10); - TPagedVector<TPagedVector<int, 3>, 3>::iterator it(vect.begin()), end(vect.end()); - for (; it != end; ++it) { - UNIT_ASSERT((*it).empty()); - UNIT_ASSERT((*it).size() == 0); - UNIT_ASSERT((*it).begin() == (*it).end()); + { + TPagedVector<TPagedVector<int, 3>, 3> vect; + vect.resize(10); + UNIT_ASSERT(vect.size() == 10); + TPagedVector<TPagedVector<int, 3>, 3>::iterator it(vect.begin()), end(vect.end()); + for (; it != end; ++it) { + UNIT_ASSERT((*it).empty()); + UNIT_ASSERT((*it).size() == 0); + UNIT_ASSERT((*it).begin() == (*it).end()); } } - } + } - void Test2() { - using NPagedVector::TPagedVector; - TPagedVector<double, 3> v1; // Empty vector of doubles. - v1.push_back(32.1); - v1.push_back(40.5); - v1.push_back(45.5); - v1.push_back(33.4); - TPagedVector<double, 3> v2; // Another empty vector of doubles. - v2.push_back(3.56); + void Test2() { + using NPagedVector::TPagedVector; + TPagedVector<double, 3> v1; // Empty vector of doubles. + v1.push_back(32.1); + v1.push_back(40.5); + v1.push_back(45.5); + v1.push_back(33.4); + TPagedVector<double, 3> v2; // Another empty vector of doubles. + v2.push_back(3.56); - UNIT_ASSERT(v1.size() == 4); - UNIT_ASSERT(v1[0] == 32.1); - UNIT_ASSERT(v1[1] == 40.5); - UNIT_ASSERT(v1[2] == 45.5); - UNIT_ASSERT(v1[3] == 33.4); + UNIT_ASSERT(v1.size() == 4); + UNIT_ASSERT(v1[0] == 32.1); + UNIT_ASSERT(v1[1] == 40.5); + UNIT_ASSERT(v1[2] == 45.5); + UNIT_ASSERT(v1[3] == 33.4); - UNIT_ASSERT(v2.size() == 1); - UNIT_ASSERT(v2[0] == 3.56); - v1.swap(v2); // Swap the vector's contents. + UNIT_ASSERT(v2.size() == 1); + UNIT_ASSERT(v2[0] == 3.56); + v1.swap(v2); // Swap the vector's contents. - UNIT_ASSERT(v1.size() == 1); - UNIT_ASSERT(v1[0] == 3.56); + UNIT_ASSERT(v1.size() == 1); + UNIT_ASSERT(v1[0] == 3.56); - UNIT_ASSERT(v2.size() == 4); - UNIT_ASSERT(v2[0] == 32.1); - UNIT_ASSERT(v2[1] == 40.5); - UNIT_ASSERT(v2[2] == 45.5); - UNIT_ASSERT(v2[3] == 33.4); + UNIT_ASSERT(v2.size() == 4); + UNIT_ASSERT(v2[0] == 32.1); + UNIT_ASSERT(v2[1] == 40.5); + UNIT_ASSERT(v2[2] == 45.5); + UNIT_ASSERT(v2[3] == 33.4); - v2 = v1; // Assign one vector to another. + v2 = v1; // Assign one vector to another. - UNIT_ASSERT(v2.size() == 1); - UNIT_ASSERT(v2[0] == 3.56); + UNIT_ASSERT(v2.size() == 1); + UNIT_ASSERT(v2[0] == 3.56); - v2.pop_back(); - UNIT_ASSERT(v2.size() == 0); - UNIT_ASSERT(v2.empty()); - } + v2.pop_back(); + UNIT_ASSERT(v2.size() == 0); + UNIT_ASSERT(v2.empty()); + } - void Test3() { - using NPagedVector::TPagedVector; - TPagedVector<char, 1> v1; + void Test3() { + using NPagedVector::TPagedVector; + TPagedVector<char, 1> v1; - v1.push_back('h'); - v1.push_back('i'); + v1.push_back('h'); + v1.push_back('i'); - UNIT_ASSERT(v1.size() == 2); - UNIT_ASSERT(v1[0] == 'h'); - UNIT_ASSERT(v1[1] == 'i'); + UNIT_ASSERT(v1.size() == 2); + UNIT_ASSERT(v1[0] == 'h'); + UNIT_ASSERT(v1[1] == 'i'); - TPagedVector<char, 1> v2; - v2.resize(v1.size()); + TPagedVector<char, 1> v2; + v2.resize(v1.size()); - for (size_t i = 0; i < v1.size(); ++i) - v2[i] = v1[i]; + for (size_t i = 0; i < v1.size(); ++i) + v2[i] = v1[i]; - v2[1] = 'o'; // Replace second character. + v2[1] = 'o'; // Replace second character. - UNIT_ASSERT(v2.size() == 2); - UNIT_ASSERT(v2[0] == 'h'); - UNIT_ASSERT(v2[1] == 'o'); + UNIT_ASSERT(v2.size() == 2); + UNIT_ASSERT(v2[0] == 'h'); + UNIT_ASSERT(v2[1] == 'o'); - UNIT_ASSERT((v1 == v2) == false); + UNIT_ASSERT((v1 == v2) == false); - UNIT_ASSERT((v1 < v2) == true); - } + UNIT_ASSERT((v1 < v2) == true); + } - void Test4() { - using NPagedVector::TPagedVector; - TPagedVector<int, 3> v; - v.resize(4); + void Test4() { + using NPagedVector::TPagedVector; + TPagedVector<int, 3> v; + v.resize(4); - v[0] = 1; - v[1] = 4; - v[2] = 9; - v[3] = 16; + v[0] = 1; + v[1] = 4; + v[2] = 9; + v[3] = 16; - UNIT_ASSERT(v.front() == 1); - UNIT_ASSERT(v.back() == 16); + UNIT_ASSERT(v.front() == 1); + UNIT_ASSERT(v.back() == 16); - v.push_back(25); + v.push_back(25); - UNIT_ASSERT(v.back() == 25); - UNIT_ASSERT(v.size() == 5); + UNIT_ASSERT(v.back() == 25); + UNIT_ASSERT(v.size() == 5); - v.pop_back(); + v.pop_back(); - UNIT_ASSERT(v.back() == 16); - UNIT_ASSERT(v.size() == 4); - } + UNIT_ASSERT(v.back() == 16); + UNIT_ASSERT(v.size() == 4); + } - void Test5() { - int array[] = {1, 4, 9, 16}; + void Test5() { + int array[] = {1, 4, 9, 16}; - typedef NPagedVector::TPagedVector<int, 3> TVectorType; - TVectorType v(array, array + 4); + typedef NPagedVector::TPagedVector<int, 3> TVectorType; + TVectorType v(array, array + 4); - UNIT_ASSERT(v.size() == 4); - - UNIT_ASSERT(v[0] == 1); - UNIT_ASSERT(v[1] == 4); - UNIT_ASSERT(v[2] == 9); - UNIT_ASSERT(v[3] == 16); - } - - void Test6() { - int array[] = {1, 4, 9, 16, 25, 36}; + UNIT_ASSERT(v.size() == 4); + + UNIT_ASSERT(v[0] == 1); + UNIT_ASSERT(v[1] == 4); + UNIT_ASSERT(v[2] == 9); + UNIT_ASSERT(v[3] == 16); + } + + void Test6() { + int array[] = {1, 4, 9, 16, 25, 36}; - typedef NPagedVector::TPagedVector<int, 3> TVectorType; - TVectorType v(array, array + 6); - TVectorType::iterator vit; + typedef NPagedVector::TPagedVector<int, 3> TVectorType; + TVectorType v(array, array + 6); + TVectorType::iterator vit; - UNIT_ASSERT_VALUES_EQUAL(v.size(), 6u); - UNIT_ASSERT(v[0] == 1); - UNIT_ASSERT(v[1] == 4); - UNIT_ASSERT(v[2] == 9); - UNIT_ASSERT(v[3] == 16); - UNIT_ASSERT(v[4] == 25); - UNIT_ASSERT(v[5] == 36); + UNIT_ASSERT_VALUES_EQUAL(v.size(), 6u); + UNIT_ASSERT(v[0] == 1); + UNIT_ASSERT(v[1] == 4); + UNIT_ASSERT(v[2] == 9); + UNIT_ASSERT(v[3] == 16); + UNIT_ASSERT(v[4] == 25); + UNIT_ASSERT(v[5] == 36); - vit = v.erase(v.begin()); // Erase first element. - UNIT_ASSERT(*vit == 4); + vit = v.erase(v.begin()); // Erase first element. + UNIT_ASSERT(*vit == 4); - UNIT_ASSERT(v.size() == 5); - UNIT_ASSERT(v[0] == 4); - UNIT_ASSERT(v[1] == 9); - UNIT_ASSERT(v[2] == 16); - UNIT_ASSERT(v[3] == 25); - UNIT_ASSERT(v[4] == 36); + UNIT_ASSERT(v.size() == 5); + UNIT_ASSERT(v[0] == 4); + UNIT_ASSERT(v[1] == 9); + UNIT_ASSERT(v[2] == 16); + UNIT_ASSERT(v[3] == 25); + UNIT_ASSERT(v[4] == 36); - vit = v.erase(v.end() - 1); // Erase last element. - UNIT_ASSERT(vit == v.end()); + vit = v.erase(v.end() - 1); // Erase last element. + UNIT_ASSERT(vit == v.end()); - UNIT_ASSERT(v.size() == 4); - UNIT_ASSERT(v[0] == 4); - UNIT_ASSERT(v[1] == 9); - UNIT_ASSERT(v[2] == 16); - UNIT_ASSERT(v[3] == 25); + UNIT_ASSERT(v.size() == 4); + UNIT_ASSERT(v[0] == 4); + UNIT_ASSERT(v[1] == 9); + UNIT_ASSERT(v[2] == 16); + UNIT_ASSERT(v[3] == 25); - v.erase(v.begin() + 1, v.end() - 1); // Erase all but first and last. + v.erase(v.begin() + 1, v.end() - 1); // Erase all but first and last. - UNIT_ASSERT(v.size() == 2); - UNIT_ASSERT(v[0] == 4); - UNIT_ASSERT(v[1] == 25); - } + UNIT_ASSERT(v.size() == 2); + UNIT_ASSERT(v[0] == 4); + UNIT_ASSERT(v[1] == 25); + } - void Test7() { - int array1[] = {1, 4, 25}; - int array2[] = {9, 16}; + void Test7() { + int array1[] = {1, 4, 25}; + int array2[] = {9, 16}; - typedef NPagedVector::TPagedVector<int, 3> TVectorType; + typedef NPagedVector::TPagedVector<int, 3> TVectorType; - TVectorType v(array1, array1 + 3); - TVectorType::iterator vit; - vit = v.insert(v.begin(), 0); // Insert before first element. - UNIT_ASSERT_VALUES_EQUAL(*vit, 0); - - vit = v.insert(v.end(), 36); // Insert after last element. - UNIT_ASSERT(*vit == 36); - - UNIT_ASSERT(v.size() == 5); - UNIT_ASSERT(v[0] == 0); - UNIT_ASSERT(v[1] == 1); - UNIT_ASSERT(v[2] == 4); - UNIT_ASSERT(v[3] == 25); - UNIT_ASSERT(v[4] == 36); - - // Insert contents of array2 before fourth element. - v.insert(v.begin() + 3, array2, array2 + 2); - - UNIT_ASSERT(v.size() == 7); - - UNIT_ASSERT(v[0] == 0); - UNIT_ASSERT(v[1] == 1); - UNIT_ASSERT(v[2] == 4); - UNIT_ASSERT(v[3] == 9); - UNIT_ASSERT(v[4] == 16); - UNIT_ASSERT(v[5] == 25); - UNIT_ASSERT(v[6] == 36); - - v.clear(); - UNIT_ASSERT(v.empty()); - } - - void TestAt() { - using NPagedVector::TPagedVector; - TPagedVector<int, 3> v; - TPagedVector<int, 3> const& cv = v; - - v.push_back(10); - UNIT_ASSERT(v.at(0) == 10); - v.at(0) = 20; - UNIT_ASSERT(cv.at(0) == 20); - - for (;;) { - try { - v.at(1) = 20; - UNIT_ASSERT(false); - } catch (std::out_of_range const&) { - return; - } catch (...) { - UNIT_ASSERT(false); + TVectorType v(array1, array1 + 3); + TVectorType::iterator vit; + vit = v.insert(v.begin(), 0); // Insert before first element. + UNIT_ASSERT_VALUES_EQUAL(*vit, 0); + + vit = v.insert(v.end(), 36); // Insert after last element. + UNIT_ASSERT(*vit == 36); + + UNIT_ASSERT(v.size() == 5); + UNIT_ASSERT(v[0] == 0); + UNIT_ASSERT(v[1] == 1); + UNIT_ASSERT(v[2] == 4); + UNIT_ASSERT(v[3] == 25); + UNIT_ASSERT(v[4] == 36); + + // Insert contents of array2 before fourth element. + v.insert(v.begin() + 3, array2, array2 + 2); + + UNIT_ASSERT(v.size() == 7); + + UNIT_ASSERT(v[0] == 0); + UNIT_ASSERT(v[1] == 1); + UNIT_ASSERT(v[2] == 4); + UNIT_ASSERT(v[3] == 9); + UNIT_ASSERT(v[4] == 16); + UNIT_ASSERT(v[5] == 25); + UNIT_ASSERT(v[6] == 36); + + v.clear(); + UNIT_ASSERT(v.empty()); + } + + void TestAt() { + using NPagedVector::TPagedVector; + TPagedVector<int, 3> v; + TPagedVector<int, 3> const& cv = v; + + v.push_back(10); + UNIT_ASSERT(v.at(0) == 10); + v.at(0) = 20; + UNIT_ASSERT(cv.at(0) == 20); + + for (;;) { + try { + v.at(1) = 20; + UNIT_ASSERT(false); + } catch (std::out_of_range const&) { + return; + } catch (...) { + UNIT_ASSERT(false); } } - } - - void TestAutoRef() { - using NPagedVector::TPagedVector; - typedef TPagedVector<int, 3> TVec; - TVec ref; - for (int i = 0; i < 5; ++i) { - ref.push_back(i); - } - - TPagedVector<TVec, 3> v_v_int; - v_v_int.push_back(ref); - v_v_int.push_back(v_v_int[0]); - v_v_int.push_back(ref); - v_v_int.push_back(v_v_int[0]); - v_v_int.push_back(v_v_int[0]); - v_v_int.push_back(ref); - - TPagedVector<TVec, 3>::iterator vvit(v_v_int.begin()), vvitEnd(v_v_int.end()); - for (; vvit != vvitEnd; ++vvit) { - UNIT_ASSERT(*vvit == ref); + } + + void TestAutoRef() { + using NPagedVector::TPagedVector; + typedef TPagedVector<int, 3> TVec; + TVec ref; + for (int i = 0; i < 5; ++i) { + ref.push_back(i); + } + + TPagedVector<TVec, 3> v_v_int; + v_v_int.push_back(ref); + v_v_int.push_back(v_v_int[0]); + v_v_int.push_back(ref); + v_v_int.push_back(v_v_int[0]); + v_v_int.push_back(v_v_int[0]); + v_v_int.push_back(ref); + + TPagedVector<TVec, 3>::iterator vvit(v_v_int.begin()), vvitEnd(v_v_int.end()); + for (; vvit != vvitEnd; ++vvit) { + UNIT_ASSERT(*vvit == ref); + } + } + + struct Point { + int x, y; + }; + + struct PointEx: public Point { + PointEx() + : builtFromBase(false) + { } - } - - struct Point { - int x, y; - }; - - struct PointEx: public Point { - PointEx() - : builtFromBase(false) - { - } - PointEx(const Point&) - : builtFromBase(true) - { - } - - bool builtFromBase; - }; - - void TestIterators() { - using NPagedVector::TPagedVector; - TPagedVector<int, 3> vint; - vint.resize(10); - TPagedVector<int, 3> const& crvint = vint; - - UNIT_ASSERT(vint.begin() == vint.begin()); - UNIT_ASSERT(crvint.begin() == vint.begin()); - UNIT_ASSERT(vint.begin() == crvint.begin()); - UNIT_ASSERT(crvint.begin() == crvint.begin()); - - UNIT_ASSERT(vint.begin() != vint.end()); - UNIT_ASSERT(crvint.begin() != vint.end()); - UNIT_ASSERT(vint.begin() != crvint.end()); - UNIT_ASSERT(crvint.begin() != crvint.end()); - - UNIT_ASSERT(vint.rbegin() == vint.rbegin()); - // Not Standard: - //UNIT_ASSERT(vint.rbegin() == crvint.rbegin()); - //UNIT_ASSERT(crvint.rbegin() == vint.rbegin()); - UNIT_ASSERT(crvint.rbegin() == crvint.rbegin()); - - UNIT_ASSERT(vint.rbegin() != vint.rend()); - // Not Standard: - //UNIT_ASSERT(vint.rbegin() != crvint.rend()); - //UNIT_ASSERT(crvint.rbegin() != vint.rend()); - UNIT_ASSERT(crvint.rbegin() != crvint.rend()); - } - - /* This test check a potential issue with empty base class + PointEx(const Point&) + : builtFromBase(true) + { + } + + bool builtFromBase; + }; + + void TestIterators() { + using NPagedVector::TPagedVector; + TPagedVector<int, 3> vint; + vint.resize(10); + TPagedVector<int, 3> const& crvint = vint; + + UNIT_ASSERT(vint.begin() == vint.begin()); + UNIT_ASSERT(crvint.begin() == vint.begin()); + UNIT_ASSERT(vint.begin() == crvint.begin()); + UNIT_ASSERT(crvint.begin() == crvint.begin()); + + UNIT_ASSERT(vint.begin() != vint.end()); + UNIT_ASSERT(crvint.begin() != vint.end()); + UNIT_ASSERT(vint.begin() != crvint.end()); + UNIT_ASSERT(crvint.begin() != crvint.end()); + + UNIT_ASSERT(vint.rbegin() == vint.rbegin()); + // Not Standard: + //UNIT_ASSERT(vint.rbegin() == crvint.rbegin()); + //UNIT_ASSERT(crvint.rbegin() == vint.rbegin()); + UNIT_ASSERT(crvint.rbegin() == crvint.rbegin()); + + UNIT_ASSERT(vint.rbegin() != vint.rend()); + // Not Standard: + //UNIT_ASSERT(vint.rbegin() != crvint.rend()); + //UNIT_ASSERT(crvint.rbegin() != vint.rend()); + UNIT_ASSERT(crvint.rbegin() != crvint.rend()); + } + + /* This test check a potential issue with empty base class * optimization. Some compilers (VC6) do not implement it * correctly resulting ina wrong behavior. */ - void TestEbo() { - using NPagedVector::TPagedVector; - // We use heap memory as test failure can corrupt vector internal - // representation making executable crash on vector destructor invocation. - // We prefer a simple memory leak, internal corruption should be reveal - // by size or capacity checks. - typedef TPagedVector<int, 3> V; - V* pv1 = new V; + void TestEbo() { + using NPagedVector::TPagedVector; + // We use heap memory as test failure can corrupt vector internal + // representation making executable crash on vector destructor invocation. + // We prefer a simple memory leak, internal corruption should be reveal + // by size or capacity checks. + typedef TPagedVector<int, 3> V; + V* pv1 = new V; - pv1->resize(1); - pv1->at(0) = 1; + pv1->resize(1); + pv1->at(0) = 1; - V* pv2 = new V; + V* pv2 = new V; - pv2->resize(10); - for (int i = 0; i < 10; ++i) - pv2->at(i) = 2; + pv2->resize(10); + for (int i = 0; i < 10; ++i) + pv2->at(i) = 2; - pv1->swap(*pv2); + pv1->swap(*pv2); - UNIT_ASSERT(pv1->size() == 10); - UNIT_ASSERT((*pv1)[5] == 2); + UNIT_ASSERT(pv1->size() == 10); + UNIT_ASSERT((*pv1)[5] == 2); - UNIT_ASSERT(pv2->size() == 1); - UNIT_ASSERT((*pv2)[0] == 1); + UNIT_ASSERT(pv2->size() == 1); + UNIT_ASSERT((*pv2)[0] == 1); - delete pv2; - delete pv1; - } + delete pv2; + delete pv1; + } }; UNIT_TEST_SUITE_REGISTRATION(TPagedVectorTest); diff --git a/library/cpp/containers/paged_vector/ut/ya.make b/library/cpp/containers/paged_vector/ut/ya.make index 69054531b1..74cfe5fb4a 100644 --- a/library/cpp/containers/paged_vector/ut/ya.make +++ b/library/cpp/containers/paged_vector/ut/ya.make @@ -1,13 +1,13 @@ -UNITTEST() - -OWNER(velavokr) - -PEERDIR( +UNITTEST() + +OWNER(velavokr) + +PEERDIR( library/cpp/containers/paged_vector -) - -SRCS( - paged_vector_ut.cpp -) - -END() +) + +SRCS( + paged_vector_ut.cpp +) + +END() diff --git a/library/cpp/containers/sorted_vector/sorted_vector.cpp b/library/cpp/containers/sorted_vector/sorted_vector.cpp index 806efe371a..56aaf69dde 100644 --- a/library/cpp/containers/sorted_vector/sorted_vector.cpp +++ b/library/cpp/containers/sorted_vector/sorted_vector.cpp @@ -1 +1 @@ -#include "sorted_vector.h" +#include "sorted_vector.h" diff --git a/library/cpp/containers/sorted_vector/sorted_vector.h b/library/cpp/containers/sorted_vector/sorted_vector.h index 17a1fddcc5..123539af9e 100644 --- a/library/cpp/containers/sorted_vector/sorted_vector.h +++ b/library/cpp/containers/sorted_vector/sorted_vector.h @@ -1,85 +1,85 @@ -#pragma once - -#include <util/system/defaults.h> -#include <util/generic/hash.h> -#include <util/generic/vector.h> -#include <util/generic/algorithm.h> +#pragma once + +#include <util/system/defaults.h> +#include <util/generic/hash.h> +#include <util/generic/vector.h> +#include <util/generic/algorithm.h> #include <util/generic/mapfindptr.h> -#include <util/ysaveload.h> +#include <util/ysaveload.h> #include <utility> - + #include <initializer_list> -namespace NSorted { - namespace NPrivate { +namespace NSorted { + namespace NPrivate { template <class TPredicate> struct TEqual { template<typename TValueType1, typename TValueType2> inline bool operator()(const TValueType1& l, const TValueType2& r) const { - TPredicate comp; - return comp(l, r) == comp(r, l); - } - }; - + TPredicate comp; + return comp(l, r) == comp(r, l); + } + }; + template <typename TValueType, class TPredicate, class TKeyExtractor> struct TKeyCompare { - inline bool operator()(const TValueType& l, const TValueType& r) const { - TKeyExtractor extractKey; - return TPredicate()(extractKey(l), extractKey(r)); - } + inline bool operator()(const TValueType& l, const TValueType& r) const { + TKeyExtractor extractKey; + return TPredicate()(extractKey(l), extractKey(r)); + } template<typename TKeyType> - inline bool operator()(const TKeyType& l, const TValueType& r) const { - return TPredicate()(l, TKeyExtractor()(r)); - } + inline bool operator()(const TKeyType& l, const TValueType& r) const { + return TPredicate()(l, TKeyExtractor()(r)); + } template<typename TKeyType> - inline bool operator()(const TValueType& l, const TKeyType& r) const { - return TPredicate()(TKeyExtractor()(l), r); - } - }; - - template <typename TValueType, class TPredicate> + inline bool operator()(const TValueType& l, const TKeyType& r) const { + return TPredicate()(TKeyExtractor()(l), r); + } + }; + + template <typename TValueType, class TPredicate> struct TKeyCompare<TValueType, TPredicate, TIdentity> { template <typename TValueType1, typename TValueType2> inline bool operator()(const TValueType1& l, const TValueType2& r) const { - return TPredicate()(l, r); - } - }; - - } - - // Sorted vector, which is order by the key. The key is extracted from the value by the provided key-extractor - template <typename TValueType, typename TKeyType = TValueType, class TKeyExtractor = TIdentity, + return TPredicate()(l, r); + } + }; + + } + + // Sorted vector, which is order by the key. The key is extracted from the value by the provided key-extractor + template <typename TValueType, typename TKeyType = TValueType, class TKeyExtractor = TIdentity, class TPredicate = TLess<TKeyType>, class A = std::allocator<TValueType>> class TSortedVector: public TVector<TValueType, A> { - private: + private: typedef TVector<TValueType, A> TBase; typedef NPrivate::TKeyCompare<TValueType, TPredicate, TKeyExtractor> TKeyCompare; typedef NPrivate::TEqual<TKeyCompare> TValueEqual; typedef NPrivate::TEqual<TPredicate> TKeyEqual; - - public: - typedef TValueType value_type; - typedef TKeyType key_type; - typedef typename TBase::iterator iterator; - typedef typename TBase::const_iterator const_iterator; - typedef typename TBase::size_type size_type; - - public: - inline TSortedVector() - : TBase() - { - } - - inline explicit TSortedVector(size_type count) - : TBase(count) - { - } - - inline TSortedVector(size_type count, const value_type& val) - : TBase(count, val) - { - } - + + public: + typedef TValueType value_type; + typedef TKeyType key_type; + typedef typename TBase::iterator iterator; + typedef typename TBase::const_iterator const_iterator; + typedef typename TBase::size_type size_type; + + public: + inline TSortedVector() + : TBase() + { + } + + inline explicit TSortedVector(size_type count) + : TBase(count) + { + } + + inline TSortedVector(size_type count, const value_type& val) + : TBase(count, val) + { + } + inline TSortedVector(std::initializer_list<value_type> il) : TBase(il) { @@ -92,293 +92,293 @@ namespace NSorted { Sort(); } - template <class TIter> - inline TSortedVector(TIter first, TIter last) - : TBase(first, last) - { - Sort(); - } - - // Inserts non-unique value in the proper position according to the key-sort order. - // Returns iterator, which points to the inserted value - inline iterator Insert(const value_type& value) { - return TBase::insert(LowerBound(TKeyExtractor()(value)), value); - } - - // STL-compatible synonym + template <class TIter> + inline TSortedVector(TIter first, TIter last) + : TBase(first, last) + { + Sort(); + } + + // Inserts non-unique value in the proper position according to the key-sort order. + // Returns iterator, which points to the inserted value + inline iterator Insert(const value_type& value) { + return TBase::insert(LowerBound(TKeyExtractor()(value)), value); + } + + // STL-compatible synonym Y_FORCE_INLINE iterator insert(const value_type& value) { - return this->Insert(value); - } - - // Inserts non-unique value range in the proper position according to the key-sort order. - template <class TIter> - inline void Insert(TIter first, TIter last) { - TBase::insert(TBase::end(), first, last); - Sort(); - } - - // STL-compatible synonym - template <class TIter> + return this->Insert(value); + } + + // Inserts non-unique value range in the proper position according to the key-sort order. + template <class TIter> + inline void Insert(TIter first, TIter last) { + TBase::insert(TBase::end(), first, last); + Sort(); + } + + // STL-compatible synonym + template <class TIter> Y_FORCE_INLINE void insert(TIter first, TIter last) { - this->Insert(first, last); - } - - // Inserts unique value in the proper position according to the key-sort order, - // if the value with the same key doesn't exist. Returns <iterator, bool> pair, - // where the first member is the pointer to the inserted/existing value, and the - // second member indicates either the value is inserted or not. + this->Insert(first, last); + } + + // Inserts unique value in the proper position according to the key-sort order, + // if the value with the same key doesn't exist. Returns <iterator, bool> pair, + // where the first member is the pointer to the inserted/existing value, and the + // second member indicates either the value is inserted or not. inline std::pair<iterator, bool> InsertUnique(const value_type& value) { - iterator i = LowerBound(TKeyExtractor()(value)); - if (i == TBase::end() || !TValueEqual()(*i, value)) + iterator i = LowerBound(TKeyExtractor()(value)); + if (i == TBase::end() || !TValueEqual()(*i, value)) return std::pair<iterator, bool>(TBase::insert(i, value), true); - else + else return std::pair<iterator, bool>(i, false); - } - - // STL-compatible synonym + } + + // STL-compatible synonym Y_FORCE_INLINE std::pair<iterator, bool> insert_unique(const value_type& value) { - return this->InsertUnique(value); - } - - // Inserts unique value range in the proper position according to the key-sort order. - template <class TIter> - inline void InsertUnique(TIter first, TIter last) { - TBase::insert(TBase::end(), first, last); - Sort(); - MakeUnique(); - } - - // STL-compatible synonym - template <class TIter> + return this->InsertUnique(value); + } + + // Inserts unique value range in the proper position according to the key-sort order. + template <class TIter> + inline void InsertUnique(TIter first, TIter last) { + TBase::insert(TBase::end(), first, last); + Sort(); + MakeUnique(); + } + + // STL-compatible synonym + template <class TIter> Y_FORCE_INLINE void insert_unique(TIter first, TIter last) { - this->InsertUnique(first, last); - } - - // Inserts unique value in the proper position according to the key-sort order. - // If the value with the same key already exists, then it is replaced with the new one. - // Returns iterator, which points to the inserted value - inline iterator InsertOrReplace(const value_type& value) { - iterator i = ::LowerBound(TBase::begin(), TBase::end(), value, TKeyCompare()); - if (i == TBase::end() || !TValueEqual()(*i, value)) - return TBase::insert(i, value); - else - return TBase::insert(TBase::erase(i), value); - } - - // STL-compatible synonym + this->InsertUnique(first, last); + } + + // Inserts unique value in the proper position according to the key-sort order. + // If the value with the same key already exists, then it is replaced with the new one. + // Returns iterator, which points to the inserted value + inline iterator InsertOrReplace(const value_type& value) { + iterator i = ::LowerBound(TBase::begin(), TBase::end(), value, TKeyCompare()); + if (i == TBase::end() || !TValueEqual()(*i, value)) + return TBase::insert(i, value); + else + return TBase::insert(TBase::erase(i), value); + } + + // STL-compatible synonym Y_FORCE_INLINE iterator insert_or_replace(const value_type& value) { - return this->InsertOrReplace(value); - } - + return this->InsertOrReplace(value); + } + Y_FORCE_INLINE void Sort() { - ::Sort(TBase::begin(), TBase::end(), TKeyCompare()); - } - - // STL-compatible synonym + ::Sort(TBase::begin(), TBase::end(), TKeyCompare()); + } + + // STL-compatible synonym Y_FORCE_INLINE void sort() { - this->Sort(); - } - + this->Sort(); + } + Y_FORCE_INLINE void Sort(iterator from, iterator to) { - ::Sort(from, to, TKeyCompare()); - } - - // STL-compatible synonym + ::Sort(from, to, TKeyCompare()); + } + + // STL-compatible synonym Y_FORCE_INLINE void sort(iterator from, iterator to) { - this->Sort(from, to); - } - - inline void MakeUnique() { - TBase::erase(::Unique(TBase::begin(), TBase::end(), TValueEqual()), TBase::end()); - } - - // STL-compatible synonym + this->Sort(from, to); + } + + inline void MakeUnique() { + TBase::erase(::Unique(TBase::begin(), TBase::end(), TValueEqual()), TBase::end()); + } + + // STL-compatible synonym Y_FORCE_INLINE void make_unique() { - this->MakeUnique(); - } - + this->MakeUnique(); + } + template<class K> inline const_iterator Find(const K& key) const { - const_iterator i = LowerBound(key); - if (i == TBase::end() || !TKeyEqual()(TKeyExtractor()(*i), key)) - return TBase::end(); - else - return i; - } - - // STL-compatible synonym + const_iterator i = LowerBound(key); + if (i == TBase::end() || !TKeyEqual()(TKeyExtractor()(*i), key)) + return TBase::end(); + else + return i; + } + + // STL-compatible synonym template<class K> Y_FORCE_INLINE const_iterator find(const K& key) const { - return this->Find(key); - } - + return this->Find(key); + } + template<class K> inline iterator Find(const K& key) { - iterator i = LowerBound(key); - if (i == TBase::end() || !TKeyEqual()(TKeyExtractor()(*i), key)) - return TBase::end(); - else - return i; - } - - // STL-compatible synonym + iterator i = LowerBound(key); + if (i == TBase::end() || !TKeyEqual()(TKeyExtractor()(*i), key)) + return TBase::end(); + else + return i; + } + + // STL-compatible synonym template<class K> Y_FORCE_INLINE iterator find(const K& key) { - return this->Find(key); - } - + return this->Find(key); + } + template<class K> Y_FORCE_INLINE bool Has(const K& key) const { - return this->find(key) != TBase::end(); - } - + return this->find(key) != TBase::end(); + } + template<class K> Y_FORCE_INLINE bool has(const K& key) const { - return this->Has(key); - } - + return this->Has(key); + } + template<class K> Y_FORCE_INLINE iterator LowerBound(const K& key) { - return ::LowerBound(TBase::begin(), TBase::end(), key, TKeyCompare()); - } - - // STL-compatible synonym + return ::LowerBound(TBase::begin(), TBase::end(), key, TKeyCompare()); + } + + // STL-compatible synonym template<class K> Y_FORCE_INLINE iterator lower_bound(const K& key) { - return this->LowerBound(key); - } - + return this->LowerBound(key); + } + template<class K> Y_FORCE_INLINE const_iterator LowerBound(const K& key) const { - return ::LowerBound(TBase::begin(), TBase::end(), key, TKeyCompare()); - } - - // STL-compatible synonym + return ::LowerBound(TBase::begin(), TBase::end(), key, TKeyCompare()); + } + + // STL-compatible synonym template<class K> Y_FORCE_INLINE const_iterator lower_bound(const K& key) const { - return this->LowerBound(key); - } - + return this->LowerBound(key); + } + template<class K> Y_FORCE_INLINE iterator UpperBound(const K& key) { - return ::UpperBound(TBase::begin(), TBase::end(), key, TKeyCompare()); - } - - // STL-compatible synonym + return ::UpperBound(TBase::begin(), TBase::end(), key, TKeyCompare()); + } + + // STL-compatible synonym template<class K> Y_FORCE_INLINE iterator upper_bound(const K& key) { - return this->UpperBound(key); - } - + return this->UpperBound(key); + } + template<class K> Y_FORCE_INLINE const_iterator UpperBound(const K& key) const { - return ::UpperBound(TBase::begin(), TBase::end(), key, TKeyCompare()); - } - - // STL-compatible synonym + return ::UpperBound(TBase::begin(), TBase::end(), key, TKeyCompare()); + } + + // STL-compatible synonym template<class K> Y_FORCE_INLINE const_iterator upper_bound(const K& key) const { - return this->UpperBound(key); - } - + return this->UpperBound(key); + } + template<class K> Y_FORCE_INLINE std::pair<iterator, iterator> EqualRange(const K& key) { - return std::equal_range(TBase::begin(), TBase::end(), key, TKeyCompare()); - } - - // STL-compatible synonym + return std::equal_range(TBase::begin(), TBase::end(), key, TKeyCompare()); + } + + // STL-compatible synonym template<class K> Y_FORCE_INLINE std::pair<iterator, iterator> equal_range(const K& key) { - return this->EqualRange(key); - } - + return this->EqualRange(key); + } + template<class K> Y_FORCE_INLINE std::pair<const_iterator, const_iterator> EqualRange(const K& key) const { - return std::equal_range(TBase::begin(), TBase::end(), key, TKeyCompare()); - } - - // STL-compatible synonym + return std::equal_range(TBase::begin(), TBase::end(), key, TKeyCompare()); + } + + // STL-compatible synonym template<class K> Y_FORCE_INLINE std::pair<const_iterator, const_iterator> equal_range(const K& key) const { - return this->EqualRange(key); - } - + return this->EqualRange(key); + } + template<class K> inline void Erase(const K& key) { std::pair<iterator, iterator> res = EqualRange(key); - TBase::erase(res.first, res.second); - } - - // STL-compatible synonym + TBase::erase(res.first, res.second); + } + + // STL-compatible synonym Y_FORCE_INLINE void erase(const key_type& key) { - this->Erase(key); - } - + this->Erase(key); + } + template<class K> inline size_t count(const K& key) const { const std::pair<const_iterator, const_iterator> range = this->EqualRange(key); - return std::distance(range.first, range.second); - } - - using TBase::erase; - }; - + return std::distance(range.first, range.second); + } + + using TBase::erase; + }; + // The simplified map (a.k.a TFlatMap, flat_map), which is implemented by the sorted-vector. - // This structure has the side-effect: if you keep a reference to an existing element - // and then inserts a new one, the existing reference can be broken (due to reallocation). - // Please keep this in mind when using this structure. + // This structure has the side-effect: if you keep a reference to an existing element + // and then inserts a new one, the existing reference can be broken (due to reallocation). + // Please keep this in mind when using this structure. template <typename TKeyType, typename TValueType, class TPredicate = TLess<TKeyType>, class A = std::allocator<TValueType>> class TSimpleMap: public TSortedVector<std::pair<TKeyType, TValueType>, TKeyType, TSelect1st, TPredicate, A>, public TMapOps<TSimpleMap<TKeyType, TValueType, TPredicate, A>> { - private: + private: typedef TSortedVector<std::pair<TKeyType, TValueType>, TKeyType, TSelect1st, TPredicate, A> TBase; - - public: - typedef typename TBase::value_type value_type; - typedef typename TBase::key_type key_type; - typedef typename TBase::iterator iterator; - typedef typename TBase::const_iterator const_iterator; - typedef typename TBase::size_type size_type; - - public: - inline TSimpleMap() - : TBase() - { - } - - template <class TIter> - inline TSimpleMap(TIter first, TIter last) - : TBase(first, last) - { - TBase::MakeUnique(); - } - + + public: + typedef typename TBase::value_type value_type; + typedef typename TBase::key_type key_type; + typedef typename TBase::iterator iterator; + typedef typename TBase::const_iterator const_iterator; + typedef typename TBase::size_type size_type; + + public: + inline TSimpleMap() + : TBase() + { + } + + template <class TIter> + inline TSimpleMap(TIter first, TIter last) + : TBase(first, last) + { + TBase::MakeUnique(); + } + inline TSimpleMap(std::initializer_list<value_type> il) : TBase(il) { TBase::MakeUnique(); } - inline TValueType& Get(const TKeyType& key) { - typename TBase::iterator i = TBase::LowerBound(key); - if (i == TBase::end() || key != i->first) + inline TValueType& Get(const TKeyType& key) { + typename TBase::iterator i = TBase::LowerBound(key); + if (i == TBase::end() || key != i->first) return TVector<std::pair<TKeyType, TValueType>, A>::insert(i, std::make_pair(key, TValueType()))->second; - else - return i->second; - } - + else + return i->second; + } + template<class K> inline const TValueType& Get(const K& key, const TValueType& def) const { - typename TBase::const_iterator i = TBase::Find(key); - return i != TBase::end() ? i->second : def; - } - + typename TBase::const_iterator i = TBase::Find(key); + return i != TBase::end() ? i->second : def; + } + template<class K> Y_FORCE_INLINE TValueType& operator[](const K& key) { - return Get(key); - } + return Get(key); + } template<class K> const TValueType& at(const K& key) const { @@ -395,98 +395,98 @@ namespace NSorted { return const_cast<TValueType&>( const_cast<const TSimpleMap<TKeyType, TValueType, TPredicate, A>*>(this)->at(key)); } - }; - + }; + // The simplified set (a.k.a TFlatSet, flat_set), which is implemented by the sorted-vector. - // This structure has the same side-effect as TSimpleMap. - // The value type must have TValueType(TKeyType) constructor in order to use [] operator - template <typename TValueType, typename TKeyType = TValueType, class TKeyExtractor = TIdentity, + // This structure has the same side-effect as TSimpleMap. + // The value type must have TValueType(TKeyType) constructor in order to use [] operator + template <typename TValueType, typename TKeyType = TValueType, class TKeyExtractor = TIdentity, class TPredicate = TLess<TKeyType>, class A = std::allocator<TValueType>> - class TSimpleSet: public TSortedVector<TValueType, TKeyType, TKeyExtractor, TPredicate, A> { - private: - typedef TSortedVector<TValueType, TKeyType, TKeyExtractor, TPredicate, A> TBase; - - public: - typedef typename TBase::value_type value_type; - typedef typename TBase::key_type key_type; - typedef typename TBase::iterator iterator; - typedef typename TBase::const_iterator const_iterator; - typedef typename TBase::size_type size_type; + class TSimpleSet: public TSortedVector<TValueType, TKeyType, TKeyExtractor, TPredicate, A> { + private: + typedef TSortedVector<TValueType, TKeyType, TKeyExtractor, TPredicate, A> TBase; + + public: + typedef typename TBase::value_type value_type; + typedef typename TBase::key_type key_type; + typedef typename TBase::iterator iterator; + typedef typename TBase::const_iterator const_iterator; + typedef typename TBase::size_type size_type; typedef NPrivate::TEqual<TPredicate> TKeyEqual; - - public: - inline TSimpleSet() - : TBase() - { - } - - template <class TIter> - inline TSimpleSet(TIter first, TIter last) - : TBase(first, last) - { - TBase::MakeUnique(); - } - + + public: + inline TSimpleSet() + : TBase() + { + } + + template <class TIter> + inline TSimpleSet(TIter first, TIter last) + : TBase(first, last) + { + TBase::MakeUnique(); + } + inline TSimpleSet(std::initializer_list<value_type> il) : TBase(il) { TBase::MakeUnique(); } - // The method expects that there is a TValueType(TKeyType) constructor available - inline TValueType& Get(const TKeyType& key) { - typename TBase::iterator i = TBase::LowerBound(key); - if (i == TBase::end() || !TKeyEqual()(TKeyExtractor()(*i), key)) + // The method expects that there is a TValueType(TKeyType) constructor available + inline TValueType& Get(const TKeyType& key) { + typename TBase::iterator i = TBase::LowerBound(key); + if (i == TBase::end() || !TKeyEqual()(TKeyExtractor()(*i), key)) i = TVector<TValueType, A>::insert(i, TValueType(key)); - return *i; - } - + return *i; + } + template<class K> inline const TValueType& Get(const K& key, const TValueType& def) const { - typename TBase::const_iterator i = TBase::Find(key); - return i != TBase::end() ? *i : def; - } - + typename TBase::const_iterator i = TBase::Find(key); + return i != TBase::end() ? *i : def; + } + template<class K> Y_FORCE_INLINE TValueType& operator[](const K& key) { - return Get(key); - } - - // Inserts value with unique key. Returns <iterator, bool> pair, - // where the first member is the pointer to the inserted/existing value, and the - // second member indicates either the value is inserted or not. + return Get(key); + } + + // Inserts value with unique key. Returns <iterator, bool> pair, + // where the first member is the pointer to the inserted/existing value, and the + // second member indicates either the value is inserted or not. Y_FORCE_INLINE std::pair<iterator, bool> Insert(const TValueType& value) { - return TBase::InsertUnique(value); - } - - // STL-compatible synonym + return TBase::InsertUnique(value); + } + + // STL-compatible synonym Y_FORCE_INLINE std::pair<iterator, bool> insert(const TValueType& value) { - return TBase::InsertUnique(value); - } - - // Inserts value range with unique keys. - template <class TIter> + return TBase::InsertUnique(value); + } + + // Inserts value range with unique keys. + template <class TIter> Y_FORCE_INLINE void Insert(TIter first, TIter last) { - TBase::InsertUnique(first, last); - } - - // STL-compatible synonym - template <class TIter> + TBase::InsertUnique(first, last); + } + + // STL-compatible synonym + template <class TIter> Y_FORCE_INLINE void insert(TIter first, TIter last) { - TBase::InsertUnique(first, last); - } - }; - -} - -template <typename V, typename K, class E, class P, class A> -class TSerializer<NSorted::TSortedVector<V, K, E, P, A>>: public TVectorSerializer<NSorted::TSortedVector<V, K, E, P, A>> { -}; - -template <typename K, typename V, class P, class A> -class TSerializer<NSorted::TSimpleMap<K, V, P, A>>: public TVectorSerializer<NSorted::TSimpleMap<K, V, P, A>> { -}; - -template <typename V, typename K, class E, class P, class A> -class TSerializer<NSorted::TSimpleSet<V, K, E, P, A>>: public TVectorSerializer<NSorted::TSimpleSet<V, K, E, P, A>> { -}; + TBase::InsertUnique(first, last); + } + }; + +} + +template <typename V, typename K, class E, class P, class A> +class TSerializer<NSorted::TSortedVector<V, K, E, P, A>>: public TVectorSerializer<NSorted::TSortedVector<V, K, E, P, A>> { +}; + +template <typename K, typename V, class P, class A> +class TSerializer<NSorted::TSimpleMap<K, V, P, A>>: public TVectorSerializer<NSorted::TSimpleMap<K, V, P, A>> { +}; + +template <typename V, typename K, class E, class P, class A> +class TSerializer<NSorted::TSimpleSet<V, K, E, P, A>>: public TVectorSerializer<NSorted::TSimpleSet<V, K, E, P, A>> { +}; diff --git a/library/cpp/containers/sorted_vector/ya.make b/library/cpp/containers/sorted_vector/ya.make index 78f1c1494e..1975c5dc90 100644 --- a/library/cpp/containers/sorted_vector/ya.make +++ b/library/cpp/containers/sorted_vector/ya.make @@ -1,11 +1,11 @@ -LIBRARY() - -OWNER(udovichenko-r) - -SRCS( - sorted_vector.cpp -) - -END() +LIBRARY() + +OWNER(udovichenko-r) + +SRCS( + sorted_vector.cpp +) + +END() RECURSE_FOR_TESTS(ut) diff --git a/library/cpp/containers/stack_array/range_ops.cpp b/library/cpp/containers/stack_array/range_ops.cpp index ea47fe6777..f1b5e3af0d 100644 --- a/library/cpp/containers/stack_array/range_ops.cpp +++ b/library/cpp/containers/stack_array/range_ops.cpp @@ -1 +1 @@ -#include "range_ops.h" +#include "range_ops.h" diff --git a/library/cpp/containers/stack_array/range_ops.h b/library/cpp/containers/stack_array/range_ops.h index dfb95ab401..1d40341aa1 100644 --- a/library/cpp/containers/stack_array/range_ops.h +++ b/library/cpp/containers/stack_array/range_ops.h @@ -1,52 +1,52 @@ -#pragma once - -#include <util/generic/typetraits.h> - -#include <new> - -namespace NRangeOps { - template <class T, bool isTrivial> - struct TRangeOpsBase { +#pragma once + +#include <util/generic/typetraits.h> + +#include <new> + +namespace NRangeOps { + template <class T, bool isTrivial> + struct TRangeOpsBase { static inline void DestroyRange(T* b, T* e) noexcept { - while (e > b) { - (--e)->~T(); - } - } - - static inline void InitializeRange(T* b, T* e) { - T* c = b; - - try { - for (; c < e; ++c) { - new (c) T(); - } - } catch (...) { - DestroyRange(b, c); - - throw; - } - } - }; - - template <class T> - struct TRangeOpsBase<T, true> { + while (e > b) { + (--e)->~T(); + } + } + + static inline void InitializeRange(T* b, T* e) { + T* c = b; + + try { + for (; c < e; ++c) { + new (c) T(); + } + } catch (...) { + DestroyRange(b, c); + + throw; + } + } + }; + + template <class T> + struct TRangeOpsBase<T, true> { static inline void DestroyRange(T*, T*) noexcept { - } - + } + static inline void InitializeRange(T*, T*) noexcept { - } - }; - - template <class T> - using TRangeOps = TRangeOpsBase<T, TTypeTraits<T>::IsPod>; - - template <class T> + } + }; + + template <class T> + using TRangeOps = TRangeOpsBase<T, TTypeTraits<T>::IsPod>; + + template <class T> static inline void DestroyRange(T* b, T* e) noexcept { - TRangeOps<T>::DestroyRange(b, e); - } - - template <class T> - static inline void InitializeRange(T* b, T* e) { - TRangeOps<T>::InitializeRange(b, e); - } -} + TRangeOps<T>::DestroyRange(b, e); + } + + template <class T> + static inline void InitializeRange(T* b, T* e) { + TRangeOps<T>::InitializeRange(b, e); + } +} diff --git a/library/cpp/containers/stack_array/stack_array.cpp b/library/cpp/containers/stack_array/stack_array.cpp index d579328128..68e8b097ba 100644 --- a/library/cpp/containers/stack_array/stack_array.cpp +++ b/library/cpp/containers/stack_array/stack_array.cpp @@ -1 +1 @@ -#include "stack_array.h" +#include "stack_array.h" diff --git a/library/cpp/containers/stack_array/stack_array.h b/library/cpp/containers/stack_array/stack_array.h index 105189de06..28e49bfc3c 100644 --- a/library/cpp/containers/stack_array/stack_array.h +++ b/library/cpp/containers/stack_array/stack_array.h @@ -1,11 +1,11 @@ -#pragma once - -#include "range_ops.h" - +#pragma once + +#include "range_ops.h" + #include <util/generic/array_ref.h> #include <util/system/defaults.h> /* For alloca. */ - -namespace NStackArray { + +namespace NStackArray { /** * A stack-allocated array. Should be used instead of � variable length * arrays that are not part of C++ standard. @@ -21,20 +21,20 @@ namespace NStackArray { * * Note that it is generally a *VERY BAD* idea to use this in inline methods * as those might be called from a loop, and then stack overflow is in the cards. - */ - template <class T> + */ + template <class T> class TStackArray: public TArrayRef<T> { - public: - inline TStackArray(void* data, size_t len) + public: + inline TStackArray(void* data, size_t len) : TArrayRef<T>((T*)data, len) - { + { NRangeOps::InitializeRange(this->begin(), this->end()); - } - + } + inline ~TStackArray() { NRangeOps::DestroyRange(this->begin(), this->end()); - } - }; -} - -#define ALLOC_ON_STACK(type, n) alloca(sizeof(type) * (n)), (n) + } + }; +} + +#define ALLOC_ON_STACK(type, n) alloca(sizeof(type) * (n)), (n) diff --git a/library/cpp/containers/stack_array/ut/tests_ut.cpp b/library/cpp/containers/stack_array/ut/tests_ut.cpp index d0c4bfe8c0..3e96384f0e 100644 --- a/library/cpp/containers/stack_array/ut/tests_ut.cpp +++ b/library/cpp/containers/stack_array/ut/tests_ut.cpp @@ -1,94 +1,94 @@ #include <library/cpp/containers/stack_array/stack_array.h> #include <library/cpp/testing/unittest/registar.h> - + Y_UNIT_TEST_SUITE(TestStackArray) { - using namespace NStackArray; - - static inline void* FillWithTrash(void* d, size_t l) { - memset(d, 0xCC, l); - - return d; - } - -#define ALLOC(type, len) FillWithTrash(alloca(sizeof(type) * len), sizeof(type) * len), len - + using namespace NStackArray; + + static inline void* FillWithTrash(void* d, size_t l) { + memset(d, 0xCC, l); + + return d; + } + +#define ALLOC(type, len) FillWithTrash(alloca(sizeof(type) * len), sizeof(type) * len), len + Y_UNIT_TEST(Test1) { - TStackArray<ui32> s(ALLOC(ui32, 10)); - + TStackArray<ui32> s(ALLOC(ui32, 10)); + UNIT_ASSERT_VALUES_EQUAL(s.size(), 10); - + for (size_t i = 0; i < s.size(); ++i) { - UNIT_ASSERT_VALUES_EQUAL(s[i], 0xCCCCCCCC); - } - - for (auto&& x : s) { - UNIT_ASSERT_VALUES_EQUAL(x, 0xCCCCCCCC); - } - + UNIT_ASSERT_VALUES_EQUAL(s[i], 0xCCCCCCCC); + } + + for (auto&& x : s) { + UNIT_ASSERT_VALUES_EQUAL(x, 0xCCCCCCCC); + } + for (size_t i = 0; i < s.size(); ++i) { - s[i] = i; - } - - size_t ss = 0; - - for (auto&& x : s) { - ss += x; - } - - UNIT_ASSERT_VALUES_EQUAL(ss, 45); - } - - static int N1 = 0; - - struct TX1 { - inline TX1() { - ++N1; - } - - inline ~TX1() { - --N1; - } - }; - + s[i] = i; + } + + size_t ss = 0; + + for (auto&& x : s) { + ss += x; + } + + UNIT_ASSERT_VALUES_EQUAL(ss, 45); + } + + static int N1 = 0; + + struct TX1 { + inline TX1() { + ++N1; + } + + inline ~TX1() { + --N1; + } + }; + Y_UNIT_TEST(Test2) { - { - TStackArray<TX1> s(ALLOC(TX1, 10)); - - UNIT_ASSERT_VALUES_EQUAL(N1, 10); - } - - UNIT_ASSERT_VALUES_EQUAL(N1, 0); - } - - static int N2 = 0; - static int N3 = 0; - - struct TX2 { - inline TX2() { - if (N2 >= 5) { - ythrow yexception() << "ups"; - } - - ++N3; - ++N2; - } - - inline ~TX2() { - --N2; - } - }; - + { + TStackArray<TX1> s(ALLOC(TX1, 10)); + + UNIT_ASSERT_VALUES_EQUAL(N1, 10); + } + + UNIT_ASSERT_VALUES_EQUAL(N1, 0); + } + + static int N2 = 0; + static int N3 = 0; + + struct TX2 { + inline TX2() { + if (N2 >= 5) { + ythrow yexception() << "ups"; + } + + ++N3; + ++N2; + } + + inline ~TX2() { + --N2; + } + }; + Y_UNIT_TEST(Test3) { - bool haveException = false; - - try { - TStackArray<TX2> s(ALLOC_ON_STACK(TX2, 10)); - } catch (...) { - haveException = true; - } - - UNIT_ASSERT(haveException); - UNIT_ASSERT_VALUES_EQUAL(N2, 0); - UNIT_ASSERT_VALUES_EQUAL(N3, 5); - } -} + bool haveException = false; + + try { + TStackArray<TX2> s(ALLOC_ON_STACK(TX2, 10)); + } catch (...) { + haveException = true; + } + + UNIT_ASSERT(haveException); + UNIT_ASSERT_VALUES_EQUAL(N2, 0); + UNIT_ASSERT_VALUES_EQUAL(N3, 5); + } +} diff --git a/library/cpp/containers/stack_array/ut/ya.make b/library/cpp/containers/stack_array/ut/ya.make index f224ff2942..7db7340073 100644 --- a/library/cpp/containers/stack_array/ut/ya.make +++ b/library/cpp/containers/stack_array/ut/ya.make @@ -1,9 +1,9 @@ UNITTEST_FOR(library/cpp/containers/stack_array) - -OWNER(pg) - -SRCS( - tests_ut.cpp -) - -END() + +OWNER(pg) + +SRCS( + tests_ut.cpp +) + +END() diff --git a/library/cpp/containers/stack_array/ya.make b/library/cpp/containers/stack_array/ya.make index ad84393f02..9bc0afc66c 100644 --- a/library/cpp/containers/stack_array/ya.make +++ b/library/cpp/containers/stack_array/ya.make @@ -1,10 +1,10 @@ -LIBRARY() - -OWNER(pg) - -SRCS( - range_ops.cpp - stack_array.cpp -) - -END() +LIBRARY() + +OWNER(pg) + +SRCS( + range_ops.cpp + stack_array.cpp +) + +END() diff --git a/library/cpp/containers/stack_vector/stack_vec.h b/library/cpp/containers/stack_vector/stack_vec.h index 0108642da1..fcc5d9a2a5 100644 --- a/library/cpp/containers/stack_vector/stack_vec.h +++ b/library/cpp/containers/stack_vector/stack_vec.h @@ -20,27 +20,27 @@ using TSmallVec = TStackVec<T, 16, true, Alloc>; template <typename T, size_t CountOnStack = 256> using TStackOnlyVec = TStackVec<T, CountOnStack, false>; -namespace NPrivate { - template <class Alloc, class StackAlloc, typename T, typename U> - struct TRebind { +namespace NPrivate { + template <class Alloc, class StackAlloc, typename T, typename U> + struct TRebind { typedef TReboundAllocator<Alloc, U> other; }; - template <class Alloc, class StackAlloc, typename T> - struct TRebind<Alloc, StackAlloc, T, T> { + template <class Alloc, class StackAlloc, typename T> + struct TRebind<Alloc, StackAlloc, T, T> { typedef StackAlloc other; }; template <typename T, size_t CountOnStack, bool UseFallbackAlloc, class Alloc = std::allocator<T>> - class TStackBasedAllocator: public Alloc { + class TStackBasedAllocator: public Alloc { public: typedef TStackBasedAllocator<T, CountOnStack, UseFallbackAlloc, Alloc> TSelf; - using typename Alloc::difference_type; + using typename Alloc::difference_type; using typename Alloc::size_type; - using typename Alloc::value_type; + using typename Alloc::value_type; - template <class U> + template <class U> struct rebind: public ::NPrivate::TRebind<Alloc, TSelf, T, U> { }; @@ -89,7 +89,7 @@ namespace NPrivate { return static_cast<Alloc&>(*this); } }; -} +} template <typename T, size_t CountOnStack, bool UseFallbackAlloc, class Alloc> class TStackVec: public TVector<T, ::NPrivate::TStackBasedAllocator<T, CountOnStack, UseFallbackAlloc, TReboundAllocator<Alloc, T>>> { @@ -98,11 +98,11 @@ private: using TAllocator = typename TBase::allocator_type; public: - using typename TBase::const_iterator; - using typename TBase::const_reverse_iterator; + using typename TBase::const_iterator; + using typename TBase::const_reverse_iterator; using typename TBase::iterator; using typename TBase::reverse_iterator; - using typename TBase::size_type; + using typename TBase::size_type; using typename TBase::value_type; public: diff --git a/library/cpp/containers/str_map/str_map.cpp b/library/cpp/containers/str_map/str_map.cpp index 1b65718d42..58c65babda 100644 --- a/library/cpp/containers/str_map/str_map.cpp +++ b/library/cpp/containers/str_map/str_map.cpp @@ -1 +1 @@ -#include "str_map.h" +#include "str_map.h" diff --git a/library/cpp/containers/str_map/str_map.h b/library/cpp/containers/str_map/str_map.h index 47a4540787..31b00d1b99 100644 --- a/library/cpp/containers/str_map/str_map.h +++ b/library/cpp/containers/str_map/str_map.h @@ -1,44 +1,44 @@ #pragma once -#include <util/memory/segmented_string_pool.h> +#include <util/memory/segmented_string_pool.h> #include <util/generic/map.h> #include <util/generic/hash.h> -#include <util/generic/buffer.h> -#include <util/str_stl.h> // less<> and equal_to<> for const char* +#include <util/generic/buffer.h> +#include <util/str_stl.h> // less<> and equal_to<> for const char* #include <utility> #include <util/generic/noncopyable.h> -template <class T, class HashFcn = THash<const char*>, class EqualTo = TEqualTo<const char*>, class Alloc = std::allocator<const char*>> -class string_hash; - -template <class T, class HashFcn = THash<const char*>, class EqualTo = TEqualTo<const char*>> -class segmented_string_hash; - +template <class T, class HashFcn = THash<const char*>, class EqualTo = TEqualTo<const char*>, class Alloc = std::allocator<const char*>> +class string_hash; + +template <class T, class HashFcn = THash<const char*>, class EqualTo = TEqualTo<const char*>> +class segmented_string_hash; + template <class Map> inline std::pair<typename Map::iterator, bool> -pool_insert(Map* m, const char* key, const typename Map::mapped_type& data, TBuffer& pool) { +pool_insert(Map* m, const char* key, const typename Map::mapped_type& data, TBuffer& pool) { std::pair<typename Map::iterator, bool> ins = m->insert(typename Map::value_type(key, data)); - if (ins.second) { // new? - size_t buflen = strlen(key) + 1; // strlen??? - const char* old_pool = pool.Begin(); - pool.Append(key, buflen); - if (pool.Begin() != old_pool) // repoint? + if (ins.second) { // new? + size_t buflen = strlen(key) + 1; // strlen??? + const char* old_pool = pool.Begin(); + pool.Append(key, buflen); + if (pool.Begin() != old_pool) // repoint? for (typename Map::iterator it = m->begin(); it != m->end(); ++it) if ((*it).first != key) - const_cast<const char*&>((*it).first) += (pool.Begin() - old_pool); - const_cast<const char*&>((*ins.first).first) = pool.End() - buflen; + const_cast<const char*&>((*it).first) += (pool.Begin() - old_pool); + const_cast<const char*&>((*ins.first).first) = pool.End() - buflen; } return ins; } #define HASH_SIZE_DEFAULT 100 -#define AVERAGEWORD_BUF 10 +#define AVERAGEWORD_BUF 10 template <class T, class HashFcn, class EqualTo, class Alloc> class string_hash: public THashMap<const char*, T, HashFcn, EqualTo, Alloc> { protected: - TBuffer pool; - + TBuffer pool; + public: using yh = THashMap<const char*, T, HashFcn, EqualTo, Alloc>; using iterator = typename yh::iterator; @@ -46,25 +46,25 @@ public: using mapped_type = typename yh::mapped_type; using size_type = typename yh::size_type; using pool_size_type = typename yh::size_type; - string_hash() { - pool.Reserve(HASH_SIZE_DEFAULT * AVERAGEWORD_BUF); // reserve here + string_hash() { + pool.Reserve(HASH_SIZE_DEFAULT * AVERAGEWORD_BUF); // reserve here } string_hash(size_type hash_size, pool_size_type pool_size) : THashMap<const char*, T, HashFcn, EqualTo, Alloc>(hash_size) { - pool.Reserve(pool_size); // reserve here + pool.Reserve(pool_size); // reserve here } std::pair<iterator, bool> insert_copy(const char* key, const mapped_type& data) { return ::pool_insert(this, key, data, pool); } - void clear_hash() { + void clear_hash() { yh::clear(); - pool.Clear(); + pool.Clear(); } - pool_size_type pool_size() const { - return pool.Size(); + pool_size_type pool_size() const { + return pool.Size(); } string_hash(const string_hash& sh) @@ -83,7 +83,7 @@ public: (const char*&)(*i).first += delta; } */ - string_hash& operator=(const string_hash& sh) { + string_hash& operator=(const string_hash& sh) { if (&sh != this) { clear_hash(); for (const_iterator i = sh.begin(); i != sh.end(); ++i) @@ -92,7 +92,7 @@ public: return *this; } - mapped_type& operator[](const char* key) { + mapped_type& operator[](const char* key) { iterator I = yh::find(key); if (I == yh::end()) I = insert_copy(key, mapped_type()).first; @@ -104,7 +104,7 @@ template <class C, class T, class HashFcn, class EqualTo> class THashWithSegmentedPoolForKeys: protected THashMap<const C*, T, HashFcn, EqualTo>, TNonCopyable { protected: segmented_pool<C> pool; - + public: using yh = THashMap<const C*, T, HashFcn, EqualTo>; using iterator = typename yh::iterator; @@ -176,7 +176,7 @@ public: }; template <class T, class HashFcn, class EqualTo> -class segmented_string_hash: public THashWithSegmentedPoolForKeys<char, T, HashFcn, EqualTo> { +class segmented_string_hash: public THashWithSegmentedPoolForKeys<char, T, HashFcn, EqualTo> { public: using Base = THashWithSegmentedPoolForKeys<char, T, HashFcn, EqualTo>; using iterator = typename Base::iterator; @@ -185,10 +185,10 @@ public: using size_type = typename Base::size_type; using key_type = typename Base::key_type; using value_type = typename Base::value_type; - + public: segmented_string_hash(size_type hash_size = HASH_SIZE_DEFAULT, size_t segsize = HASH_SIZE_DEFAULT * AVERAGEWORD_BUF, bool afs = false) - : Base(hash_size, segsize, afs) + : Base(hash_size, segsize, afs) { } diff --git a/library/cpp/containers/str_map/ya.make b/library/cpp/containers/str_map/ya.make index 9c887fd9e2..b834159cda 100644 --- a/library/cpp/containers/str_map/ya.make +++ b/library/cpp/containers/str_map/ya.make @@ -1,9 +1,9 @@ -LIBRARY() - -OWNER(pg) - -SRCS( - str_map.cpp -) - -END() +LIBRARY() + +OWNER(pg) + +SRCS( + str_map.cpp +) + +END() diff --git a/library/cpp/containers/top_keeper/top_keeper.h b/library/cpp/containers/top_keeper/top_keeper.h index b5f901a86e..2f282b5a9e 100644 --- a/library/cpp/containers/top_keeper/top_keeper.h +++ b/library/cpp/containers/top_keeper/top_keeper.h @@ -14,13 +14,13 @@ private: size_t HalfMaxSize; TComparator Comparer; size_t MinElementIndex; - + private: void Reserve() { Internal.reserve(2 * HalfMaxSize); } - template <class UT> + template <class UT> bool Insert(UT&& value) noexcept { if (Y_UNLIKELY(0 == HalfMaxSize)) { return false; @@ -55,7 +55,7 @@ private: Reserve(); } - template <class TAllocParam> + template <class TAllocParam> TVectorWithMin(const size_t halfMaxSize, const TComparator& comp, TAllocParam&& param) : Internal(std::forward<TAllocParam>(param)) , HalfMaxSize(halfMaxSize) @@ -89,7 +89,7 @@ private: return Insert(std::move(value)); } - template <class... TArgs> + template <class... TArgs> bool Emplace(TArgs&&... args) { return Insert(T(std::forward<TArgs>(args)...)); // TODO: make it "real" emplace, not that fake one } @@ -133,7 +133,7 @@ private: void CheckNotFinalized() { Y_ENSURE(!Finalized, "Cannot insert after finalizing (Pop() / GetNext() / Finalize())! " - "Use TLimitedHeap for this scenario"); + "Use TLimitedHeap for this scenario"); } size_t MaxSize; @@ -158,7 +158,7 @@ public: { } - template <class TAllocParam> + template <class TAllocParam> TTopKeeper(size_t maxSize, const TComparator& comp, TAllocParam&& param) : MaxSize(maxSize) , Comparer(comp) @@ -219,7 +219,7 @@ public: return Internal.Push(std::move(value)); } - template <class... TArgs> + template <class... TArgs> bool Emplace(TArgs&&... args) { CheckNotFinalized(); return Internal.Emplace(std::forward<TArgs>(args)...); @@ -244,7 +244,7 @@ public: void SetMaxSize(size_t newMaxSize) { Y_ENSURE(!Finalized, "Cannot resize after finalizing (Pop() / GetNext() / Finalize())! " - "Use TLimitedHeap for this scenario"); + "Use TLimitedHeap for this scenario"); MaxSize = newMaxSize; Internal.SetMaxSize(newMaxSize); } diff --git a/library/cpp/containers/top_keeper/top_keeper/top_keeper.h b/library/cpp/containers/top_keeper/top_keeper/top_keeper.h index b5f901a86e..2f282b5a9e 100644 --- a/library/cpp/containers/top_keeper/top_keeper/top_keeper.h +++ b/library/cpp/containers/top_keeper/top_keeper/top_keeper.h @@ -14,13 +14,13 @@ private: size_t HalfMaxSize; TComparator Comparer; size_t MinElementIndex; - + private: void Reserve() { Internal.reserve(2 * HalfMaxSize); } - template <class UT> + template <class UT> bool Insert(UT&& value) noexcept { if (Y_UNLIKELY(0 == HalfMaxSize)) { return false; @@ -55,7 +55,7 @@ private: Reserve(); } - template <class TAllocParam> + template <class TAllocParam> TVectorWithMin(const size_t halfMaxSize, const TComparator& comp, TAllocParam&& param) : Internal(std::forward<TAllocParam>(param)) , HalfMaxSize(halfMaxSize) @@ -89,7 +89,7 @@ private: return Insert(std::move(value)); } - template <class... TArgs> + template <class... TArgs> bool Emplace(TArgs&&... args) { return Insert(T(std::forward<TArgs>(args)...)); // TODO: make it "real" emplace, not that fake one } @@ -133,7 +133,7 @@ private: void CheckNotFinalized() { Y_ENSURE(!Finalized, "Cannot insert after finalizing (Pop() / GetNext() / Finalize())! " - "Use TLimitedHeap for this scenario"); + "Use TLimitedHeap for this scenario"); } size_t MaxSize; @@ -158,7 +158,7 @@ public: { } - template <class TAllocParam> + template <class TAllocParam> TTopKeeper(size_t maxSize, const TComparator& comp, TAllocParam&& param) : MaxSize(maxSize) , Comparer(comp) @@ -219,7 +219,7 @@ public: return Internal.Push(std::move(value)); } - template <class... TArgs> + template <class... TArgs> bool Emplace(TArgs&&... args) { CheckNotFinalized(); return Internal.Emplace(std::forward<TArgs>(args)...); @@ -244,7 +244,7 @@ public: void SetMaxSize(size_t newMaxSize) { Y_ENSURE(!Finalized, "Cannot resize after finalizing (Pop() / GetNext() / Finalize())! " - "Use TLimitedHeap for this scenario"); + "Use TLimitedHeap for this scenario"); MaxSize = newMaxSize; Internal.SetMaxSize(newMaxSize); } |