/* * Copyright (c) 2020, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #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; 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(); } MetadataType& metadata_value() requires(!IsNullPointer) { return m_metadata.value(); } const ValueType& value() const { return m_value; } ValueType& value() { return m_value; } ErrorOr ensure_child(ValueType value, Optional metadata = {}) { auto it = m_children.find(value); if (it == m_children.end()) { auto node = TRY(adopt_nonnull_own_or_enomem(new (nothrow) Trie(value, move(metadata)))); auto& node_ref = *node; TRY(m_children.try_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 ErrorOr 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); auto invoke_provide_missing_metadata = [&](Ts && ... args)->ErrorOr> { if constexpr (SameAs(args)...))>) return Optional(provide_missing_metadata(forward(args)...)); else return provide_missing_metadata(forward(args)...); }; for (; it != end; ++it) last_root_node = static_cast(TRY(last_root_node->ensure_child(*it, TRY(invoke_provide_missing_metadata(static_cast(*last_root_node), it))))); last_root_node->set_metadata(move(metadata)); return static_cast(last_root_node); } template ErrorOr 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(TRY(last_root_node->ensure_child(*it, {}))); return static_cast(last_root_node); } template ErrorOr 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 ErrorOr insert(const It& begin, const It& end) requires(IsNullPointer) { auto it = begin; return insert(it, end); } HashMap, ValueTraits>& children() { return m_children; } HashMap, ValueTraits> const& children() const { return m_children; } template ErrorOr for_each_node_in_tree_order(Fn callback) const { struct State { bool did_generate_root { false }; typename HashMap, ValueTraits>::ConstIteratorType it; typename HashMap, ValueTraits>::ConstIteratorType end; }; Vector state; TRY(state.try_empend(false, m_children.begin(), m_children.end())); auto invoke = [&](auto& current_node) -> ErrorOr { if constexpr (VoidFunction) { callback(static_cast(current_node)); return IterationDecision::Continue; } else if constexpr (IsSpecializationOf())), ErrorOr>) { return callback(static_cast(current_node)); } else if constexpr (IteratorFunction) { return callback(static_cast(current_node)); } else { static_assert(DependentFalse, "Invalid iterator function type signature"); } return IterationDecision::Continue; }; for (auto* current_node = this; current_node != nullptr;) { if (TRY(invoke(*current_node)) == IterationDecision::Break) break; TRY(skip_to_next_iterator(state, current_node)); } return {}; } [[nodiscard]] bool is_empty() const { return m_children.is_empty(); } void clear() { m_children.clear(); } ErrorOr deep_copy() { Trie root(m_value, TRY(copy_metadata(m_metadata))); for (auto& it : m_children) TRY(root.m_children.try_set(it.key, TRY(adopt_nonnull_own_or_enomem(new (nothrow) Trie(TRY(it.value->deep_copy())))))); return static_cast(move(root)); } private: static ErrorOr> copy_metadata(Optional const& metadata) { if (!metadata.has_value()) return Optional {}; if constexpr (requires(MetadataType t) { { t.copy() } -> SpecializationOf; }) return Optional { TRY(metadata->copy()) }; #ifndef KERNEL else return Optional { MetadataType(metadata.value()) }; #endif } static ErrorOr skip_to_next_iterator(auto& state, auto& current_node) { auto& current_state = 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_iterator(state, current_node); current_node = &*(*current_state.it).value; TRY(state.try_empend(false, current_node->m_children.begin(), current_node->m_children.end())); return {}; } static ErrorOr pop_and_get_next_iterator(auto& state, auto& current_node) { state.take_last(); if (state.is_empty()) { current_node = nullptr; return {}; } return skip_to_next_iterator(state, current_node); } 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;