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/comptrie/opaque_trie_iterator.cpp | |
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/comptrie/opaque_trie_iterator.cpp')
-rw-r--r-- | library/cpp/containers/comptrie/opaque_trie_iterator.cpp | 428 |
1 files changed, 214 insertions, 214 deletions
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(); } } |