mdds
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 
19 namespace mdds {
20 
21 namespace trie {
22 
23 namespace detail {
24 
26 {
27 };
28 
30 {
31 };
32 
33 template<typename TrieT, typename PackedT>
35 
36 } // namespace detail
37 
39 template<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 
52 template<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 
66 template<typename T>
68 {
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 
85 template<typename T, typename U = void>
87 {
88 };
89 
90 template<typename T>
91 struct value_serializer<T, typename std::enable_if<mdds::detail::has_value_type<T>::value>::type>
93 {
94 };
95 
96 template<>
97 struct value_serializer<std::string> : variable_value_serializer<std::string>
98 {
99 };
100 
102 {
112  using pack_value_type = uintptr_t;
113 };
114 
118 enum class dump_structure_type
119 {
124  packed_buffer,
125 
129  trie_traversal,
130 };
131 
132 } // namespace trie
133 
134 template<typename KeyT, typename ValueT, typename TraitsT>
136 
143 template<typename KeyT, typename ValueT, typename TraitsT = trie::default_traits>
144 class trie_map
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>;
149  friend class trie::detail::const_iterator<trie_map>;
150  friend class trie::detail::iterator<trie_map>;
151  friend class trie::detail::search_results<trie_map>;
154 
155 public:
156  using traits_type = TraitsT;
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 
166 
167 private:
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 
213 public:
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 
280  trie_map();
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 
306  const_node_type root_node() const;
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 
441 private:
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 
459 private:
460  trie_node m_root;
461 };
462 
473 template<typename KeyT, typename ValueT, typename TraitsT = trie::default_traits>
474 class 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 
484 public:
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 
508 private:
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 
569 public:
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 
663  packed_trie_map(const trie_map<KeyT, ValueT, TraitsT>& other);
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 
773 private:
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 
802 private:
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: */
Definition: trie_map_itr.hpp:464
Definition: trie_map.hpp:573
const_node_type root_node() const
Definition: trie_map_itr.hpp:315
void insert(const key_type &key, value_type value)
Definition: trie_map.hpp:86
search_results prefix_search(const key_type &prefix) const
Definition: trie_map_itr.hpp:64
Definition: trie_map_itr.hpp:312
uintptr_t pack_value_type
Definition: trie_map.hpp:112
Definition: trie_map.hpp:497
Definition: trie_map_itr.hpp:61
Definition: trie_map.hpp:135
Definition: global.hpp:158
Definition: trie_map.hpp:53
size_type size() const
Definition: trie_map.hpp:101
Definition: global.hpp:122
Definition: trie_map.hpp:29
const_node_type child(key_unit_type c) const
Definition: trie_map.hpp:144
Definition: trie_map.hpp:217
packed_type pack()
Definition: cref_wrapper.hpp:12
Definition: trie_map.hpp:34
Definition: trie_map_itr.hpp:46
Definition: trie_map.hpp:40
Definition: trie_map.hpp:25
bool erase(const key_unit_type *key, size_type len)
const value_type & value() const
const_iterator find(const key_type &key) const
Definition: trie_map_itr.hpp:461