mdds
Loading...
Searching...
No Matches
trie_map.hpp
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3// SPDX-FileCopyrightText: 2015 - 2025 Kohei Yoshida
4//
5// SPDX-License-Identifier: MIT
6
7#pragma once
8
9#include "trie_map_itr.hpp"
10
11#include <vector>
12#include <string>
13#include <deque>
14#include <map>
15#include <memory>
16#include <limits>
17#include <cstdint>
18
19namespace mdds {
20
21namespace trie {
22
23namespace detail {
24
26{
27};
28
30{
31};
32
33template<typename TrieT, typename PackedT>
35
36} // namespace detail
37
39template<typename T>
41{
42 static constexpr bool variable_size = false;
43
44 static constexpr size_t value_size = sizeof(T);
45
46 static void write(std::ostream& os, const T& v);
47
48 static void read(std::istream& is, size_t n, T& v);
49};
50
52template<typename T>
54{
55 static constexpr bool variable_size = true;
56
57 static void write(std::ostream& os, const T& v);
58
59 static void read(std::istream& is, size_t n, T& v);
60};
61
66template<typename T>
68{
69 using element_serializer = numeric_value_serializer<typename T::value_type>;
70
71 static constexpr bool variable_size = true;
72
73 static void write(std::ostream& os, const T& v);
74
75 static void read(std::istream& is, size_t n, T& v);
76};
77
85template<typename T, typename U = void>
89
90template<typename T>
91struct value_serializer<T, typename std::enable_if<mdds::detail::has_value_type<T>::value>::type>
93{
94};
95
96template<>
97struct value_serializer<std::string> : variable_value_serializer<std::string>
98{
99};
100
102{
112 using pack_value_type = uintptr_t;
113};
114
118enum class dump_structure_type
119{
124 packed_buffer,
125
129 trie_traversal,
130};
131
132} // namespace trie
133
134template<typename KeyT, typename ValueT, typename TraitsT>
135class packed_trie_map;
136
143template<typename KeyT, typename ValueT, typename TraitsT = trie::default_traits>
145{
146 friend class packed_trie_map<KeyT, ValueT, TraitsT>;
147 friend class trie::detail::iterator_base<trie_map, true>;
148 friend class trie::detail::iterator_base<trie_map, false>;
150 friend class trie::detail::iterator<trie_map>;
154
155public:
156 using traits_type = TraitsT;
157 typedef packed_trie_map<KeyT, ValueT, TraitsT> packed_type;
158 typedef KeyT key_type;
159 typedef typename key_type::value_type key_unit_type;
160 typedef ValueT value_type;
161 typedef size_t size_type;
162
163 using const_iterator = trie::detail::const_iterator<trie_map>;
164 using iterator = trie::detail::iterator<trie_map>;
165 typedef trie::detail::search_results<trie_map> search_results;
166
167private:
168 struct trie_node
169 {
170 typedef std::map<key_unit_type, trie_node> children_type;
171
172 children_type children;
173 value_type value;
174 bool has_value;
175
176 trie_node();
177 trie_node(const trie_node& other);
178 trie_node(trie_node&& other);
179
180 void swap(trie_node& other);
181 };
182
183 template<bool IsConst>
184 struct stack_item
185 {
186 using _is_const = std::bool_constant<IsConst>;
187
188 using child_pos_type =
190
191 using trie_node_type = typename mdds::detail::const_or_not<trie_node, _is_const>::type;
192
193 trie_node_type* node;
194 child_pos_type child_pos;
195
196 stack_item(trie_node_type* _node, const child_pos_type& _child_pos) : node(_node), child_pos(_child_pos)
197 {}
198
199 bool operator==(const stack_item& r) const
200 {
201 return node == r.node && child_pos == r.child_pos;
202 }
203
204 bool operator!=(const stack_item& r) const
205 {
206 return !operator==(r);
207 }
208 };
209
210 using const_node_stack_type = std::vector<stack_item<true>>;
211 using node_stack_type = std::vector<stack_item<false>>;
212
213public:
217 class const_node_type
218 {
219 friend class trie_map;
220
221 const trie_node* m_ref_node = nullptr;
222
223 const_node_type(const trie_node* ref_node);
224
225 public:
226 const_node_type();
227 const_node_type(const const_node_type& other);
228
229 const_node_type& operator=(const const_node_type& other);
230
237 bool valid() const;
238
245 bool has_child() const;
246
252 bool has_value() const;
253
263 const value_type& value() const;
264
274 const_node_type child(key_unit_type c) const;
275 };
276
281
282 trie_map(const trie_map& other);
283
284 trie_map(trie_map&& other);
285
286 const_iterator begin() const;
287
288 iterator begin();
289
290 const_iterator end() const;
291
292 iterator end();
293
294 trie_map& operator=(trie_map other);
295
296 bool operator==(const trie_map& other) const;
297 bool operator!=(const trie_map& other) const;
298
299 void swap(trie_map& other);
300
307
314 void insert(const key_type& key, value_type value);
315
324 void insert(const key_unit_type* key, size_type len, value_type value);
325
335 bool erase(const key_unit_type* key, size_type len);
336
345 const_iterator find(const key_type& key) const;
346
357 const_iterator find(const key_unit_type* input, size_type len) const;
358
367 iterator find(const key_type& key);
368
379 iterator find(const key_unit_type* input, size_type len);
380
391 search_results prefix_search(const key_type& prefix) const;
392
405 search_results prefix_search(const key_unit_type* prefix, size_type len) const;
406
412 size_type size() const;
413
414 bool empty() const noexcept;
415
419 void clear();
420
439 packed_type pack();
440
441private:
442 void insert_into_tree(trie_node& node, const key_unit_type* key, const key_unit_type* key_end, value_type value);
443
444 const trie_node* find_prefix_node(
445 const trie_node& node, const key_unit_type* prefix, const key_unit_type* prefix_end) const;
446
447 template<bool IsConst>
448 void find_prefix_node_with_stack(
449 std::vector<stack_item<IsConst>>& node_stack, mdds::detail::const_t<trie_node, IsConst>& node,
450 const key_unit_type* prefix, const key_unit_type* prefix_end) const;
451
452 template<bool IsConst>
453 key_type build_key_buffer_from_node_stack(const std::vector<stack_item<IsConst>>& node_stack) const;
454
455 void count_values(size_type& n, const trie_node& node) const;
456
457 bool descend_for_equality(const trie_node& left, const trie_node& right) const;
458
459private:
460 trie_node m_root;
461};
462
473template<typename KeyT, typename ValueT, typename TraitsT = trie::default_traits>
474class packed_trie_map
475{
476 using pack_value_type = typename TraitsT::pack_value_type;
477 using packed_type = std::vector<pack_value_type>;
478
479 friend class trie::detail::packed_iterator_base<packed_trie_map>;
480 friend class trie::detail::packed_search_results<packed_trie_map>;
481 friend class trie_map<KeyT, ValueT, TraitsT>;
482 friend struct trie::detail::dump_packed_buffer<packed_trie_map, packed_type>;
483
484public:
485 using traits_type = TraitsT;
486 typedef KeyT key_type;
487 typedef typename key_type::value_type key_unit_type;
488 typedef ValueT value_type;
489 typedef size_t size_type;
492
497 struct entry
498 {
499 const key_unit_type* key;
500 size_type keylen;
501 value_type value;
502
503 entry(const key_unit_type* _key, size_type _keylen, value_type _value)
504 : key(_key), keylen(_keylen), value(_value)
505 {}
506 };
507
508private:
509 using value_store_type = std::deque<value_type>;
510
512 static constexpr auto null_value = std::numeric_limits<pack_value_type>::max();
514 static constexpr auto max_value_pos = null_value - 1u;
515
516 struct trie_node
517 {
518 key_unit_type key;
519 const value_type* value;
520
521 std::deque<trie_node*> children;
522
523 trie_node(key_unit_type _key) : key(_key), value(nullptr)
524 {}
525 };
526
527 struct stack_item
528 {
529 const value_store_type* value_store = nullptr;
530
531 const pack_value_type* node_pos = nullptr;
532 const pack_value_type* child_pos = nullptr;
533 const pack_value_type* child_end = nullptr;
534
535 stack_item(
536 const value_store_type* _value_store, const pack_value_type* _node_pos, const pack_value_type* _child_pos,
537 const pack_value_type* _child_end)
538 : value_store(_value_store), node_pos(_node_pos), child_pos(_child_pos), child_end(_child_end)
539 {}
540
541 bool operator==(const stack_item& other) const
542 {
543 return value_store == other.value_store && node_pos == other.node_pos && child_pos == other.child_pos &&
544 child_end == other.child_end;
545 }
546
547 bool operator!=(const stack_item& other) const
548 {
549 return !operator==(other);
550 }
551
552 bool has_value() const
553 {
554 return *node_pos != null_value;
555 }
556
557 pack_value_type get_value_pos() const
558 {
559 return *node_pos;
560 }
561 };
562
563 typedef std::vector<stack_item> node_stack_type;
564 typedef std::deque<trie_node> node_pool_type;
565 typedef std::vector<std::tuple<size_t, key_unit_type>> child_offsets_type;
566
567 packed_trie_map(trie::detail::move_to_pack, trie_map<KeyT, ValueT, TraitsT>& from);
568
569public:
573 class const_node_type
574 {
575 friend class packed_trie_map;
576
577 const packed_type* m_packed = nullptr;
578 const value_store_type* m_value_store = nullptr;
579 const pack_value_type* m_pos = nullptr;
580
581 const_node_type(const packed_type* packed, const value_store_type* value_store, const pack_value_type* p);
582
583 public:
584 const_node_type() = default;
585 const_node_type(const const_node_type& other) = default;
586
587 const_node_type& operator=(const const_node_type& other);
588
595 bool valid() const;
596
603 bool has_child() const;
604
610 bool has_value() const;
611
621 const value_type& value() const;
622
632 const_node_type child(key_unit_type c) const;
633 };
634
635 packed_trie_map();
636
650 packed_trie_map(const entry* entries, size_type entry_size);
651
664
665 packed_trie_map(const packed_trie_map& other);
666
667 packed_trie_map(packed_trie_map&& other);
668
669 packed_trie_map& operator=(packed_trie_map other);
670
671 bool operator==(const packed_trie_map& other) const;
672
673 bool operator!=(const packed_trie_map& other) const;
674
675 const_iterator begin() const;
676
677 const_iterator end() const;
678
679 const_iterator cbegin() const;
680
681 const_iterator cend() const;
682
691 const_iterator find(const key_type& key) const;
692
703 const_iterator find(const key_unit_type* input, size_type len) const;
704
714 search_results prefix_search(const key_type& prefix) const;
715
728 search_results prefix_search(const key_unit_type* prefix, size_type len) const;
729
735 size_type size() const noexcept;
736
737 bool empty() const noexcept;
738
739 void swap(packed_trie_map& other);
740
746 const_node_type root_node() const;
747
753 template<typename FuncT = trie::value_serializer<value_type>>
754 void save_state(std::ostream& os) const;
755
762 template<typename FuncT = trie::value_serializer<value_type>>
763 void load_state(std::istream& is);
764
771 std::string dump_structure(trie::dump_structure_type type) const;
772
773private:
774 void dump_trie_traversal(std::ostream& os) const;
775
776 node_stack_type get_root_stack() const;
777
778 void traverse_range(
779 trie_node& root, node_pool_type& node_pool, const entry* start, const entry* end, size_type pos);
780
781 size_type compact_node(const trie_node& node);
782
783 template<typename ModeT, typename NodeT>
784 size_type compact_node(ModeT, NodeT& node);
785
786 void check_value_size_or_throw() const;
787
788 size_type push_value_to_store(trie::detail::copy_to_pack, const value_type& value);
789 size_type push_value_to_store(trie::detail::move_to_pack, value_type& value);
790
791 void push_child_offsets(size_type offset, const child_offsets_type& child_offsets);
792
793 void init_pack();
794 void compact(const trie_node& root);
795
796 template<typename ModeT, typename NodeT>
797 void compact(ModeT, NodeT& root);
798
799 template<typename _Handler>
800 void traverse_tree(_Handler hdl) const;
801
802private:
803 value_store_type m_value_store;
804 packed_type m_packed;
805};
806
807} // namespace mdds
808
809#include "trie_map_def.inl"
810
811/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const value_type & value() const
const_node_type child(key_unit_type c) const
Definition trie_map.hpp:475
packed_trie_map(const entry *entries, size_type entry_size)
packed_trie_map(const trie_map< KeyT, ValueT, TraitsT > &other)
search_results prefix_search(const key_type &prefix) const
void save_state(std::ostream &os) const
size_type size() const noexcept
const_iterator find(const key_unit_type *input, size_type len) const
std::string dump_structure(trie::dump_structure_type type) const
const_iterator find(const key_type &key) const
search_results prefix_search(const key_unit_type *prefix, size_type len) const
Definition trie_map_itr.hpp:341
Definition trie_map_itr.hpp:65
Definition trie_map_itr.hpp:316
Definition trie_map_itr.hpp:465
Definition trie_map_itr.hpp:762
Definition trie_map_itr.hpp:406
Definition trie_map.hpp:218
const_node_type child(key_unit_type c) const
const value_type & value() const
Definition trie_map.hpp:145
void insert(const key_unit_type *key, size_type len, value_type value)
bool erase(const key_unit_type *key, size_type len)
const_iterator find(const key_unit_type *input, size_type len) const
packed_type pack()
const_node_type root_node() const
search_results prefix_search(const key_unit_type *prefix, size_type len) const
size_type size() const
search_results prefix_search(const key_type &prefix) const
iterator find(const key_type &key)
const_iterator find(const key_type &key) const
void insert(const key_type &key, value_type value)
iterator find(const key_unit_type *input, size_type len)
Definition global.hpp:122
Definition global.hpp:158
Definition trie_map.hpp:102
uintptr_t pack_value_type
Definition trie_map.hpp:112
Definition trie_map.hpp:26
Definition trie_map.hpp:34
Definition trie_map_itr.hpp:46
Definition trie_map.hpp:30
Definition trie_map.hpp:41
Definition trie_map.hpp:87
Definition trie_map.hpp:54