search_iterator.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #pragma once
  2. #include "comptrie_trie.h"
  3. #include "first_symbol_iterator.h"
  4. #include <util/str_stl.h>
  5. #include <util/digest/numeric.h>
  6. #include <util/digest/multi.h>
  7. // Iterator for incremental searching.
  8. // All Advance() methods shift the iterator using specifed key/char.
  9. // The subsequent Advance() call starts searching from the previous state.
  10. // The Advance() returns 'true' if specified key part exists in the trie and
  11. // returns 'false' for unsuccessful search. In case of 'false' result
  12. // all subsequent calls also will return 'false'.
  13. // If current iterator state is final then GetValue() method returns 'true' and
  14. // associated value.
  15. template <class TTrie>
  16. class TSearchIterator {
  17. public:
  18. using TData = typename TTrie::TData;
  19. using TSymbol = typename TTrie::TSymbol;
  20. using TKeyBuf = typename TTrie::TKeyBuf;
  21. TSearchIterator() = default;
  22. explicit TSearchIterator(const TTrie& trie)
  23. : Trie(&trie)
  24. , DataPos(trie.DataHolder.AsCharPtr())
  25. , DataEnd(DataPos + trie.DataHolder.Length())
  26. , ValuePos(trie.EmptyValue)
  27. {
  28. }
  29. explicit TSearchIterator(const TTrie& trie, const TTrie& subTrie)
  30. : Trie(&trie)
  31. , DataPos(subTrie.Data().AsCharPtr())
  32. , DataEnd(trie.DataHolder.AsCharPtr() + trie.DataHolder.Length())
  33. , ValuePos(subTrie.EmptyValue)
  34. {
  35. }
  36. bool operator==(const TSearchIterator& other) const {
  37. Y_ASSERT(Trie && other.Trie);
  38. return Trie == other.Trie &&
  39. DataPos == other.DataPos &&
  40. DataEnd == other.DataEnd &&
  41. ValuePos == other.ValuePos;
  42. }
  43. bool operator!=(const TSearchIterator& other) const {
  44. return !(*this == other);
  45. }
  46. inline bool Advance(TSymbol label) {
  47. Y_ASSERT(Trie);
  48. if (DataPos == nullptr || DataPos >= DataEnd) {
  49. return false;
  50. }
  51. return NCompactTrie::Advance(DataPos, DataEnd, ValuePos, label, Trie->Packer);
  52. }
  53. inline bool Advance(const TKeyBuf& key) {
  54. return Advance(key.data(), key.size());
  55. }
  56. bool Advance(const TSymbol* key, size_t keylen);
  57. bool GetValue(TData* value = nullptr) const;
  58. bool HasValue() const;
  59. inline size_t GetHash() const;
  60. private:
  61. const TTrie* Trie = nullptr;
  62. const char* DataPos = nullptr;
  63. const char* DataEnd = nullptr;
  64. const char* ValuePos = nullptr;
  65. };
  66. template <class TTrie>
  67. inline TSearchIterator<TTrie> MakeSearchIterator(const TTrie& trie) {
  68. return TSearchIterator<TTrie>(trie);
  69. }
  70. template <class TTrie>
  71. struct THash<TSearchIterator<TTrie>> {
  72. inline size_t operator()(const TSearchIterator<TTrie>& item) {
  73. return item.GetHash();
  74. }
  75. };
  76. //----------------------------------------------------------------------------
  77. template <class TTrie>
  78. bool TSearchIterator<TTrie>::Advance(const TSymbol* key, size_t keylen) {
  79. Y_ASSERT(Trie);
  80. if (!key || DataPos == nullptr || DataPos >= DataEnd) {
  81. return false;
  82. }
  83. if (!keylen) {
  84. return true;
  85. }
  86. const TSymbol* keyend = key + keylen;
  87. while (key != keyend && DataPos != nullptr) {
  88. if (!NCompactTrie::Advance(DataPos, DataEnd, ValuePos, *(key++), Trie->Packer)) {
  89. return false;
  90. }
  91. if (key == keyend) {
  92. return true;
  93. }
  94. }
  95. return false;
  96. }
  97. template <class TTrie>
  98. bool TSearchIterator<TTrie>::GetValue(TData* value) const {
  99. Y_ASSERT(Trie);
  100. bool result = false;
  101. if (value) {
  102. if (ValuePos) {
  103. result = true;
  104. Trie->Packer.UnpackLeaf(ValuePos, *value);
  105. }
  106. }
  107. return result;
  108. }
  109. template <class TTrie>
  110. bool TSearchIterator<TTrie>::HasValue() const {
  111. Y_ASSERT(Trie);
  112. return ValuePos;
  113. }
  114. template <class TTrie>
  115. inline size_t TSearchIterator<TTrie>::GetHash() const {
  116. Y_ASSERT(Trie);
  117. return MultiHash(
  118. static_cast<const void*>(Trie),
  119. static_cast<const void*>(DataPos),
  120. static_cast<const void*>(DataEnd),
  121. static_cast<const void*>(ValuePos));
  122. }