mdds
Loading...
Searching...
No Matches
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
41namespace mdds {
42
43namespace trie {
44
45namespace detail {
46
48{
49};
50
52{
53};
54
55template<typename TrieT, typename PackedT>
57
58} // namespace detail
59
61template<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
74template<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
88template<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
107template<typename T, typename U = void>
111
112template<typename T>
113struct value_serializer<T, typename std::enable_if<mdds::detail::has_value_type<T>::value>::type>
115{
116};
117
118template<>
119struct value_serializer<std::string> : variable_value_serializer<std::string>
120{
121};
122
124{
134 using pack_value_type = uintptr_t;
135};
136
140enum class dump_structure_type
141{
146 packed_buffer,
147
151 trie_traversal,
152};
153
154} // namespace trie
155
156template<typename KeyT, typename ValueT, typename TraitsT>
157class packed_trie_map;
158
165template<typename KeyT, typename ValueT, typename TraitsT = trie::default_traits>
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>;
172 friend class trie::detail::iterator<trie_map>;
176
177public:
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
189private:
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
235public:
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:
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
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
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
462
463private:
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
481private:
482 trie_node m_root;
483};
484
495template<typename KeyT, typename ValueT, typename TraitsT = trie::default_traits>
497{
498 using pack_value_type = typename TraitsT::pack_value_type;
499 using packed_type = std::vector<pack_value_type>;
500
503 friend class trie_map<KeyT, ValueT, TraitsT>;
504 friend struct trie::detail::dump_packed_buffer<packed_trie_map, packed_type>;
505
506public:
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
530private:
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
591public:
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
658
672 packed_trie_map(const entry* entries, size_type entry_size);
673
686
687 packed_trie_map(const packed_trie_map& other);
688
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
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
795private:
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
824private:
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.hpp:596
const value_type & value() const
const_node_type child(key_unit_type c) const
Definition trie_map.hpp:497
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
size_type size() const noexcept
const_iterator find(const key_unit_type *input, size_type len) 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:365
Definition trie_map_itr.hpp:89
Definition trie_map_itr.hpp:340
Definition trie_map_itr.hpp:489
Definition trie_map_itr.hpp:786
Definition trie_map_itr.hpp:430
Definition trie_map.hpp:240
const_node_type child(key_unit_type c) const
const value_type & value() const
Definition trie_map.hpp:167
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:146
Definition global.hpp:182
Definition trie_map.hpp:520
Definition trie_map.hpp:124
uintptr_t pack_value_type
Definition trie_map.hpp:134
Definition trie_map.hpp:48
Definition trie_map.hpp:56
Definition trie_map_itr.hpp:70
Definition trie_map.hpp:52
Definition trie_map.hpp:63
Definition trie_map.hpp:109
Definition trie_map.hpp:76