mdds
trie_map.hpp
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
3  *
4  * Copyright (c) 2015-2020 Kohei Yoshida
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following
13  * conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  *
27  ************************************************************************/
28 
29 #ifndef INCLUDED_MDDS_TRIE_MAP_HPP
30 #define INCLUDED_MDDS_TRIE_MAP_HPP
31 
32 #include "trie_map_itr.hpp"
33 
34 #include <vector>
35 #include <string>
36 #include <deque>
37 #include <map>
38 #include <memory>
39 #include <limits>
40 
41 namespace mdds {
42 
43 namespace trie {
44 
45 namespace detail {
46 
48 {
49 };
50 
52 {
53 };
54 
55 template<typename TrieT, typename PackedT>
57 
58 } // namespace detail
59 
61 template<typename T>
63 {
64  static constexpr bool variable_size = false;
65 
66  static constexpr size_t value_size = sizeof(T);
67 
68  static void write(std::ostream& os, const T& v);
69 
70  static void read(std::istream& is, size_t n, T& v);
71 };
72 
74 template<typename T>
76 {
77  static constexpr bool variable_size = true;
78 
79  static void write(std::ostream& os, const T& v);
80 
81  static void read(std::istream& is, size_t n, T& v);
82 };
83 
88 template<typename T>
90 {
92 
93  static constexpr bool variable_size = true;
94 
95  static void write(std::ostream& os, const T& v);
96 
97  static void read(std::istream& is, size_t n, T& v);
98 };
99 
107 template<typename T, typename U = void>
109 {
110 };
111 
112 template<typename T>
113 struct value_serializer<T, typename std::enable_if<mdds::detail::has_value_type<T>::value>::type>
115 {
116 };
117 
118 template<>
119 struct value_serializer<std::string> : variable_value_serializer<std::string>
120 {
121 };
122 
124 {
134  using pack_value_type = uintptr_t;
135 };
136 
140 enum class dump_structure_type
141 {
146  packed_buffer,
147 
151  trie_traversal,
152 };
153 
154 } // namespace trie
155 
156 template<typename KeyT, typename ValueT, typename TraitsT>
158 
165 template<typename KeyT, typename ValueT, typename TraitsT = trie::default_traits>
166 class trie_map
167 {
168  friend class packed_trie_map<KeyT, ValueT, TraitsT>;
169  friend class trie::detail::iterator_base<trie_map, true>;
170  friend class trie::detail::iterator_base<trie_map, false>;
171  friend class trie::detail::const_iterator<trie_map>;
172  friend class trie::detail::iterator<trie_map>;
173  friend class trie::detail::search_results<trie_map>;
176 
177 public:
178  using traits_type = TraitsT;
180  typedef KeyT key_type;
181  typedef typename key_type::value_type key_unit_type;
182  typedef ValueT value_type;
183  typedef size_t size_type;
184 
188 
189 private:
190  struct trie_node
191  {
192  typedef std::map<key_unit_type, trie_node> children_type;
193 
194  children_type children;
195  value_type value;
196  bool has_value;
197 
198  trie_node();
199  trie_node(const trie_node& other);
200  trie_node(trie_node&& other);
201 
202  void swap(trie_node& other);
203  };
204 
205  template<bool IsConst>
206  struct stack_item
207  {
208  using _is_const = std::bool_constant<IsConst>;
209 
210  using child_pos_type =
212 
213  using trie_node_type = typename mdds::detail::const_or_not<trie_node, _is_const>::type;
214 
215  trie_node_type* node;
216  child_pos_type child_pos;
217 
218  stack_item(trie_node_type* _node, const child_pos_type& _child_pos) : node(_node), child_pos(_child_pos)
219  {}
220 
221  bool operator==(const stack_item& r) const
222  {
223  return node == r.node && child_pos == r.child_pos;
224  }
225 
226  bool operator!=(const stack_item& r) const
227  {
228  return !operator==(r);
229  }
230  };
231 
232  using const_node_stack_type = std::vector<stack_item<true>>;
233  using node_stack_type = std::vector<stack_item<false>>;
234 
235 public:
240  {
241  friend class trie_map;
242 
243  const trie_node* m_ref_node = nullptr;
244 
245  const_node_type(const trie_node* ref_node);
246 
247  public:
248  const_node_type();
249  const_node_type(const const_node_type& other);
250 
251  const_node_type& operator=(const const_node_type& other);
252 
259  bool valid() const;
260 
267  bool has_child() const;
268 
274  bool has_value() const;
275 
285  const value_type& value() const;
286 
296  const_node_type child(key_unit_type c) const;
297  };
298 
302  trie_map();
303 
304  trie_map(const trie_map& other);
305 
306  trie_map(trie_map&& other);
307 
308  const_iterator begin() const;
309 
310  iterator begin();
311 
312  const_iterator end() const;
313 
314  iterator end();
315 
316  trie_map& operator=(trie_map other);
317 
318  bool operator==(const trie_map& other) const;
319  bool operator!=(const trie_map& other) const;
320 
321  void swap(trie_map& other);
322 
328  const_node_type root_node() const;
329 
336  void insert(const key_type& key, value_type value);
337 
346  void insert(const key_unit_type* key, size_type len, value_type value);
347 
357  bool erase(const key_unit_type* key, size_type len);
358 
367  const_iterator find(const key_type& key) const;
368 
379  const_iterator find(const key_unit_type* input, size_type len) const;
380 
389  iterator find(const key_type& key);
390 
401  iterator find(const key_unit_type* input, size_type len);
402 
413  search_results prefix_search(const key_type& prefix) const;
414 
427  search_results prefix_search(const key_unit_type* prefix, size_type len) const;
428 
434  size_type size() const;
435 
436  bool empty() const noexcept;
437 
441  void clear();
442 
461  packed_type pack();
462 
463 private:
464  void insert_into_tree(trie_node& node, const key_unit_type* key, const key_unit_type* key_end, value_type value);
465 
466  const trie_node* find_prefix_node(
467  const trie_node& node, const key_unit_type* prefix, const key_unit_type* prefix_end) const;
468 
469  template<bool IsConst>
470  void find_prefix_node_with_stack(
471  std::vector<stack_item<IsConst>>& node_stack, mdds::detail::const_t<trie_node, IsConst>& node,
472  const key_unit_type* prefix, const key_unit_type* prefix_end) const;
473 
474  template<bool IsConst>
475  key_type build_key_buffer_from_node_stack(const std::vector<stack_item<IsConst>>& node_stack) const;
476 
477  void count_values(size_type& n, const trie_node& node) const;
478 
479  bool descend_for_equality(const trie_node& left, const trie_node& right) const;
480 
481 private:
482  trie_node m_root;
483 };
484 
495 template<typename KeyT, typename ValueT, typename TraitsT = trie::default_traits>
496 class packed_trie_map
497 {
498  using pack_value_type = typename TraitsT::pack_value_type;
499  using packed_type = std::vector<pack_value_type>;
500 
501  friend class trie::detail::packed_iterator_base<packed_trie_map>;
502  friend class trie::detail::packed_search_results<packed_trie_map>;
503  friend class trie_map<KeyT, ValueT, TraitsT>;
504  friend struct trie::detail::dump_packed_buffer<packed_trie_map, packed_type>;
505 
506 public:
507  using traits_type = TraitsT;
508  typedef KeyT key_type;
509  typedef typename key_type::value_type key_unit_type;
510  typedef ValueT value_type;
511  typedef size_t size_type;
514 
519  struct entry
520  {
521  const key_unit_type* key;
522  size_type keylen;
523  value_type value;
524 
525  entry(const key_unit_type* _key, size_type _keylen, value_type _value)
526  : key(_key), keylen(_keylen), value(_value)
527  {}
528  };
529 
530 private:
531  using value_store_type = std::deque<value_type>;
532 
534  static constexpr auto null_value = std::numeric_limits<pack_value_type>::max();
536  static constexpr auto max_value_pos = null_value - 1u;
537 
538  struct trie_node
539  {
540  key_unit_type key;
541  const value_type* value;
542 
543  std::deque<trie_node*> children;
544 
545  trie_node(key_unit_type _key) : key(_key), value(nullptr)
546  {}
547  };
548 
549  struct stack_item
550  {
551  const value_store_type* value_store = nullptr;
552 
553  const pack_value_type* node_pos = nullptr;
554  const pack_value_type* child_pos = nullptr;
555  const pack_value_type* child_end = nullptr;
556 
557  stack_item(
558  const value_store_type* _value_store, const pack_value_type* _node_pos, const pack_value_type* _child_pos,
559  const pack_value_type* _child_end)
560  : value_store(_value_store), node_pos(_node_pos), child_pos(_child_pos), child_end(_child_end)
561  {}
562 
563  bool operator==(const stack_item& other) const
564  {
565  return value_store == other.value_store && node_pos == other.node_pos && child_pos == other.child_pos &&
566  child_end == other.child_end;
567  }
568 
569  bool operator!=(const stack_item& other) const
570  {
571  return !operator==(other);
572  }
573 
574  bool has_value() const
575  {
576  return *node_pos != null_value;
577  }
578 
579  pack_value_type get_value_pos() const
580  {
581  return *node_pos;
582  }
583  };
584 
585  typedef std::vector<stack_item> node_stack_type;
586  typedef std::deque<trie_node> node_pool_type;
587  typedef std::vector<std::tuple<size_t, key_unit_type>> child_offsets_type;
588 
589  packed_trie_map(trie::detail::move_to_pack, trie_map<KeyT, ValueT, TraitsT>& from);
590 
591 public:
596  {
597  friend class packed_trie_map;
598 
599  const packed_type* m_packed = nullptr;
600  const value_store_type* m_value_store = nullptr;
601  const pack_value_type* m_pos = nullptr;
602 
603  const_node_type(const packed_type* packed, const value_store_type* value_store, const pack_value_type* p);
604 
605  public:
606  const_node_type() = default;
607  const_node_type(const const_node_type& other) = default;
608 
609  const_node_type& operator=(const const_node_type& other);
610 
617  bool valid() const;
618 
625  bool has_child() const;
626 
632  bool has_value() const;
633 
643  const value_type& value() const;
644 
654  const_node_type child(key_unit_type c) const;
655  };
656 
657  packed_trie_map();
658 
672  packed_trie_map(const entry* entries, size_type entry_size);
673 
685  packed_trie_map(const trie_map<KeyT, ValueT, TraitsT>& other);
686 
687  packed_trie_map(const packed_trie_map& other);
688 
689  packed_trie_map(packed_trie_map&& other);
690 
691  packed_trie_map& operator=(packed_trie_map other);
692 
693  bool operator==(const packed_trie_map& other) const;
694 
695  bool operator!=(const packed_trie_map& other) const;
696 
697  const_iterator begin() const;
698 
699  const_iterator end() const;
700 
701  const_iterator cbegin() const;
702 
703  const_iterator cend() const;
704 
713  const_iterator find(const key_type& key) const;
714 
725  const_iterator find(const key_unit_type* input, size_type len) const;
726 
736  search_results prefix_search(const key_type& prefix) const;
737 
750  search_results prefix_search(const key_unit_type* prefix, size_type len) const;
751 
757  size_type size() const noexcept;
758 
759  bool empty() const noexcept;
760 
761  void swap(packed_trie_map& other);
762 
768  const_node_type root_node() const;
769 
775  template<typename FuncT = trie::value_serializer<value_type>>
776  void save_state(std::ostream& os) const;
777 
784  template<typename FuncT = trie::value_serializer<value_type>>
785  void load_state(std::istream& is);
786 
793  std::string dump_structure(trie::dump_structure_type type) const;
794 
795 private:
796  void dump_trie_traversal(std::ostream& os) const;
797 
798  node_stack_type get_root_stack() const;
799 
800  void traverse_range(
801  trie_node& root, node_pool_type& node_pool, const entry* start, const entry* end, size_type pos);
802 
803  size_type compact_node(const trie_node& node);
804 
805  template<typename ModeT, typename NodeT>
806  size_type compact_node(ModeT, NodeT& node);
807 
808  void check_value_size_or_throw() const;
809 
810  size_type push_value_to_store(trie::detail::copy_to_pack, const value_type& value);
811  size_type push_value_to_store(trie::detail::move_to_pack, value_type& value);
812 
813  void push_child_offsets(size_type offset, const child_offsets_type& child_offsets);
814 
815  void init_pack();
816  void compact(const trie_node& root);
817 
818  template<typename ModeT, typename NodeT>
819  void compact(ModeT, NodeT& root);
820 
821  template<typename _Handler>
822  void traverse_tree(_Handler hdl) const;
823 
824 private:
825  value_store_type m_value_store;
826  packed_type m_packed;
827 };
828 
829 } // namespace mdds
830 
831 #include "trie_map_def.inl"
832 
833 #endif
834 
835 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition: trie_map_itr.hpp:488
Definition: trie_map.hpp:595
const_node_type root_node() const
Definition: trie_map_itr.hpp:339
void insert(const key_type &key, value_type value)
Definition: trie_map.hpp:108
search_results prefix_search(const key_type &prefix) const
Definition: trie_map_itr.hpp:88
Definition: trie_map_itr.hpp:336
uintptr_t pack_value_type
Definition: trie_map.hpp:134
Definition: trie_map.hpp:519
Definition: trie_map_itr.hpp:85
Definition: trie_map.hpp:157
Definition: global.hpp:182
Definition: trie_map.hpp:75
size_type size() const
Definition: trie_map.hpp:123
Definition: global.hpp:146
Definition: trie_map.hpp:51
const_node_type child(key_unit_type c) const
Definition: trie_map.hpp:166
Definition: trie_map.hpp:239
packed_type pack()
Definition: cref_wrapper.hpp:34
Definition: trie_map.hpp:56
Definition: trie_map_itr.hpp:70
Definition: trie_map.hpp:62
Definition: trie_map.hpp:47
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:485