prefix_iterator.h 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #pragma once
  2. #include "comptrie_trie.h"
  3. // Iterates over all prefixes of the given key in the trie.
  4. template <class TTrie>
  5. class TPrefixIterator {
  6. public:
  7. using TSymbol = typename TTrie::TSymbol;
  8. using TPacker = typename TTrie::TPacker;
  9. using TData = typename TTrie::TData;
  10. private:
  11. const TTrie& Trie;
  12. const TSymbol* key;
  13. size_t keylen;
  14. const TSymbol* keyend;
  15. size_t prefixLen;
  16. const char* valuepos;
  17. const char* datapos;
  18. const char* dataend;
  19. TPacker Packer;
  20. const char* EmptyValue;
  21. bool result;
  22. bool Next();
  23. public:
  24. TPrefixIterator(const TTrie& trie, const TSymbol* aKey, size_t aKeylen)
  25. : Trie(trie)
  26. , key(aKey)
  27. , keylen(aKeylen)
  28. , keyend(aKey + aKeylen)
  29. , prefixLen(0)
  30. , valuepos(nullptr)
  31. , datapos(trie.DataHolder.AsCharPtr())
  32. , dataend(datapos + trie.DataHolder.Length())
  33. {
  34. result = Next();
  35. }
  36. operator bool() const {
  37. return result;
  38. }
  39. TPrefixIterator& operator++() {
  40. result = Next();
  41. return *this;
  42. }
  43. size_t GetPrefixLen() const {
  44. return prefixLen;
  45. }
  46. void GetValue(TData& to) const {
  47. Trie.Packer.UnpackLeaf(valuepos, to);
  48. }
  49. };
  50. template <class TTrie>
  51. bool TPrefixIterator<TTrie>::Next() {
  52. using namespace NCompactTrie;
  53. if (!key || datapos == dataend)
  54. return false;
  55. if ((key == keyend - keylen) && !valuepos && Trie.EmptyValue) {
  56. valuepos = Trie.EmptyValue;
  57. return true;
  58. }
  59. while (datapos && key != keyend) {
  60. TSymbol label = *(key++);
  61. if (!Advance(datapos, dataend, valuepos, label, Packer)) {
  62. return false;
  63. }
  64. if (valuepos) { // There is a value at the end of this symbol.
  65. prefixLen = keylen - (keyend - key);
  66. return true;
  67. }
  68. }
  69. return false;
  70. }
  71. template <class TTrie>
  72. TPrefixIterator<TTrie> MakePrefixIterator(const TTrie& trie, const typename TTrie::TSymbol* key, size_t keylen) {
  73. return TPrefixIterator<TTrie>(trie, key, keylen);
  74. }