/* * Copyright (c) 2020, the SerenityOS developers. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include #include #include namespace AK { namespace Detail { template struct SubstituteIfVoid { using Type = TypeA; }; template struct SubstituteIfVoid { using Type = Default; }; template class Trie { using BaseType = typename SubstituteIfVoid::Type; class ConstIterator { public: static ConstIterator end() { return {}; } bool operator==(const ConstIterator& other) const { return m_current_node == other.m_current_node; } const BaseType& operator*() const { return static_cast(*m_current_node); } const BaseType* operator->() const { return static_cast(m_current_node); } void operator++() { skip_to_next(); } explicit ConstIterator(const Trie& node) { m_current_node = &node; m_state.empend(false, node.m_children.begin(), node.m_children.end()); } private: void skip_to_next() { auto& current_state = m_state.last(); if (current_state.did_generate_root) ++current_state.it; else current_state.did_generate_root = true; if (current_state.it == current_state.end) return pop_and_get_next(); m_current_node = &*(*current_state.it).value; m_state.empend(false, m_current_node->m_children.begin(), m_current_node->m_children.end()); } void pop_and_get_next() { m_state.take_last(); if (m_state.is_empty()) { m_current_node = nullptr; return; } skip_to_next(); } ConstIterator() = default; struct State { bool did_generate_root { false }; typename HashMap, ValueTraits>::ConstIteratorType it; typename HashMap, ValueTraits>::ConstIteratorType end; }; Vector m_state; const Trie* m_current_node { nullptr }; }; public: using MetadataType = MetadataT; Trie(ValueType value, Optional metadata) : m_value(move(value)) , m_metadata(move(metadata)) { } template BaseType& traverse_until_last_accessible_node(It& it, const It& end) { Trie* node = this; for (; it < end; ++it) { auto next_it = node->m_children.find(*it); if (next_it == node->m_children.end()) return static_cast(*node); node = &*(*next_it).value; } return static_cast(*node); } template const BaseType& traverse_until_last_accessible_node(It& it, const It& end) const { return const_cast(this)->traverse_until_last_accessible_node(it, end); } template BaseType& traverse_until_last_accessible_node(const It& begin, const It& end) { auto it = begin; return const_cast(this)->traverse_until_last_accessible_node(it, end); } template const BaseType& traverse_until_last_accessible_node(const It& begin, const It& end) const { auto it = begin; return const_cast(this)->traverse_until_last_accessible_node(it, end); } Optional metadata() const requires(!IsNullPointer) { return m_metadata; } void set_metadata(MetadataType metadata) requires(!IsNullPointer) { m_metadata = move(metadata); } const MetadataType& metadata_value() const requires(!IsNullPointer) { return m_metadata.value(); } const ValueType& value() const { return m_value; } ValueType& value() { return m_value; } Trie& ensure_child(ValueType value, Optional metadata = {}) { auto it = m_children.find(value); if (it == m_children.end()) { auto node = make(value, move(metadata)); auto& node_ref = *node; m_children.set(move(value), move(node)); return static_cast(node_ref); } auto& node_ref = *it->value; if (metadata.has_value()) node_ref.m_metadata = move(metadata); return static_cast(node_ref); } template BaseType& insert( It& it, const It& end, MetadataType metadata, ProvideMetadataFunction provide_missing_metadata) requires(!IsNullPointer) { Trie* last_root_node = &traverse_until_last_accessible_node(it, end); for (; it != end; ++it) last_root_node = static_cast(&last_root_node->ensure_child(*it, provide_missing_metadata(static_cast(*last_root_node), it))); last_root_node->set_metadata(move(metadata)); return static_cast(*last_root_node); } template BaseType& insert(It& it, const It& end) requires(IsNullPointer) { Trie* last_root_node = &traverse_until_last_accessible_node(it, end); for (; it != end; ++it) last_root_node = static_cast(&last_root_node->ensure_child(*it, {})); return static_cast(*last_root_node); } template BaseType& insert( const It& begin, const It& end, MetadataType metadata, ProvideMetadataFunction provide_missing_metadata) requires(!IsNullPointer) { auto it = begin; return insert(it, end, move(metadata), move(provide_missing_metadata)); } template BaseType& insert(const It& begin, const It& end) requires(IsNullPointer) { auto it = begin; return insert(it, end); } ConstIterator begin() const { return ConstIterator(*this); } ConstIterator end() const { return ConstIterator::end(); } [[nodiscard]] bool is_empty() const { return m_children.is_empty(); } void clear() { m_children.clear(); } BaseType deep_copy() { Trie root(m_value, m_metadata); for (auto& it : m_children) root.m_children.set(it.key, make(it.value->deep_copy())); return static_cast(move(root)); } private: ValueType m_value; Optional m_metadata; HashMap, ValueTraits> m_children; }; template class Trie : public Trie { using Trie::Trie; }; } template, typename BaseT = void> class Trie : public Detail::Trie, ValueType, MetadataT, ValueTraits> { public: using DetailTrie = Detail::Trie, ValueType, MetadataT, ValueTraits>; using MetadataType = typename DetailTrie::MetadataType; Trie(ValueType value, MetadataType metadata) requires(!IsVoid && !IsNullPointer) : DetailTrie(move(value), move(metadata)) { } explicit Trie(ValueType value) : DetailTrie(move(value), Optional {}) { } }; } using AK::Trie;