mdds
trie_map.hpp
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
3  *
4  * Copyright (c) 2015-2016 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 
39 namespace mdds {
40 
41 namespace trie {
42 
48 {
50  typedef std::string key_type;
51 
58  typedef std::string key_buffer_type;
59 
65  typedef char key_unit_type;
66 
76  static key_buffer_type to_key_buffer(const key_unit_type* str, size_t length)
77  {
78  return key_buffer_type(str, length);
79  }
80 
89  static key_buffer_type to_key_buffer(const key_type& key)
90  {
91  return key_buffer_type(key);
92  }
93 
94  static const key_unit_type* buffer_data(const key_buffer_type& buf)
95  {
96  return buf.data();
97  }
98 
99  static size_t buffer_size(const key_buffer_type& buf)
100  {
101  return buf.size();
102  }
103 
111  static void push_back(key_buffer_type& buffer, key_unit_type c)
112  {
113  buffer.push_back(c);
114  }
115 
122  static void pop_back(key_buffer_type& buffer)
123  {
124  buffer.pop_back();
125  }
126 
135  static key_type to_key(const key_buffer_type& buf)
136  {
137  return buf;
138  }
139 };
140 
141 }
142 
143 template<typename _KeyTrait, typename _ValueT>
145 
152 template<typename _KeyTrait, typename _ValueT>
153 class trie_map
154 {
155  friend class packed_trie_map<_KeyTrait, _ValueT>;
156  friend class trie::detail::iterator_base<trie_map>;
157  friend class trie::detail::search_results<trie_map>;
158 
159 public:
161  typedef _KeyTrait key_trait_type;
162  typedef typename key_trait_type::key_type key_type;
163  typedef typename key_trait_type::key_buffer_type key_buffer_type;
164  typedef typename key_trait_type::key_unit_type key_unit_type;
165  typedef _ValueT value_type;
166  typedef size_t size_type;
167  typedef std::pair<key_type, value_type> key_value_type;
168 
171 
172 private:
173 
174  struct trie_node
175  {
176  typedef std::map<key_unit_type, trie_node> children_type;
177 
178  children_type children;
179  value_type value;
180  bool has_value;
181 
182  trie_node() : value(value_type()), has_value(false) {}
183  };
184 
185  struct stack_item
186  {
187  typedef typename trie_node::children_type::const_iterator child_pos_type;
188  const trie_node* node;
189  child_pos_type child_pos;
190 
191  stack_item(const trie_node* _node, const child_pos_type& _child_pos) :
192  node(_node), child_pos(_child_pos) {}
193 
194  bool operator== (const stack_item& r) const
195  {
196  return node == r.node && child_pos == r.child_pos;
197  }
198 
199  bool operator!= (const stack_item& r) const
200  {
201  return !operator== (r);
202  }
203  };
204 
205  typedef std::vector<stack_item> node_stack_type;
206 
207 public:
208 
212  trie_map();
213 
214  const_iterator begin() const;
215 
216  const_iterator end() const;
217 
224  void insert(const key_type& key, const value_type& value);
225 
234  void insert(const key_unit_type* key, size_type len, const value_type& value);
235 
245  bool erase(const key_unit_type* key, size_type len);
246 
255  const_iterator find(const key_type& key) const;
256 
267  const_iterator find(const key_unit_type* input, size_type len) const;
268 
278  search_results prefix_search(const key_type& prefix) const;
279 
292  search_results prefix_search(const key_unit_type* prefix, size_type len) const;
293 
299  size_type size() const;
300 
304  void clear();
305 
313  packed_type pack() const;
314 
315 private:
316  void insert_into_tree(
317  trie_node& node, const key_unit_type* key, const key_unit_type* key_end, const value_type& value);
318 
319  const trie_node* find_prefix_node(
320  const trie_node& node, const key_unit_type* prefix, const key_unit_type* prefix_end) const;
321 
322  void find_prefix_node_with_stack(
323  node_stack_type& node_stack,
324  const trie_node& node, const key_unit_type* prefix, const key_unit_type* prefix_end) const;
325 
326  void count_values(size_type& n, const trie_node& node) const;
327 
328 private:
329  trie_node m_root;
330 };
331 
342 template<typename _KeyTrait, typename _ValueT>
343 class packed_trie_map
344 {
345  friend class trie::detail::packed_iterator_base<packed_trie_map>;
346  friend class trie::detail::packed_search_results<packed_trie_map>;
347 
348 public:
349  typedef _KeyTrait key_trait_type;
350  typedef typename key_trait_type::key_type key_type;
351  typedef typename key_trait_type::key_buffer_type key_buffer_type;
352  typedef typename key_trait_type::key_unit_type key_unit_type;
353  typedef _ValueT value_type;
354  typedef size_t size_type;
355  typedef std::pair<key_type, value_type> key_value_type;
358 
363  struct entry
364  {
365  const key_unit_type* key;
366  size_type keylen;
367  value_type value;
368 
369  entry(const key_unit_type* _key, size_type _keylen, value_type _value) :
370  key(_key), keylen(_keylen), value(_value) {}
371  };
372 
373 private:
374  struct trie_node
375  {
376  key_unit_type key;
377  const value_type* value;
378 
379  std::deque<trie_node*> children;
380 
381  trie_node(key_unit_type _key) : key(_key), value(nullptr) {}
382  };
383 
384  struct stack_item
385  {
386  const uintptr_t* node_pos;
387  const uintptr_t* child_pos;
388  const uintptr_t* child_end;
389 
390  stack_item(const uintptr_t* _node_pos, const uintptr_t* _child_pos, const uintptr_t* _child_end) :
391  node_pos(_node_pos), child_pos(_child_pos), child_end(_child_end) {}
392 
393  bool operator== (const stack_item& other) const
394  {
395  return node_pos == other.node_pos && child_pos == other.child_pos;
396  }
397 
398  bool operator!= (const stack_item& other) const
399  {
400  return !operator==(other);
401  }
402 
403  bool has_value() const
404  {
405  const value_type* pv = reinterpret_cast<const value_type*>(*node_pos);
406  return pv;
407  }
408 
409  const value_type* get_value() const
410  {
411  return reinterpret_cast<const value_type*>(*node_pos);
412  }
413  };
414 
415  typedef std::vector<stack_item> node_stack_type;
416 
417  typedef std::deque<trie_node> node_pool_type;
418  typedef std::vector<uintptr_t> packed_type;
419  typedef std::deque<value_type> value_store_type;
420  typedef std::vector<std::tuple<size_t, key_unit_type>> child_offsets_type;
421 
422 public:
423 
427  packed_trie_map() = delete;
428 
439  packed_trie_map(const entry* entries, size_type entry_size);
440 
447  packed_trie_map(const trie_map<key_trait_type, value_type>& other);
448 
449  const_iterator begin() const;
450 
451  const_iterator end() const;
452 
461  const_iterator find(const key_type& key) const;
462 
473  const_iterator find(const key_unit_type* input, size_type len) const;
474 
484  search_results prefix_search(const key_type& prefix) const;
485 
498  search_results prefix_search(const key_unit_type* prefix, size_type len) const;
499 
505  size_type size() const;
506 
507 private:
508  node_stack_type get_root_stack() const;
509 
510  void traverse_range(
511  trie_node& root, node_pool_type& node_pool, const entry* start, const entry* end,
512  size_type pos);
513 
514  size_type compact_node(const trie_node& node);
515  size_type compact_node(const typename trie_map<_KeyTrait, _ValueT>::trie_node& node);
516 
517  void push_child_offsets(size_type offset, const child_offsets_type& child_offsets);
518 
519  void compact(const trie_node& root);
520  void compact(const typename trie_map<_KeyTrait, _ValueT>::trie_node& root);
521 
522  const uintptr_t* find_prefix_node(
523  const uintptr_t* p, const key_unit_type* prefix, const key_unit_type* prefix_end) const;
524 
525  void find_prefix_node_with_stack(
526  node_stack_type& node_stack,
527  const uintptr_t* p, const key_unit_type* prefix, const key_unit_type* prefix_end) const;
528 
529 #ifdef MDDS_TRIE_MAP_DEBUG
530  void dump_node(key_buffer_type& buffer, const trie_node& node) const;
531  void dump_trie(const trie_node& root) const;
532  void dump_packed_trie(const std::vector<uintptr_t>& packed) const;
533 #endif
534 
535 private:
536  size_type m_entry_size;
537 
538  value_store_type m_value_store;
539  packed_type m_packed;
540 };
541 
542 }
543 
544 #include "trie_map_def.inl"
545 
546 #endif
547 
548 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition: trie_map_itr.hpp:387
std::string key_buffer_type
Definition: trie_map.hpp:58
static void pop_back(key_buffer_type &buffer)
Definition: trie_map.hpp:122
Definition: trie_map_itr.hpp:69
Definition: trie_map.hpp:363
Definition: trie_map.hpp:47
Definition: trie_map_itr.hpp:66
static key_type to_key(const key_buffer_type &buf)
Definition: trie_map.hpp:135
Definition: trie_map.hpp:144
char key_unit_type
Definition: trie_map.hpp:65
static key_buffer_type to_key_buffer(const key_type &key)
Definition: trie_map.hpp:89
Definition: trie_map.hpp:153
Definition: flat_segment_tree.hpp:46
static void push_back(key_buffer_type &buffer, key_unit_type c)
Definition: trie_map.hpp:111
static key_buffer_type to_key_buffer(const key_unit_type *str, size_t length)
Definition: trie_map.hpp:76
std::string key_type
Definition: trie_map.hpp:50
Definition: trie_map_itr.hpp:384