#pragma once #include "base/assert.hpp" #include "base/base.hpp" #include "base/buffer_vector.hpp" #include "base/mem_trie.hpp" #include #include #include namespace trie { using TrieChar = uint32_t; // 95 is a good value for the default baseChar, since both small and capital latin letters // are less than +/- 32 from it and thus can fit into supershort edge. // However 0 is used because the first byte is actually language id. uint32_t constexpr kDefaultChar = 0; template struct Iterator { using List = ValueList; using Value = typename List::Value; struct Edge { using EdgeLabel = buffer_vector; Edge() = default; template Edge(It begin, It end): m_label(begin, end) {} EdgeLabel m_label; }; virtual ~Iterator() = default; virtual std::unique_ptr> Clone() const = 0; virtual std::unique_ptr> GoToEdge(size_t i) const = 0; buffer_vector m_edges; List m_values; }; template class MemTrieIterator final : public trie::Iterator { public: using Base = trie::Iterator; using Char = typename String::value_type; using InnerIterator = typename base::MemTrie::Iterator; explicit MemTrieIterator(InnerIterator const & innerIt) { Base::m_values = innerIt.GetValues(); innerIt.ForEachMove([&](Char c, InnerIterator it) { auto const label = it.GetLabel(); Base::m_edges.emplace_back(); auto & edge = Base::m_edges.back().m_label; edge.push_back(c); edge.append(label); m_moves.push_back(it); }); } ~MemTrieIterator() override = default; // Iterator overrides: std::unique_ptr Clone() const override { return std::make_unique(*this); } std::unique_ptr GoToEdge(size_t i) const override { ASSERT_LESS(i, m_moves.size(), ()); return std::make_unique(m_moves[i]); } private: std::vector m_moves; }; template void ForEachRef(Iterator const & it, ToDo && toDo, String const & s) { it.m_values.ForEach([&toDo, &s](typename ValueList::Value const & value) { toDo(s, value); }); for (size_t i = 0; i < it.m_edges.size(); ++i) { String s1(s); s1.insert(s1.end(), it.m_edges[i].m_label.begin(), it.m_edges[i].m_label.end()); auto nextIt = it.GoToEdge(i); ForEachRef(*nextIt, toDo, s1); } } } // namespace trie