Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 1 | /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
| 2 | /* |
| 3 | * Copyright (c) 2011 University of California, Los Angeles |
| 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License version 2 as |
| 7 | * published by the Free Software Foundation; |
| 8 | * |
| 9 | * This program is distributed in the hope that it will be useful, |
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | * GNU General Public License for more details. |
| 13 | * |
| 14 | * You should have received a copy of the GNU General Public License |
| 15 | * along with this program; if not, write to the Free Software |
| 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 17 | * |
| 18 | * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu> |
| 19 | */ |
| 20 | |
Alexander Afanasyev | 9a98970 | 2012-06-29 17:44:00 -0700 | [diff] [blame] | 21 | #ifndef TRIE_H_ |
| 22 | #define TRIE_H_ |
| 23 | |
Spyridon Mastorakis | 53e922f | 2014-10-17 17:29:26 -0700 | [diff] [blame] | 24 | #include "ns3/ndnSIM/model/ndn-common.hpp" |
| 25 | |
Alexander Afanasyev | 9a98970 | 2012-06-29 17:44:00 -0700 | [diff] [blame] | 26 | #include "ns3/ptr.h" |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 27 | |
| 28 | #include <boost/intrusive/unordered_set.hpp> |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 29 | #include <boost/intrusive/list.hpp> |
Alexander Afanasyev | 9a98970 | 2012-06-29 17:44:00 -0700 | [diff] [blame] | 30 | #include <boost/intrusive/set.hpp> |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 31 | #include <boost/functional/hash.hpp> |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 32 | #include <boost/interprocess/smart_ptr/unique_ptr.hpp> |
Alexander Afanasyev | 0717901 | 2014-12-21 00:23:04 -0800 | [diff] [blame^] | 33 | #include <tuple> |
Alexander Afanasyev | 78057c3 | 2012-07-06 15:18:46 -0700 | [diff] [blame] | 34 | #include <boost/foreach.hpp> |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 35 | #include <boost/mpl/if.hpp> |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 36 | |
Alexander Afanasyev | 2b4c947 | 2012-08-09 15:00:38 -0700 | [diff] [blame] | 37 | namespace ns3 { |
| 38 | namespace ndn { |
| 39 | namespace ndnSIM { |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 40 | |
| 41 | ///////////////////////////////////////////////////// |
| 42 | // Allow customization for payload |
| 43 | // |
Alexander Afanasyev | 8566f45 | 2012-12-10 15:21:51 -0800 | [diff] [blame] | 44 | template<typename Payload, typename BasePayload = Payload> |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 45 | struct pointer_payload_traits { |
| 46 | typedef Payload payload_type; // general type of the payload |
| 47 | typedef Payload* storage_type; // how the payload is actually stored |
| 48 | typedef Payload* insert_type; // what parameter is inserted |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 49 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 50 | typedef Payload* return_type; // what is returned on access |
| 51 | typedef const Payload* const_return_type; // what is returned on const access |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 52 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 53 | typedef BasePayload* |
| 54 | base_type; // base type of the entry (when implementation details need to be hidden) |
| 55 | typedef const BasePayload* |
| 56 | const_base_type; // const base type of the entry (when implementation details need to be hidden) |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 57 | |
Alexander Afanasyev | 78057c3 | 2012-07-06 15:18:46 -0700 | [diff] [blame] | 58 | static Payload* empty_payload; |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 59 | }; |
| 60 | |
Alexander Afanasyev | 8566f45 | 2012-12-10 15:21:51 -0800 | [diff] [blame] | 61 | template<typename Payload, typename BasePayload> |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 62 | Payload* pointer_payload_traits<Payload, BasePayload>::empty_payload = 0; |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 63 | |
Alexander Afanasyev | 8566f45 | 2012-12-10 15:21:51 -0800 | [diff] [blame] | 64 | template<typename Payload, typename BasePayload = Payload> |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 65 | struct smart_pointer_payload_traits { |
| 66 | typedef Payload payload_type; |
| 67 | typedef ns3::Ptr<Payload> storage_type; |
| 68 | typedef ns3::Ptr<Payload> insert_type; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 69 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 70 | typedef ns3::Ptr<Payload> return_type; |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 71 | typedef ns3::Ptr<const Payload> const_return_type; |
Alexander Afanasyev | 8566f45 | 2012-12-10 15:21:51 -0800 | [diff] [blame] | 72 | |
| 73 | typedef ns3::Ptr<BasePayload> base_type; |
| 74 | typedef ns3::Ptr<const BasePayload> const_base_type; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 75 | |
Alexander Afanasyev | 78057c3 | 2012-07-06 15:18:46 -0700 | [diff] [blame] | 76 | static ns3::Ptr<Payload> empty_payload; |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 77 | }; |
| 78 | |
Alexander Afanasyev | 8566f45 | 2012-12-10 15:21:51 -0800 | [diff] [blame] | 79 | template<typename Payload, typename BasePayload> |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 80 | ns3::Ptr<Payload> smart_pointer_payload_traits<Payload, BasePayload>::empty_payload = 0; |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 81 | |
Alexander Afanasyev | 8566f45 | 2012-12-10 15:21:51 -0800 | [diff] [blame] | 82 | template<typename Payload, typename BasePayload = Payload> |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 83 | struct non_pointer_traits { |
| 84 | typedef Payload payload_type; |
| 85 | typedef Payload storage_type; |
| 86 | typedef const Payload& insert_type; // nothing to insert |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 87 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 88 | typedef Payload& return_type; |
| 89 | typedef const Payload& const_return_type; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 90 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 91 | typedef BasePayload& base_type; |
Alexander Afanasyev | 62304f2 | 2012-12-10 18:06:21 -0800 | [diff] [blame] | 92 | typedef const BasePayload& const_base_type; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 93 | |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 94 | static Payload empty_payload; |
| 95 | }; |
| 96 | |
Alexander Afanasyev | 8566f45 | 2012-12-10 15:21:51 -0800 | [diff] [blame] | 97 | template<typename Payload, typename BasePayload> |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 98 | Payload non_pointer_traits<Payload, BasePayload>::empty_payload = Payload(); |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 99 | |
| 100 | //////////////////////////////////////////////////// |
| 101 | // forward declarations |
| 102 | // |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 103 | template<typename FullKey, typename PayloadTraits, typename PolicyHook> |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 104 | class trie; |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 105 | |
Alexander Afanasyev | 30f60e3 | 2012-07-10 14:21:16 -0700 | [diff] [blame] | 106 | template<typename FullKey, typename PayloadTraits, typename PolicyHook> |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 107 | inline std::ostream& |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 108 | operator<<(std::ostream& os, const trie<FullKey, PayloadTraits, PolicyHook>& trie_node); |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 109 | |
Alexander Afanasyev | 30f60e3 | 2012-07-10 14:21:16 -0700 | [diff] [blame] | 110 | template<typename FullKey, typename PayloadTraits, typename PolicyHook> |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 111 | bool |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 112 | operator==(const trie<FullKey, PayloadTraits, PolicyHook>& a, |
| 113 | const trie<FullKey, PayloadTraits, PolicyHook>& b); |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 114 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 115 | template<typename FullKey, typename PayloadTraits, typename PolicyHook> |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 116 | std::size_t |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 117 | hash_value(const trie<FullKey, PayloadTraits, PolicyHook>& trie_node); |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 118 | |
| 119 | /////////////////////////////////////////////////// |
| 120 | // actual definition |
| 121 | // |
Alexander Afanasyev | 1cb4aad | 2012-08-09 14:58:16 -0700 | [diff] [blame] | 122 | template<class T, class NonConstT> |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 123 | class trie_iterator; |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 124 | |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 125 | template<class T> |
| 126 | class trie_point_iterator; |
| 127 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 128 | template<typename FullKey, typename PayloadTraits, typename PolicyHook> |
| 129 | class trie { |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 130 | public: |
Spyridon Mastorakis | 1f1cd5e | 2014-12-04 11:12:40 -0800 | [diff] [blame] | 131 | typedef typename FullKey::value_type Key; |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 132 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 133 | typedef trie* iterator; |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 134 | typedef const trie* const_iterator; |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 135 | |
Alexander Afanasyev | 1cb4aad | 2012-08-09 14:58:16 -0700 | [diff] [blame] | 136 | typedef trie_iterator<trie, trie> recursive_iterator; |
| 137 | typedef trie_iterator<const trie, trie> const_recursive_iterator; |
Alexander Afanasyev | 30f60e3 | 2012-07-10 14:21:16 -0700 | [diff] [blame] | 138 | |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 139 | typedef trie_point_iterator<trie> point_iterator; |
| 140 | typedef trie_point_iterator<const trie> const_point_iterator; |
| 141 | |
Alexander Afanasyev | 30f60e3 | 2012-07-10 14:21:16 -0700 | [diff] [blame] | 142 | typedef PayloadTraits payload_traits; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 143 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 144 | inline trie(const Key& key, size_t bucketSize = 1, size_t bucketIncrement = 1) |
| 145 | : key_(key) |
| 146 | , initialBucketSize_(bucketSize) |
| 147 | , bucketIncrement_(bucketIncrement) |
| 148 | , bucketSize_(initialBucketSize_) |
| 149 | , buckets_(new bucket_type[bucketSize_]) // cannot use normal pointer, because lifetime of |
| 150 | // buckets should be larger than lifetime of the |
| 151 | // container |
| 152 | , children_(bucket_traits(buckets_.get(), bucketSize_)) |
| 153 | , payload_(PayloadTraits::empty_payload) |
| 154 | , parent_(0) |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 155 | { |
| 156 | } |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 157 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 158 | inline ~trie() |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 159 | { |
| 160 | payload_ = PayloadTraits::empty_payload; // necessary for smart pointers... |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 161 | children_.clear_and_dispose(trie_delete_disposer()); |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 162 | } |
Alexander Afanasyev | 78057c3 | 2012-07-06 15:18:46 -0700 | [diff] [blame] | 163 | |
| 164 | void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 165 | clear() |
Alexander Afanasyev | 78057c3 | 2012-07-06 15:18:46 -0700 | [diff] [blame] | 166 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 167 | children_.clear_and_dispose(trie_delete_disposer()); |
Alexander Afanasyev | 78057c3 | 2012-07-06 15:18:46 -0700 | [diff] [blame] | 168 | } |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 169 | |
| 170 | template<class Predicate> |
| 171 | void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 172 | clear_if(Predicate cond) |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 173 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 174 | recursive_iterator trieNode(this); |
| 175 | recursive_iterator end(0); |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 176 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 177 | while (trieNode != end) { |
| 178 | if (cond(*trieNode)) { |
| 179 | trieNode = recursive_iterator(trieNode->erase()); |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 180 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 181 | trieNode++; |
| 182 | } |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 183 | } |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 184 | |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 185 | // actual entry |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 186 | friend bool operator==<>(const trie<FullKey, PayloadTraits, PolicyHook>& a, |
| 187 | const trie<FullKey, PayloadTraits, PolicyHook>& b); |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 188 | |
| 189 | friend std::size_t |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 190 | hash_value<>(const trie<FullKey, PayloadTraits, PolicyHook>& trie_node); |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 191 | |
| 192 | inline std::pair<iterator, bool> |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 193 | insert(const FullKey& key, typename PayloadTraits::insert_type payload) |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 194 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 195 | trie* trieNode = this; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 196 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 197 | BOOST_FOREACH (const Key& subkey, key) { |
| 198 | typename unordered_set::iterator item = trieNode->children_.find(subkey); |
| 199 | if (item == trieNode->children_.end()) { |
| 200 | trie* newNode = new trie(subkey, initialBucketSize_, bucketIncrement_); |
| 201 | // std::cout << "new " << newNode << "\n"; |
| 202 | newNode->parent_ = trieNode; |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 203 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 204 | if (trieNode->children_.size() >= trieNode->bucketSize_) { |
| 205 | trieNode->bucketSize_ += trieNode->bucketIncrement_; |
| 206 | trieNode->bucketIncrement_ *= 2; // increase bucketIncrement exponentially |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 207 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 208 | buckets_array newBuckets(new bucket_type[trieNode->bucketSize_]); |
| 209 | trieNode->children_.rehash(bucket_traits(newBuckets.get(), trieNode->bucketSize_)); |
| 210 | trieNode->buckets_.swap(newBuckets); |
| 211 | } |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 212 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 213 | std::pair<typename unordered_set::iterator, bool> ret = |
| 214 | trieNode->children_.insert(*newNode); |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 215 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 216 | trieNode = &(*ret.first); |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 217 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 218 | else |
| 219 | trieNode = &(*item); |
| 220 | } |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 221 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 222 | if (trieNode->payload_ == PayloadTraits::empty_payload) { |
| 223 | trieNode->payload_ = payload; |
| 224 | return std::make_pair(trieNode, true); |
| 225 | } |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 226 | else |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 227 | return std::make_pair(trieNode, false); |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 228 | } |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 229 | |
| 230 | /** |
| 231 | * @brief Removes payload (if it exists) and if there are no children, prunes parents trie |
| 232 | */ |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 233 | inline iterator |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 234 | erase() |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 235 | { |
| 236 | payload_ = PayloadTraits::empty_payload; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 237 | return prune(); |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 238 | } |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 239 | |
| 240 | /** |
| 241 | * @brief Do exactly as erase, but without erasing the payload |
| 242 | */ |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 243 | inline iterator |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 244 | prune() |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 245 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 246 | if (payload_ == PayloadTraits::empty_payload && children_.size() == 0) { |
| 247 | if (parent_ == 0) |
| 248 | return this; |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 249 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 250 | trie* parent = parent_; |
| 251 | parent->children_ |
| 252 | .erase_and_dispose(*this, |
| 253 | trie_delete_disposer()); // delete this; basically, committing a suicide |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 254 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 255 | return parent->prune(); |
| 256 | } |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 257 | return this; |
| 258 | } |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 259 | |
Alexander Afanasyev | 70426a0 | 2012-08-15 15:39:18 -0700 | [diff] [blame] | 260 | /** |
| 261 | * @brief Perform prune of the node, but without attempting to parent of the node |
| 262 | */ |
| 263 | inline void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 264 | prune_node() |
Alexander Afanasyev | 70426a0 | 2012-08-15 15:39:18 -0700 | [diff] [blame] | 265 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 266 | if (payload_ == PayloadTraits::empty_payload && children_.size() == 0) { |
| 267 | if (parent_ == 0) |
| 268 | return; |
Alexander Afanasyev | 70426a0 | 2012-08-15 15:39:18 -0700 | [diff] [blame] | 269 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 270 | trie* parent = parent_; |
| 271 | parent->children_ |
| 272 | .erase_and_dispose(*this, |
| 273 | trie_delete_disposer()); // delete this; basically, committing a suicide |
| 274 | } |
Alexander Afanasyev | 70426a0 | 2012-08-15 15:39:18 -0700 | [diff] [blame] | 275 | } |
| 276 | |
Alexander Afanasyev | 0717901 | 2014-12-21 00:23:04 -0800 | [diff] [blame^] | 277 | // inline std::tuple<const iterator, bool, const iterator> |
Alexander Afanasyev | 30f60e3 | 2012-07-10 14:21:16 -0700 | [diff] [blame] | 278 | // find (const FullKey &key) const |
| 279 | // { |
| 280 | // return const_cast<trie*> (this)->find (key); |
| 281 | // } |
Alexander Afanasyev | 78057c3 | 2012-07-06 15:18:46 -0700 | [diff] [blame] | 282 | |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 283 | /** |
| 284 | * @brief Perform the longest prefix match |
| 285 | * @param key the key for which to perform the longest prefix match |
| 286 | * |
| 287 | * @return ->second is true if prefix in ->first is longer than key |
| 288 | */ |
Alexander Afanasyev | 0717901 | 2014-12-21 00:23:04 -0800 | [diff] [blame^] | 289 | inline std::tuple<iterator, bool, iterator> |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 290 | find(const FullKey& key) |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 291 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 292 | trie* trieNode = this; |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 293 | iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0; |
| 294 | bool reachLast = true; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 295 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 296 | BOOST_FOREACH (const Key& subkey, key) { |
| 297 | typename unordered_set::iterator item = trieNode->children_.find(subkey); |
| 298 | if (item == trieNode->children_.end()) { |
| 299 | reachLast = false; |
| 300 | break; |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 301 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 302 | else { |
| 303 | trieNode = &(*item); |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 304 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 305 | if (trieNode->payload_ != PayloadTraits::empty_payload) |
| 306 | foundNode = trieNode; |
| 307 | } |
| 308 | } |
| 309 | |
Alexander Afanasyev | 0717901 | 2014-12-21 00:23:04 -0800 | [diff] [blame^] | 310 | return std::make_tuple(foundNode, reachLast, trieNode); |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 311 | } |
| 312 | |
| 313 | /** |
| 314 | * @brief Perform the longest prefix match satisfying preficate |
| 315 | * @param key the key for which to perform the longest prefix match |
| 316 | * |
| 317 | * @return ->second is true if prefix in ->first is longer than key |
| 318 | */ |
| 319 | template<class Predicate> |
Alexander Afanasyev | 0717901 | 2014-12-21 00:23:04 -0800 | [diff] [blame^] | 320 | inline std::tuple<iterator, bool, iterator> |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 321 | find_if(const FullKey& key, Predicate pred) |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 322 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 323 | trie* trieNode = this; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 324 | iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0; |
| 325 | bool reachLast = true; |
| 326 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 327 | BOOST_FOREACH (const Key& subkey, key) { |
| 328 | typename unordered_set::iterator item = trieNode->children_.find(subkey); |
| 329 | if (item == trieNode->children_.end()) { |
| 330 | reachLast = false; |
| 331 | break; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 332 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 333 | else { |
| 334 | trieNode = &(*item); |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 335 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 336 | if (trieNode->payload_ != PayloadTraits::empty_payload && pred(trieNode->payload_)) { |
| 337 | foundNode = trieNode; |
| 338 | } |
| 339 | } |
| 340 | } |
| 341 | |
Alexander Afanasyev | 0717901 | 2014-12-21 00:23:04 -0800 | [diff] [blame^] | 342 | return std::make_tuple(foundNode, reachLast, trieNode); |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 343 | } |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 344 | |
| 345 | /** |
| 346 | * @brief Find next payload of the sub-trie |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 347 | * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration |
| 348 | * ) |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 349 | */ |
| 350 | inline iterator |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 351 | find() |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 352 | { |
| 353 | if (payload_ != PayloadTraits::empty_payload) |
| 354 | return this; |
| 355 | |
Alexander Afanasyev | 30f60e3 | 2012-07-10 14:21:16 -0700 | [diff] [blame] | 356 | typedef trie<FullKey, PayloadTraits, PolicyHook> trie; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 357 | for (typename trie::unordered_set::iterator subnode = children_.begin(); |
| 358 | subnode != children_.end(); subnode++) |
| 359 | // BOOST_FOREACH (trie &subnode, children_) |
| 360 | { |
| 361 | iterator value = subnode->find(); |
| 362 | if (value != 0) |
| 363 | return value; |
| 364 | } |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 365 | |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 366 | return 0; |
| 367 | } |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 368 | |
| 369 | /** |
| 370 | * @brief Find next payload of the sub-trie satisfying the predicate |
| 371 | * @param pred predicate |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 372 | * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration |
| 373 | * ) |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 374 | */ |
| 375 | template<class Predicate> |
Alexander Afanasyev | 30f60e3 | 2012-07-10 14:21:16 -0700 | [diff] [blame] | 376 | inline const iterator |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 377 | find_if(Predicate pred) |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 378 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 379 | if (payload_ != PayloadTraits::empty_payload && pred(payload_)) |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 380 | return this; |
| 381 | |
Alexander Afanasyev | 30f60e3 | 2012-07-10 14:21:16 -0700 | [diff] [blame] | 382 | typedef trie<FullKey, PayloadTraits, PolicyHook> trie; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 383 | for (typename trie::unordered_set::iterator subnode = children_.begin(); |
| 384 | subnode != children_.end(); subnode++) |
| 385 | // BOOST_FOREACH (const trie &subnode, children_) |
| 386 | { |
| 387 | iterator value = subnode->find_if(pred); |
| 388 | if (value != 0) |
| 389 | return value; |
| 390 | } |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 391 | |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 392 | return 0; |
| 393 | } |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 394 | |
Alexander Afanasyev | eec89ba | 2013-07-19 16:34:30 -0700 | [diff] [blame] | 395 | /** |
| 396 | * @brief Find next payload of the sub-trie satisfying the predicate |
| 397 | * @param pred predicate |
| 398 | * |
| 399 | * This version check predicate only for the next level children |
| 400 | * |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 401 | * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration |
| 402 | *) |
Alexander Afanasyev | eec89ba | 2013-07-19 16:34:30 -0700 | [diff] [blame] | 403 | */ |
| 404 | template<class Predicate> |
| 405 | inline const iterator |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 406 | find_if_next_level(Predicate pred) |
Alexander Afanasyev | eec89ba | 2013-07-19 16:34:30 -0700 | [diff] [blame] | 407 | { |
| 408 | typedef trie<FullKey, PayloadTraits, PolicyHook> trie; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 409 | for (typename trie::unordered_set::iterator subnode = children_.begin(); |
| 410 | subnode != children_.end(); subnode++) { |
| 411 | if (pred(subnode->key())) { |
| 412 | return subnode->find(); |
Alexander Afanasyev | eec89ba | 2013-07-19 16:34:30 -0700 | [diff] [blame] | 413 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 414 | } |
Alexander Afanasyev | eec89ba | 2013-07-19 16:34:30 -0700 | [diff] [blame] | 415 | |
| 416 | return 0; |
| 417 | } |
| 418 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 419 | iterator |
| 420 | end() |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 421 | { |
| 422 | return 0; |
| 423 | } |
| 424 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 425 | const_iterator |
| 426 | end() const |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 427 | { |
| 428 | return 0; |
| 429 | } |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 430 | |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 431 | typename PayloadTraits::const_return_type |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 432 | payload() const |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 433 | { |
| 434 | return payload_; |
| 435 | } |
| 436 | |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 437 | typename PayloadTraits::return_type |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 438 | payload() |
Alexander Afanasyev | 78057c3 | 2012-07-06 15:18:46 -0700 | [diff] [blame] | 439 | { |
| 440 | return payload_; |
| 441 | } |
| 442 | |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 443 | void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 444 | set_payload(typename PayloadTraits::insert_type payload) |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 445 | { |
| 446 | payload_ = payload; |
| 447 | } |
Alexander Afanasyev | 0560eec | 2012-07-16 15:44:31 -0700 | [diff] [blame] | 448 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 449 | Key |
| 450 | key() const |
Alexander Afanasyev | 0560eec | 2012-07-16 15:44:31 -0700 | [diff] [blame] | 451 | { |
| 452 | return key_; |
| 453 | } |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 454 | |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 455 | inline void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 456 | PrintStat(std::ostream& os) const; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 457 | |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 458 | private: |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 459 | // The disposer object function |
| 460 | struct trie_delete_disposer { |
| 461 | void |
| 462 | operator()(trie* delete_this) |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 463 | { |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 464 | delete delete_this; |
| 465 | } |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 466 | }; |
| 467 | |
| 468 | template<class D> |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 469 | struct array_disposer { |
| 470 | void |
| 471 | operator()(D* array) |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 472 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 473 | delete[] array; |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 474 | } |
| 475 | }; |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 476 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 477 | friend std::ostream& operator<<<>(std::ostream& os, const trie& trie_node); |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 478 | |
| 479 | public: |
| 480 | PolicyHook policy_hook_; |
| 481 | |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 482 | private: |
Alexander Afanasyev | 30cb117 | 2012-07-06 10:47:39 -0700 | [diff] [blame] | 483 | boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_; |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 484 | |
| 485 | // necessary typedefs |
| 486 | typedef trie self_type; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 487 | typedef boost::intrusive::member_hook<trie, boost::intrusive::unordered_set_member_hook<>, |
| 488 | &trie::unordered_set_member_hook_> member_hook; |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 489 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 490 | typedef boost::intrusive::unordered_set<trie, member_hook> unordered_set; |
| 491 | typedef typename unordered_set::bucket_type bucket_type; |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 492 | typedef typename unordered_set::bucket_traits bucket_traits; |
| 493 | |
Alexander Afanasyev | 1cb4aad | 2012-08-09 14:58:16 -0700 | [diff] [blame] | 494 | template<class T, class NonConstT> |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 495 | friend class trie_iterator; |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 496 | |
| 497 | template<class T> |
| 498 | friend class trie_point_iterator; |
| 499 | |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 500 | //////////////////////////////////////////////// |
| 501 | // Actual data |
| 502 | //////////////////////////////////////////////// |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 503 | |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 504 | Key key_; ///< name component |
| 505 | |
| 506 | size_t initialBucketSize_; |
| 507 | size_t bucketIncrement_; |
| 508 | |
| 509 | size_t bucketSize_; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 510 | typedef boost::interprocess::unique_ptr<bucket_type, array_disposer<bucket_type>> buckets_array; |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 511 | buckets_array buckets_; |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 512 | unordered_set children_; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 513 | |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 514 | typename PayloadTraits::storage_type payload_; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 515 | trie* parent_; // to make cleaning effective |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 516 | }; |
| 517 | |
Alexander Afanasyev | 30f60e3 | 2012-07-10 14:21:16 -0700 | [diff] [blame] | 518 | template<typename FullKey, typename PayloadTraits, typename PolicyHook> |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 519 | inline std::ostream& |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 520 | operator<<(std::ostream& os, const trie<FullKey, PayloadTraits, PolicyHook>& trie_node) |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 521 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 522 | os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload) ? "*" : "") |
| 523 | << std::endl; |
Alexander Afanasyev | 30f60e3 | 2012-07-10 14:21:16 -0700 | [diff] [blame] | 524 | typedef trie<FullKey, PayloadTraits, PolicyHook> trie; |
Alexander Afanasyev | 051d378 | 2012-07-03 10:10:15 -0700 | [diff] [blame] | 525 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 526 | for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin(); |
| 527 | subnode != trie_node.children_.end(); subnode++) |
Alexander Afanasyev | 051d378 | 2012-07-03 10:10:15 -0700 | [diff] [blame] | 528 | // BOOST_FOREACH (const trie &subnode, trie_node.children_) |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 529 | { |
| 530 | os << "\"" << &trie_node << "\"" |
| 531 | << " [label=\"" << trie_node.key_ |
| 532 | << ((trie_node.payload_ != PayloadTraits::empty_payload) ? "*" : "") << "\"]\n"; |
| 533 | os << "\"" << &(*subnode) << "\"" |
| 534 | << " [label=\"" << subnode->key_ |
| 535 | << ((subnode->payload_ != PayloadTraits::empty_payload) ? "*" : "") << "\"]" |
| 536 | "\n"; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 537 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 538 | os << "\"" << &trie_node << "\"" |
| 539 | << " -> " |
| 540 | << "\"" << &(*subnode) << "\"" |
| 541 | << "\n"; |
| 542 | os << *subnode; |
| 543 | } |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 544 | |
| 545 | return os; |
| 546 | } |
| 547 | |
Alexander Afanasyev | 30f60e3 | 2012-07-10 14:21:16 -0700 | [diff] [blame] | 548 | template<typename FullKey, typename PayloadTraits, typename PolicyHook> |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 549 | inline void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 550 | trie<FullKey, PayloadTraits, PolicyHook>::PrintStat(std::ostream& os) const |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 551 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 552 | os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload) ? "*" : "") << ": " |
| 553 | << children_.size() << " children" << std::endl; |
| 554 | for (size_t bucket = 0, maxbucket = children_.bucket_count(); bucket < maxbucket; bucket++) { |
| 555 | os << " " << children_.bucket_size(bucket); |
| 556 | } |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 557 | os << "\n"; |
| 558 | |
Alexander Afanasyev | 30f60e3 | 2012-07-10 14:21:16 -0700 | [diff] [blame] | 559 | typedef trie<FullKey, PayloadTraits, PolicyHook> trie; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 560 | for (typename trie::unordered_set::const_iterator subnode = children_.begin(); |
| 561 | subnode != children_.end(); subnode++) |
Alexander Afanasyev | 051d378 | 2012-07-03 10:10:15 -0700 | [diff] [blame] | 562 | // BOOST_FOREACH (const trie &subnode, children_) |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 563 | { |
| 564 | subnode->PrintStat(os); |
| 565 | } |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 566 | } |
| 567 | |
Alexander Afanasyev | 30f60e3 | 2012-07-10 14:21:16 -0700 | [diff] [blame] | 568 | template<typename FullKey, typename PayloadTraits, typename PolicyHook> |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 569 | inline bool |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 570 | operator==(const trie<FullKey, PayloadTraits, PolicyHook>& a, |
| 571 | const trie<FullKey, PayloadTraits, PolicyHook>& b) |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 572 | { |
| 573 | return a.key_ == b.key_; |
| 574 | } |
| 575 | |
Alexander Afanasyev | 30f60e3 | 2012-07-10 14:21:16 -0700 | [diff] [blame] | 576 | template<typename FullKey, typename PayloadTraits, typename PolicyHook> |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 577 | inline std::size_t |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 578 | hash_value(const trie<FullKey, PayloadTraits, PolicyHook>& trie_node) |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 579 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 580 | return boost::hash_value(trie_node.key_); |
Alexander Afanasyev | fd0c41c | 2012-06-11 22:15:49 -0700 | [diff] [blame] | 581 | } |
Alexander Afanasyev | 89fb535 | 2012-06-12 22:43:16 -0700 | [diff] [blame] | 582 | |
Alexander Afanasyev | 1cb4aad | 2012-08-09 14:58:16 -0700 | [diff] [blame] | 583 | template<class Trie, class NonConstTrie> // hack for boost < 1.47 |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 584 | class trie_iterator { |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 585 | public: |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 586 | trie_iterator() |
| 587 | : trie_(0) |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 588 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 589 | } |
| 590 | trie_iterator(typename Trie::iterator item) |
| 591 | : trie_(item) |
| 592 | { |
| 593 | } |
| 594 | trie_iterator(Trie& item) |
| 595 | : trie_(&item) |
| 596 | { |
| 597 | } |
| 598 | |
| 599 | Trie& operator*() |
| 600 | { |
| 601 | return *trie_; |
| 602 | } |
| 603 | const Trie& operator*() const |
| 604 | { |
| 605 | return *trie_; |
| 606 | } |
| 607 | Trie* operator->() |
| 608 | { |
| 609 | return trie_; |
| 610 | } |
| 611 | const Trie* operator->() const |
| 612 | { |
| 613 | return trie_; |
| 614 | } |
| 615 | bool |
| 616 | operator==(trie_iterator<const Trie, NonConstTrie>& other) const |
| 617 | { |
| 618 | return (trie_ == other.trie_); |
| 619 | } |
| 620 | bool |
| 621 | operator==(trie_iterator<Trie, NonConstTrie>& other) |
| 622 | { |
| 623 | return (trie_ == other.trie_); |
| 624 | } |
| 625 | bool |
| 626 | operator!=(trie_iterator<const Trie, NonConstTrie>& other) const |
| 627 | { |
| 628 | return !(*this == other); |
| 629 | } |
| 630 | bool |
| 631 | operator!=(trie_iterator<Trie, NonConstTrie>& other) |
| 632 | { |
| 633 | return !(*this == other); |
| 634 | } |
| 635 | |
| 636 | trie_iterator<Trie, NonConstTrie>& |
| 637 | operator++(int) |
| 638 | { |
| 639 | if (trie_->children_.size() > 0) |
| 640 | trie_ = &(*trie_->children_.begin()); |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 641 | else |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 642 | trie_ = goUp(); |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 643 | return *this; |
| 644 | } |
| 645 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 646 | trie_iterator<Trie, NonConstTrie>& |
| 647 | operator++() |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 648 | { |
| 649 | (*this)++; |
| 650 | return *this; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 651 | } |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 652 | |
| 653 | private: |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 654 | typedef typename boost::mpl::if_<boost::is_same<Trie, NonConstTrie>, |
| 655 | typename Trie::unordered_set::iterator, |
| 656 | typename Trie::unordered_set::const_iterator>::type set_iterator; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 657 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 658 | Trie* |
| 659 | goUp() |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 660 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 661 | if (trie_->parent_ != 0) { |
| 662 | // typename Trie::unordered_set::iterator item = |
| 663 | set_iterator item = const_cast<NonConstTrie*>(trie_) |
| 664 | ->parent_->children_.iterator_to(const_cast<NonConstTrie&>(*trie_)); |
| 665 | item++; |
| 666 | if (item != trie_->parent_->children_.end()) { |
| 667 | return &(*item); |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 668 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 669 | else { |
| 670 | trie_ = trie_->parent_; |
| 671 | return goUp(); |
| 672 | } |
| 673 | } |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 674 | else |
| 675 | return 0; |
| 676 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 677 | |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 678 | private: |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 679 | Trie* trie_; |
Alexander Afanasyev | 44bb6ea | 2012-07-09 08:44:41 -0700 | [diff] [blame] | 680 | }; |
| 681 | |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 682 | template<class Trie> |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 683 | class trie_point_iterator { |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 684 | private: |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 685 | typedef typename boost::mpl::if_<boost::is_same<Trie, const Trie>, |
| 686 | typename Trie::unordered_set::const_iterator, |
| 687 | typename Trie::unordered_set::iterator>::type set_iterator; |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 688 | |
| 689 | public: |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 690 | trie_point_iterator() |
| 691 | : trie_(0) |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 692 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 693 | } |
| 694 | trie_point_iterator(typename Trie::iterator item) |
| 695 | : trie_(item) |
| 696 | { |
| 697 | } |
| 698 | trie_point_iterator(Trie& item) |
| 699 | { |
| 700 | if (item.children_.size() != 0) |
| 701 | trie_ = &*item.children_.begin(); |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 702 | else |
| 703 | trie_ = 0; |
| 704 | } |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 705 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 706 | Trie& operator*() |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 707 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 708 | return *trie_; |
| 709 | } |
| 710 | const Trie& operator*() const |
| 711 | { |
| 712 | return *trie_; |
| 713 | } |
| 714 | Trie* operator->() |
| 715 | { |
| 716 | return trie_; |
| 717 | } |
| 718 | const Trie* operator->() const |
| 719 | { |
| 720 | return trie_; |
| 721 | } |
| 722 | bool |
| 723 | operator==(trie_point_iterator<const Trie>& other) const |
| 724 | { |
| 725 | return (trie_ == other.trie_); |
| 726 | } |
| 727 | bool |
| 728 | operator==(trie_point_iterator<Trie>& other) |
| 729 | { |
| 730 | return (trie_ == other.trie_); |
| 731 | } |
| 732 | bool |
| 733 | operator!=(trie_point_iterator<const Trie>& other) const |
| 734 | { |
| 735 | return !(*this == other); |
| 736 | } |
| 737 | bool |
| 738 | operator!=(trie_point_iterator<Trie>& other) |
| 739 | { |
| 740 | return !(*this == other); |
| 741 | } |
| 742 | |
| 743 | trie_point_iterator<Trie>& |
| 744 | operator++(int) |
| 745 | { |
| 746 | if (trie_->parent_ != 0) { |
| 747 | set_iterator item = trie_->parent_->children_.iterator_to(*trie_); |
| 748 | item++; |
| 749 | if (item == trie_->parent_->children_.end()) |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 750 | trie_ = 0; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 751 | else |
| 752 | trie_ = &*item; |
| 753 | } |
| 754 | else { |
| 755 | trie_ = 0; |
| 756 | } |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 757 | return *this; |
| 758 | } |
| 759 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 760 | trie_point_iterator<Trie>& |
| 761 | operator++() |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 762 | { |
| 763 | (*this)++; |
| 764 | return *this; |
Alexander Afanasyev | eec6629 | 2013-02-06 16:23:21 -0800 | [diff] [blame] | 765 | } |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 766 | |
| 767 | private: |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 768 | Trie* trie_; |
Alexander Afanasyev | 0845c09 | 2012-07-13 17:45:33 -0700 | [diff] [blame] | 769 | }; |
| 770 | |
Alexander Afanasyev | 30cb117 | 2012-07-06 10:47:39 -0700 | [diff] [blame] | 771 | } // ndnSIM |
Alexander Afanasyev | 2b4c947 | 2012-08-09 15:00:38 -0700 | [diff] [blame] | 772 | } // ndn |
Alexander Afanasyev | e77db79 | 2012-08-09 11:10:58 -0700 | [diff] [blame] | 773 | } // ns3 |
Alexander Afanasyev | 30cb117 | 2012-07-06 10:47:39 -0700 | [diff] [blame] | 774 | |
Alexander Afanasyev | 9a98970 | 2012-06-29 17:44:00 -0700 | [diff] [blame] | 775 | #endif // TRIE_H_ |