Coverage Report

Created: 2025-08-28 06:26

/src/serenity/AK/Trie.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2020, the SerenityOS developers.
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#pragma once
8
9
#include <AK/Concepts.h>
10
#include <AK/Forward.h>
11
#include <AK/HashMap.h>
12
#include <AK/OwnPtr.h>
13
#include <AK/Types.h>
14
15
namespace AK {
16
17
namespace Detail {
18
19
template<typename TypeA, typename Default>
20
struct SubstituteIfVoid {
21
    using Type = TypeA;
22
};
23
24
template<typename Default>
25
struct SubstituteIfVoid<void, Default> {
26
    using Type = Default;
27
};
28
29
template<typename DeclaredBaseType, typename DefaultBaseType, typename ValueType, typename MetadataT, typename ValueTraits, template<typename, typename, typename> typename MapType>
30
class Trie {
31
    using BaseType = typename SubstituteIfVoid<DeclaredBaseType, DefaultBaseType>::Type;
32
33
public:
34
    using MetadataType = MetadataT;
35
36
    Trie(ValueType value, Optional<MetadataType> metadata)
37
9.34M
        : m_value(move(value))
38
9.34M
        , m_metadata(move(metadata))
39
9.34M
    {
40
9.34M
    }
41
42
    template<typename It>
43
    BaseType& traverse_until_last_accessible_node(It& it, It const& end)
44
    {
45
        Trie* node = this;
46
        for (; it < end; ++it) {
47
            auto next_it = node->m_children.find(*it);
48
            if (next_it == node->m_children.end())
49
                return static_cast<BaseType&>(*node);
50
            node = &*(*next_it).value;
51
        }
52
        return static_cast<BaseType&>(*node);
53
    }
54
55
    template<typename It>
56
    BaseType const& traverse_until_last_accessible_node(It& it, It const& end) const { return const_cast<Trie*>(this)->traverse_until_last_accessible_node(it, end); }
57
58
    template<typename It>
59
    BaseType& traverse_until_last_accessible_node(It const& begin, It const& end)
60
    {
61
        auto it = begin;
62
        return const_cast<Trie*>(this)->traverse_until_last_accessible_node(it, end);
63
    }
64
65
    template<typename It>
66
    BaseType const& traverse_until_last_accessible_node(It const& begin, It const& end) const
67
    {
68
        auto it = begin;
69
        return const_cast<Trie*>(this)->traverse_until_last_accessible_node(it, end);
70
    }
71
72
241M
    bool has_metadata() const { return m_metadata.has_value(); }
73
74
    Optional<MetadataType> metadata() const
75
    requires(!IsNullPointer<MetadataType>)
76
    {
77
        return m_metadata;
78
    }
79
    void set_metadata(MetadataType metadata)
80
    requires(!IsNullPointer<MetadataType>)
81
9.34M
    {
82
9.34M
        m_metadata = move(metadata);
83
9.34M
    }
84
    MetadataType const& metadata_value() const
85
    requires(!IsNullPointer<MetadataType>)
86
231M
    {
87
231M
        return m_metadata.value();
88
231M
    }
89
    MetadataType& metadata_value()
90
    requires(!IsNullPointer<MetadataType>)
91
1.03M
    {
92
1.03M
        return m_metadata.value();
93
1.03M
    }
94
95
693k
    ValueType const& value() const { return m_value; }
96
    ValueType& value() { return m_value; }
97
98
    ErrorOr<Trie*> ensure_child(ValueType value, Optional<MetadataType> metadata = {})
99
10.3M
    {
100
10.3M
        auto it = m_children.find(value);
101
10.3M
        if (it == m_children.end()) {
102
9.34M
            OwnPtr<Trie> node;
103
            if constexpr (requires { { value->try_clone() } -> SpecializationOf<ErrorOr>; })
104
                node = TRY(adopt_nonnull_own_or_enomem(new (nothrow) Trie(TRY(value->try_clone()), move(metadata))));
105
            else
106
9.34M
                node = TRY(adopt_nonnull_own_or_enomem(new (nothrow) Trie(value, move(metadata))));
107
0
            auto& node_ref = *node;
108
9.34M
            TRY(m_children.try_set(move(value), node.release_nonnull()));
109
0
            return &static_cast<BaseType&>(node_ref);
110
9.34M
        }
111
112
1.03M
        auto& node_ref = *it->value;
113
1.03M
        if (metadata.has_value())
114
0
            node_ref.m_metadata = move(metadata);
115
1.03M
        return &static_cast<BaseType&>(node_ref);
116
10.3M
    }
117
118
    template<typename It, typename ProvideMetadataFunction>
119
    ErrorOr<BaseType*> insert(
120
        It& it, It const& end, MetadataType metadata, ProvideMetadataFunction provide_missing_metadata)
121
    requires(!IsNullPointer<MetadataType>)
122
    {
123
        Trie* last_root_node = &traverse_until_last_accessible_node(it, end);
124
        auto invoke_provide_missing_metadata = [&]<typename... Ts>(Ts&&... args) -> ErrorOr<Optional<MetadataType>> {
125
            if constexpr (SameAs<MetadataType, decltype(provide_missing_metadata(forward<Ts>(args)...))>)
126
                return Optional<MetadataType>(provide_missing_metadata(forward<Ts>(args)...));
127
            else
128
                return provide_missing_metadata(forward<Ts>(args)...);
129
        };
130
        for (; it != end; ++it) {
131
            if constexpr (requires { { ValueType::ElementType::try_create(*it) } -> SpecializationOf<ErrorOr>; })
132
                last_root_node = static_cast<Trie*>(TRY(last_root_node->ensure_child(TRY(ValueType::ElementType::try_create(*it)), TRY(invoke_provide_missing_metadata(static_cast<BaseType&>(*last_root_node), it)))));
133
            else
134
                last_root_node = static_cast<Trie*>(TRY(last_root_node->ensure_child(*it, TRY(invoke_provide_missing_metadata(static_cast<BaseType&>(*last_root_node), it)))));
135
        }
136
        last_root_node->set_metadata(move(metadata));
137
        return static_cast<BaseType*>(last_root_node);
138
    }
139
140
    template<typename It>
141
    ErrorOr<BaseType*> insert(It& it, It const& end)
142
    requires(IsNullPointer<MetadataType>)
143
    {
144
        Trie* last_root_node = &traverse_until_last_accessible_node(it, end);
145
        for (; it != end; ++it) {
146
            if constexpr (requires { { ValueType::ElementType::try_create(*it) } -> SpecializationOf<ErrorOr>; })
147
                last_root_node = static_cast<Trie*>(TRY(last_root_node->ensure_child(TRY(ValueType::ElementType::try_create(*it)), {})));
148
            else
149
                last_root_node = static_cast<Trie*>(TRY(last_root_node->ensure_child(*it, {})));
150
        }
151
        return static_cast<BaseType*>(last_root_node);
152
    }
153
154
    template<typename It, typename ProvideMetadataFunction>
155
    ErrorOr<BaseType*> insert(
156
        It const& begin, It const& end, MetadataType metadata, ProvideMetadataFunction provide_missing_metadata)
157
    requires(!IsNullPointer<MetadataType>)
158
    {
159
        auto it = begin;
160
        return insert(it, end, move(metadata), move(provide_missing_metadata));
161
    }
162
163
    template<typename It>
164
    ErrorOr<BaseType*> insert(It const& begin, It const& end)
165
    requires(IsNullPointer<MetadataType>)
166
    {
167
        auto it = begin;
168
        return insert(it, end);
169
    }
170
171
0
    MapType<ValueType, NonnullOwnPtr<Trie>, ValueTraits>& children() { return m_children; }
172
347k
    MapType<ValueType, NonnullOwnPtr<Trie>, ValueTraits> const& children() const { return m_children; }
173
174
    template<typename Fn>
175
    ErrorOr<void> for_each_node_in_tree_order(Fn callback) const
176
    {
177
        struct State {
178
            bool did_generate_root { false };
179
            typename MapType<ValueType, NonnullOwnPtr<Trie>, ValueTraits>::ConstIteratorType it;
180
            typename MapType<ValueType, NonnullOwnPtr<Trie>, ValueTraits>::ConstIteratorType end;
181
        };
182
        Vector<State> state;
183
        TRY(state.try_empend(false, m_children.begin(), m_children.end()));
184
185
        auto invoke = [&](auto& current_node) -> ErrorOr<IterationDecision> {
186
            if constexpr (VoidFunction<Fn, BaseType const&>) {
187
                callback(static_cast<BaseType const&>(current_node));
188
                return IterationDecision::Continue;
189
            } else if constexpr (IsSpecializationOf<decltype(callback(declval<BaseType const&>())), ErrorOr>) {
190
                return callback(static_cast<BaseType const&>(current_node));
191
            } else if constexpr (IteratorFunction<Fn, BaseType const&>) {
192
                return callback(static_cast<BaseType const&>(current_node));
193
            } else {
194
                static_assert(DependentFalse<Fn>, "Invalid iterator function type signature");
195
            }
196
            return IterationDecision::Continue;
197
        };
198
199
        for (auto* current_node = this; current_node != nullptr;) {
200
            if (TRY(invoke(*current_node)) == IterationDecision::Break)
201
                break;
202
            TRY(skip_to_next_iterator(state, current_node));
203
        }
204
        return {};
205
    }
206
207
    [[nodiscard]] bool is_empty() const { return m_children.is_empty(); }
208
    void clear() { m_children.clear(); }
209
210
    ErrorOr<BaseType> deep_copy()
211
    requires(requires(ValueType value) { { value->try_clone() } -> SpecializationOf<ErrorOr>; })
212
    {
213
        Trie root(TRY(m_value->try_clone()), TRY(copy_metadata(m_metadata)));
214
        for (auto& it : m_children)
215
            TRY(root.m_children.try_set(TRY(it.key->try_clone()), TRY(adopt_nonnull_own_or_enomem(new (nothrow) Trie(TRY(it.value->deep_copy()))))));
216
        return static_cast<BaseType&&>(move(root));
217
    }
218
219
    ErrorOr<BaseType> deep_copy()
220
    {
221
        Trie root(m_value, TRY(copy_metadata(m_metadata)));
222
        for (auto& it : m_children)
223
            TRY(root.m_children.try_set(it.key, TRY(adopt_nonnull_own_or_enomem(new (nothrow) Trie(TRY(it.value->deep_copy()))))));
224
        return static_cast<BaseType&&>(move(root));
225
    }
226
227
private:
228
    static ErrorOr<Optional<MetadataType>> copy_metadata(Optional<MetadataType> const& metadata)
229
    {
230
        if (!metadata.has_value())
231
            return Optional<MetadataType> {};
232
233
        if constexpr (requires(MetadataType t) { { t.copy() } -> SpecializationOf<ErrorOr>; })
234
            return Optional<MetadataType> { TRY(metadata->copy()) };
235
#ifndef KERNEL
236
        else
237
            return Optional<MetadataType> { MetadataType(metadata.value()) };
238
#endif
239
    }
240
241
    static ErrorOr<void> skip_to_next_iterator(auto& state, auto& current_node)
242
    {
243
        auto& current_state = state.last();
244
        if (current_state.did_generate_root)
245
            ++current_state.it;
246
        else
247
            current_state.did_generate_root = true;
248
249
        if (current_state.it == current_state.end)
250
            return pop_and_get_next_iterator(state, current_node);
251
252
        current_node = &*(*current_state.it).value;
253
254
        TRY(state.try_empend(false, current_node->m_children.begin(), current_node->m_children.end()));
255
        return {};
256
    }
257
258
    static ErrorOr<void> pop_and_get_next_iterator(auto& state, auto& current_node)
259
    {
260
        state.take_last();
261
        if (state.is_empty()) {
262
            current_node = nullptr;
263
            return {};
264
        }
265
        return skip_to_next_iterator(state, current_node);
266
    }
267
268
    ValueType m_value;
269
    Optional<MetadataType> m_metadata;
270
    MapType<ValueType, NonnullOwnPtr<Trie>, ValueTraits> m_children;
271
};
272
273
template<typename BaseType, typename DefaultBaseType, typename ValueType, typename ValueTraits, template<typename, typename, typename> typename MapType>
274
class Trie<BaseType, DefaultBaseType, ValueType, void, ValueTraits, MapType> : public Trie<BaseType, DefaultBaseType, ValueType, decltype(nullptr), ValueTraits, MapType> {
275
    using Trie<BaseType, DefaultBaseType, ValueType, decltype(nullptr), ValueTraits, MapType>::Trie;
276
};
277
278
template<typename K, typename V, typename T>
279
using HashMapForTrie = HashMap<K, V, T>;
280
281
}
282
283
template<typename ValueType, typename MetadataT = void, typename ValueTraits = Traits<ValueType>, typename BaseT = void, template<typename, typename, typename> typename MapType = Detail::HashMapForTrie>
284
class Trie : public Detail::Trie<BaseT, Trie<ValueType, MetadataT, ValueTraits, void, MapType>, ValueType, MetadataT, ValueTraits, MapType> {
285
public:
286
    using DetailTrie = Detail::Trie<BaseT, Trie<ValueType, MetadataT, ValueTraits, void, MapType>, ValueType, MetadataT, ValueTraits, MapType>;
287
    using MetadataType = typename DetailTrie::MetadataType;
288
289
    Trie(ValueType value, MetadataType metadata)
290
    requires(!IsVoid<MetadataType> && !IsNullPointer<MetadataType>)
291
        : DetailTrie(move(value), move(metadata))
292
    {
293
    }
294
295
    explicit Trie(ValueType value)
296
2.52k
        : DetailTrie(move(value), Optional<MetadataType> {})
297
2.52k
    {
298
2.52k
    }
299
};
300
301
}
302
303
#if USING_AK_GLOBALLY
304
using AK::Trie;
305
#endif