blob: 9afc8d1bb4d497bb96f61ad0e9dddebb22986fce [file] [log] [blame]
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -07001/* -*- 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 Afanasyev9a989702012-06-29 17:44:00 -070021#ifndef TRIE_H_
22#define TRIE_H_
23
24#include "ns3/ptr.h"
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070025
26#include <boost/intrusive/unordered_set.hpp>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070027#include <boost/intrusive/list.hpp>
Alexander Afanasyev9a989702012-06-29 17:44:00 -070028#include <boost/intrusive/set.hpp>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070029#include <boost/functional/hash.hpp>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070030#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
31#include <boost/tuple/tuple.hpp>
Alexander Afanasyev78057c32012-07-06 15:18:46 -070032#include <boost/foreach.hpp>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -070033#include <boost/mpl/if.hpp>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070034
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070035namespace ns3 {
36namespace ndn {
37namespace ndnSIM {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070038
39/////////////////////////////////////////////////////
40// Allow customization for payload
41//
Alexander Afanasyev8566f452012-12-10 15:21:51 -080042template<typename Payload, typename BasePayload = Payload>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080043struct pointer_payload_traits {
44 typedef Payload payload_type; // general type of the payload
45 typedef Payload* storage_type; // how the payload is actually stored
46 typedef Payload* insert_type; // what parameter is inserted
Alexander Afanasyev0845c092012-07-13 17:45:33 -070047
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080048 typedef Payload* return_type; // what is returned on access
49 typedef const Payload* const_return_type; // what is returned on const access
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070050
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080051 typedef BasePayload*
52 base_type; // base type of the entry (when implementation details need to be hidden)
53 typedef const BasePayload*
54 const_base_type; // const base type of the entry (when implementation details need to be hidden)
Alexander Afanasyeveec66292013-02-06 16:23:21 -080055
Alexander Afanasyev78057c32012-07-06 15:18:46 -070056 static Payload* empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070057};
58
Alexander Afanasyev8566f452012-12-10 15:21:51 -080059template<typename Payload, typename BasePayload>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080060Payload* pointer_payload_traits<Payload, BasePayload>::empty_payload = 0;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070061
Alexander Afanasyev8566f452012-12-10 15:21:51 -080062template<typename Payload, typename BasePayload = Payload>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080063struct smart_pointer_payload_traits {
64 typedef Payload payload_type;
65 typedef ns3::Ptr<Payload> storage_type;
66 typedef ns3::Ptr<Payload> insert_type;
Alexander Afanasyeveec66292013-02-06 16:23:21 -080067
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080068 typedef ns3::Ptr<Payload> return_type;
Alexander Afanasyev0845c092012-07-13 17:45:33 -070069 typedef ns3::Ptr<const Payload> const_return_type;
Alexander Afanasyev8566f452012-12-10 15:21:51 -080070
71 typedef ns3::Ptr<BasePayload> base_type;
72 typedef ns3::Ptr<const BasePayload> const_base_type;
Alexander Afanasyeveec66292013-02-06 16:23:21 -080073
Alexander Afanasyev78057c32012-07-06 15:18:46 -070074 static ns3::Ptr<Payload> empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070075};
76
Alexander Afanasyev8566f452012-12-10 15:21:51 -080077template<typename Payload, typename BasePayload>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080078ns3::Ptr<Payload> smart_pointer_payload_traits<Payload, BasePayload>::empty_payload = 0;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070079
Alexander Afanasyev8566f452012-12-10 15:21:51 -080080template<typename Payload, typename BasePayload = Payload>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080081struct non_pointer_traits {
82 typedef Payload payload_type;
83 typedef Payload storage_type;
84 typedef const Payload& insert_type; // nothing to insert
Alexander Afanasyev0845c092012-07-13 17:45:33 -070085
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080086 typedef Payload& return_type;
87 typedef const Payload& const_return_type;
Alexander Afanasyeveec66292013-02-06 16:23:21 -080088
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080089 typedef BasePayload& base_type;
Alexander Afanasyev62304f22012-12-10 18:06:21 -080090 typedef const BasePayload& const_base_type;
Alexander Afanasyeveec66292013-02-06 16:23:21 -080091
Alexander Afanasyev0845c092012-07-13 17:45:33 -070092 static Payload empty_payload;
93};
94
Alexander Afanasyev8566f452012-12-10 15:21:51 -080095template<typename Payload, typename BasePayload>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080096Payload non_pointer_traits<Payload, BasePayload>::empty_payload = Payload();
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070097
98////////////////////////////////////////////////////
99// forward declarations
100//
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800101template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800102class trie;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700103
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700104template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700105inline std::ostream&
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800106operator<<(std::ostream& os, const trie<FullKey, PayloadTraits, PolicyHook>& trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700107
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700108template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700109bool
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800110operator==(const trie<FullKey, PayloadTraits, PolicyHook>& a,
111 const trie<FullKey, PayloadTraits, PolicyHook>& b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700112
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800113template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700114std::size_t
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800115hash_value(const trie<FullKey, PayloadTraits, PolicyHook>& trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700116
117///////////////////////////////////////////////////
118// actual definition
119//
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700120template<class T, class NonConstT>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700121class trie_iterator;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700122
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700123template<class T>
124class trie_point_iterator;
125
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800126template<typename FullKey, typename PayloadTraits, typename PolicyHook>
127class trie {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700128public:
129 typedef typename FullKey::partial_type Key;
130
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800131 typedef trie* iterator;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700132 typedef const trie* const_iterator;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700133
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700134 typedef trie_iterator<trie, trie> recursive_iterator;
135 typedef trie_iterator<const trie, trie> const_recursive_iterator;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700136
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700137 typedef trie_point_iterator<trie> point_iterator;
138 typedef trie_point_iterator<const trie> const_point_iterator;
139
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700140 typedef PayloadTraits payload_traits;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800141
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800142 inline trie(const Key& key, size_t bucketSize = 1, size_t bucketIncrement = 1)
143 : key_(key)
144 , initialBucketSize_(bucketSize)
145 , bucketIncrement_(bucketIncrement)
146 , bucketSize_(initialBucketSize_)
147 , buckets_(new bucket_type[bucketSize_]) // cannot use normal pointer, because lifetime of
148 // buckets should be larger than lifetime of the
149 // container
150 , children_(bucket_traits(buckets_.get(), bucketSize_))
151 , payload_(PayloadTraits::empty_payload)
152 , parent_(0)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700153 {
154 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700155
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800156 inline ~trie()
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700157 {
158 payload_ = PayloadTraits::empty_payload; // necessary for smart pointers...
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800159 children_.clear_and_dispose(trie_delete_disposer());
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700160 }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700161
162 void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800163 clear()
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700164 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800165 children_.clear_and_dispose(trie_delete_disposer());
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700166 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700167
168 template<class Predicate>
169 void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800170 clear_if(Predicate cond)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700171 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800172 recursive_iterator trieNode(this);
173 recursive_iterator end(0);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700174
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800175 while (trieNode != end) {
176 if (cond(*trieNode)) {
177 trieNode = recursive_iterator(trieNode->erase());
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700178 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800179 trieNode++;
180 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700181 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800182
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700183 // actual entry
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800184 friend bool operator==<>(const trie<FullKey, PayloadTraits, PolicyHook>& a,
185 const trie<FullKey, PayloadTraits, PolicyHook>& b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700186
187 friend std::size_t
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800188 hash_value<>(const trie<FullKey, PayloadTraits, PolicyHook>& trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700189
190 inline std::pair<iterator, bool>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800191 insert(const FullKey& key, typename PayloadTraits::insert_type payload)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700192 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800193 trie* trieNode = this;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800194
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800195 BOOST_FOREACH (const Key& subkey, key) {
196 typename unordered_set::iterator item = trieNode->children_.find(subkey);
197 if (item == trieNode->children_.end()) {
198 trie* newNode = new trie(subkey, initialBucketSize_, bucketIncrement_);
199 // std::cout << "new " << newNode << "\n";
200 newNode->parent_ = trieNode;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700201
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800202 if (trieNode->children_.size() >= trieNode->bucketSize_) {
203 trieNode->bucketSize_ += trieNode->bucketIncrement_;
204 trieNode->bucketIncrement_ *= 2; // increase bucketIncrement exponentially
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800205
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800206 buckets_array newBuckets(new bucket_type[trieNode->bucketSize_]);
207 trieNode->children_.rehash(bucket_traits(newBuckets.get(), trieNode->bucketSize_));
208 trieNode->buckets_.swap(newBuckets);
209 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800210
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800211 std::pair<typename unordered_set::iterator, bool> ret =
212 trieNode->children_.insert(*newNode);
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800213
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800214 trieNode = &(*ret.first);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700215 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800216 else
217 trieNode = &(*item);
218 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700219
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800220 if (trieNode->payload_ == PayloadTraits::empty_payload) {
221 trieNode->payload_ = payload;
222 return std::make_pair(trieNode, true);
223 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700224 else
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800225 return std::make_pair(trieNode, false);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700226 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700227
228 /**
229 * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
230 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700231 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800232 erase()
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700233 {
234 payload_ = PayloadTraits::empty_payload;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800235 return prune();
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700236 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700237
238 /**
239 * @brief Do exactly as erase, but without erasing the payload
240 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700241 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800242 prune()
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700243 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800244 if (payload_ == PayloadTraits::empty_payload && children_.size() == 0) {
245 if (parent_ == 0)
246 return this;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700247
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800248 trie* parent = parent_;
249 parent->children_
250 .erase_and_dispose(*this,
251 trie_delete_disposer()); // delete this; basically, committing a suicide
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700252
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800253 return parent->prune();
254 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700255 return this;
256 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700257
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700258 /**
259 * @brief Perform prune of the node, but without attempting to parent of the node
260 */
261 inline void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800262 prune_node()
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700263 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800264 if (payload_ == PayloadTraits::empty_payload && children_.size() == 0) {
265 if (parent_ == 0)
266 return;
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700267
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800268 trie* parent = parent_;
269 parent->children_
270 .erase_and_dispose(*this,
271 trie_delete_disposer()); // delete this; basically, committing a suicide
272 }
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700273 }
274
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700275 // inline boost::tuple<const iterator, bool, const iterator>
276 // find (const FullKey &key) const
277 // {
278 // return const_cast<trie*> (this)->find (key);
279 // }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700280
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700281 /**
282 * @brief Perform the longest prefix match
283 * @param key the key for which to perform the longest prefix match
284 *
285 * @return ->second is true if prefix in ->first is longer than key
286 */
287 inline boost::tuple<iterator, bool, iterator>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800288 find(const FullKey& key)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700289 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800290 trie* trieNode = this;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700291 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
292 bool reachLast = true;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800293
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800294 BOOST_FOREACH (const Key& subkey, key) {
295 typename unordered_set::iterator item = trieNode->children_.find(subkey);
296 if (item == trieNode->children_.end()) {
297 reachLast = false;
298 break;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700299 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800300 else {
301 trieNode = &(*item);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700302
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800303 if (trieNode->payload_ != PayloadTraits::empty_payload)
304 foundNode = trieNode;
305 }
306 }
307
308 return boost::make_tuple(foundNode, reachLast, trieNode);
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800309 }
310
311 /**
312 * @brief Perform the longest prefix match satisfying preficate
313 * @param key the key for which to perform the longest prefix match
314 *
315 * @return ->second is true if prefix in ->first is longer than key
316 */
317 template<class Predicate>
318 inline boost::tuple<iterator, bool, iterator>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800319 find_if(const FullKey& key, Predicate pred)
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800320 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800321 trie* trieNode = this;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800322 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
323 bool reachLast = true;
324
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800325 BOOST_FOREACH (const Key& subkey, key) {
326 typename unordered_set::iterator item = trieNode->children_.find(subkey);
327 if (item == trieNode->children_.end()) {
328 reachLast = false;
329 break;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800330 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800331 else {
332 trieNode = &(*item);
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800333
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800334 if (trieNode->payload_ != PayloadTraits::empty_payload && pred(trieNode->payload_)) {
335 foundNode = trieNode;
336 }
337 }
338 }
339
340 return boost::make_tuple(foundNode, reachLast, trieNode);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700341 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700342
343 /**
344 * @brief Find next payload of the sub-trie
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800345 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration
346 * )
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700347 */
348 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800349 find()
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700350 {
351 if (payload_ != PayloadTraits::empty_payload)
352 return this;
353
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700354 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800355 for (typename trie::unordered_set::iterator subnode = children_.begin();
356 subnode != children_.end(); subnode++)
357 // BOOST_FOREACH (trie &subnode, children_)
358 {
359 iterator value = subnode->find();
360 if (value != 0)
361 return value;
362 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800363
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700364 return 0;
365 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700366
367 /**
368 * @brief Find next payload of the sub-trie satisfying the predicate
369 * @param pred predicate
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800370 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration
371 * )
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700372 */
373 template<class Predicate>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700374 inline const iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800375 find_if(Predicate pred)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700376 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800377 if (payload_ != PayloadTraits::empty_payload && pred(payload_))
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700378 return this;
379
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700380 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800381 for (typename trie::unordered_set::iterator subnode = children_.begin();
382 subnode != children_.end(); subnode++)
383 // BOOST_FOREACH (const trie &subnode, children_)
384 {
385 iterator value = subnode->find_if(pred);
386 if (value != 0)
387 return value;
388 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800389
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700390 return 0;
391 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700392
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700393 /**
394 * @brief Find next payload of the sub-trie satisfying the predicate
395 * @param pred predicate
396 *
397 * This version check predicate only for the next level children
398 *
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800399 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration
400 *)
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700401 */
402 template<class Predicate>
403 inline const iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800404 find_if_next_level(Predicate pred)
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700405 {
406 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800407 for (typename trie::unordered_set::iterator subnode = children_.begin();
408 subnode != children_.end(); subnode++) {
409 if (pred(subnode->key())) {
410 return subnode->find();
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700411 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800412 }
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700413
414 return 0;
415 }
416
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800417 iterator
418 end()
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700419 {
420 return 0;
421 }
422
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800423 const_iterator
424 end() const
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700425 {
426 return 0;
427 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700428
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700429 typename PayloadTraits::const_return_type
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800430 payload() const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700431 {
432 return payload_;
433 }
434
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700435 typename PayloadTraits::return_type
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800436 payload()
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700437 {
438 return payload_;
439 }
440
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700441 void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800442 set_payload(typename PayloadTraits::insert_type payload)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700443 {
444 payload_ = payload;
445 }
Alexander Afanasyev0560eec2012-07-16 15:44:31 -0700446
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800447 Key
448 key() const
Alexander Afanasyev0560eec2012-07-16 15:44:31 -0700449 {
450 return key_;
451 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800452
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700453 inline void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800454 PrintStat(std::ostream& os) const;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800455
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700456private:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800457 // The disposer object function
458 struct trie_delete_disposer {
459 void
460 operator()(trie* delete_this)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700461 {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700462 delete delete_this;
463 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700464 };
465
466 template<class D>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800467 struct array_disposer {
468 void
469 operator()(D* array)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700470 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800471 delete[] array;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700472 }
473 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700474
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800475 friend std::ostream& operator<<<>(std::ostream& os, const trie& trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700476
477public:
478 PolicyHook policy_hook_;
479
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700480private:
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700481 boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700482
483 // necessary typedefs
484 typedef trie self_type;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800485 typedef boost::intrusive::member_hook<trie, boost::intrusive::unordered_set_member_hook<>,
486 &trie::unordered_set_member_hook_> member_hook;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700487
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800488 typedef boost::intrusive::unordered_set<trie, member_hook> unordered_set;
489 typedef typename unordered_set::bucket_type bucket_type;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700490 typedef typename unordered_set::bucket_traits bucket_traits;
491
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700492 template<class T, class NonConstT>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700493 friend class trie_iterator;
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700494
495 template<class T>
496 friend class trie_point_iterator;
497
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700498 ////////////////////////////////////////////////
499 // Actual data
500 ////////////////////////////////////////////////
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800501
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700502 Key key_; ///< name component
503
504 size_t initialBucketSize_;
505 size_t bucketIncrement_;
506
507 size_t bucketSize_;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800508 typedef boost::interprocess::unique_ptr<bucket_type, array_disposer<bucket_type>> buckets_array;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700509 buckets_array buckets_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700510 unordered_set children_;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800511
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700512 typename PayloadTraits::storage_type payload_;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800513 trie* parent_; // to make cleaning effective
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700514};
515
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700516template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700517inline std::ostream&
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800518operator<<(std::ostream& os, const trie<FullKey, PayloadTraits, PolicyHook>& trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700519{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800520 os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload) ? "*" : "")
521 << std::endl;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700522 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700523
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800524 for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin();
525 subnode != trie_node.children_.end(); subnode++)
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700526 // BOOST_FOREACH (const trie &subnode, trie_node.children_)
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800527 {
528 os << "\"" << &trie_node << "\""
529 << " [label=\"" << trie_node.key_
530 << ((trie_node.payload_ != PayloadTraits::empty_payload) ? "*" : "") << "\"]\n";
531 os << "\"" << &(*subnode) << "\""
532 << " [label=\"" << subnode->key_
533 << ((subnode->payload_ != PayloadTraits::empty_payload) ? "*" : "") << "\"]"
534 "\n";
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800535
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800536 os << "\"" << &trie_node << "\""
537 << " -> "
538 << "\"" << &(*subnode) << "\""
539 << "\n";
540 os << *subnode;
541 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700542
543 return os;
544}
545
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700546template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700547inline void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800548trie<FullKey, PayloadTraits, PolicyHook>::PrintStat(std::ostream& os) const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700549{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800550 os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload) ? "*" : "") << ": "
551 << children_.size() << " children" << std::endl;
552 for (size_t bucket = 0, maxbucket = children_.bucket_count(); bucket < maxbucket; bucket++) {
553 os << " " << children_.bucket_size(bucket);
554 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700555 os << "\n";
556
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700557 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800558 for (typename trie::unordered_set::const_iterator subnode = children_.begin();
559 subnode != children_.end(); subnode++)
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700560 // BOOST_FOREACH (const trie &subnode, children_)
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800561 {
562 subnode->PrintStat(os);
563 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700564}
565
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700566template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700567inline bool
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800568operator==(const trie<FullKey, PayloadTraits, PolicyHook>& a,
569 const trie<FullKey, PayloadTraits, PolicyHook>& b)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700570{
571 return a.key_ == b.key_;
572}
573
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700574template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700575inline std::size_t
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800576hash_value(const trie<FullKey, PayloadTraits, PolicyHook>& trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700577{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800578 return boost::hash_value(trie_node.key_);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700579}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700580
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700581template<class Trie, class NonConstTrie> // hack for boost < 1.47
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800582class trie_iterator {
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700583public:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800584 trie_iterator()
585 : trie_(0)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700586 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800587 }
588 trie_iterator(typename Trie::iterator item)
589 : trie_(item)
590 {
591 }
592 trie_iterator(Trie& item)
593 : trie_(&item)
594 {
595 }
596
597 Trie& operator*()
598 {
599 return *trie_;
600 }
601 const Trie& operator*() const
602 {
603 return *trie_;
604 }
605 Trie* operator->()
606 {
607 return trie_;
608 }
609 const Trie* operator->() const
610 {
611 return trie_;
612 }
613 bool
614 operator==(trie_iterator<const Trie, NonConstTrie>& other) const
615 {
616 return (trie_ == other.trie_);
617 }
618 bool
619 operator==(trie_iterator<Trie, NonConstTrie>& other)
620 {
621 return (trie_ == other.trie_);
622 }
623 bool
624 operator!=(trie_iterator<const Trie, NonConstTrie>& other) const
625 {
626 return !(*this == other);
627 }
628 bool
629 operator!=(trie_iterator<Trie, NonConstTrie>& other)
630 {
631 return !(*this == other);
632 }
633
634 trie_iterator<Trie, NonConstTrie>&
635 operator++(int)
636 {
637 if (trie_->children_.size() > 0)
638 trie_ = &(*trie_->children_.begin());
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700639 else
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800640 trie_ = goUp();
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700641 return *this;
642 }
643
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800644 trie_iterator<Trie, NonConstTrie>&
645 operator++()
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700646 {
647 (*this)++;
648 return *this;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800649 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700650
651private:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800652 typedef typename boost::mpl::if_<boost::is_same<Trie, NonConstTrie>,
653 typename Trie::unordered_set::iterator,
654 typename Trie::unordered_set::const_iterator>::type set_iterator;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800655
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800656 Trie*
657 goUp()
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700658 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800659 if (trie_->parent_ != 0) {
660 // typename Trie::unordered_set::iterator item =
661 set_iterator item = const_cast<NonConstTrie*>(trie_)
662 ->parent_->children_.iterator_to(const_cast<NonConstTrie&>(*trie_));
663 item++;
664 if (item != trie_->parent_->children_.end()) {
665 return &(*item);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700666 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800667 else {
668 trie_ = trie_->parent_;
669 return goUp();
670 }
671 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700672 else
673 return 0;
674 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800675
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700676private:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800677 Trie* trie_;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700678};
679
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700680template<class Trie>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800681class trie_point_iterator {
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800682private:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800683 typedef typename boost::mpl::if_<boost::is_same<Trie, const Trie>,
684 typename Trie::unordered_set::const_iterator,
685 typename Trie::unordered_set::iterator>::type set_iterator;
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700686
687public:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800688 trie_point_iterator()
689 : trie_(0)
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700690 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800691 }
692 trie_point_iterator(typename Trie::iterator item)
693 : trie_(item)
694 {
695 }
696 trie_point_iterator(Trie& item)
697 {
698 if (item.children_.size() != 0)
699 trie_ = &*item.children_.begin();
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700700 else
701 trie_ = 0;
702 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800703
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800704 Trie& operator*()
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700705 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800706 return *trie_;
707 }
708 const Trie& operator*() const
709 {
710 return *trie_;
711 }
712 Trie* operator->()
713 {
714 return trie_;
715 }
716 const Trie* operator->() const
717 {
718 return trie_;
719 }
720 bool
721 operator==(trie_point_iterator<const Trie>& other) const
722 {
723 return (trie_ == other.trie_);
724 }
725 bool
726 operator==(trie_point_iterator<Trie>& other)
727 {
728 return (trie_ == other.trie_);
729 }
730 bool
731 operator!=(trie_point_iterator<const Trie>& other) const
732 {
733 return !(*this == other);
734 }
735 bool
736 operator!=(trie_point_iterator<Trie>& other)
737 {
738 return !(*this == other);
739 }
740
741 trie_point_iterator<Trie>&
742 operator++(int)
743 {
744 if (trie_->parent_ != 0) {
745 set_iterator item = trie_->parent_->children_.iterator_to(*trie_);
746 item++;
747 if (item == trie_->parent_->children_.end())
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700748 trie_ = 0;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800749 else
750 trie_ = &*item;
751 }
752 else {
753 trie_ = 0;
754 }
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700755 return *this;
756 }
757
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800758 trie_point_iterator<Trie>&
759 operator++()
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700760 {
761 (*this)++;
762 return *this;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800763 }
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700764
765private:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800766 Trie* trie_;
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700767};
768
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700769} // ndnSIM
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700770} // ndn
Alexander Afanasyeve77db792012-08-09 11:10:58 -0700771} // ns3
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700772
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700773#endif // TRIE_H_