blob: 1e37cbd5edb9dd6ddcb35ac85fa86d493bb2cd54 [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 Afanasyevfd0c41c2012-06-11 22:15:49 -070043struct pointer_payload_traits
44{
Alexander Afanasyev0845c092012-07-13 17:45:33 -070045 typedef Payload payload_type; // general type of the payload
46 typedef Payload* storage_type; // how the payload is actually stored
47 typedef Payload* insert_type; // what parameter is inserted
48
49 typedef Payload* return_type; // what is returned on access
50 typedef const Payload* const_return_type; // what is returned on const access
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070051
Alexander Afanasyev62304f22012-12-10 18:06:21 -080052 typedef BasePayload* base_type; // base type of the entry (when implementation details need to be hidden)
53 typedef const BasePayload* const_base_type; // const base type of the entry (when implementation details need to be hidden)
Alexander Afanasyeveec66292013-02-06 16:23:21 -080054
Alexander Afanasyev78057c32012-07-06 15:18:46 -070055 static Payload* empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070056};
57
Alexander Afanasyev8566f452012-12-10 15:21:51 -080058template<typename Payload, typename BasePayload>
Alexander Afanasyev78057c32012-07-06 15:18:46 -070059Payload*
Alexander Afanasyev8566f452012-12-10 15:21:51 -080060pointer_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 Afanasyevfd0c41c2012-06-11 22:15:49 -070063struct smart_pointer_payload_traits
64{
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070065 typedef Payload payload_type;
Alexander Afanasyev0845c092012-07-13 17:45:33 -070066 typedef ns3::Ptr<Payload> storage_type;
67 typedef ns3::Ptr<Payload> insert_type;
Alexander Afanasyeveec66292013-02-06 16:23:21 -080068
Alexander Afanasyev0845c092012-07-13 17:45:33 -070069 typedef ns3::Ptr<Payload> return_type;
70 typedef ns3::Ptr<const Payload> const_return_type;
Alexander Afanasyev8566f452012-12-10 15:21:51 -080071
72 typedef ns3::Ptr<BasePayload> base_type;
73 typedef ns3::Ptr<const BasePayload> const_base_type;
Alexander Afanasyeveec66292013-02-06 16:23:21 -080074
Alexander Afanasyev78057c32012-07-06 15:18:46 -070075 static ns3::Ptr<Payload> empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070076};
77
Alexander Afanasyev8566f452012-12-10 15:21:51 -080078template<typename Payload, typename BasePayload>
Alexander Afanasyev78057c32012-07-06 15:18:46 -070079ns3::Ptr<Payload>
Alexander Afanasyev8566f452012-12-10 15:21:51 -080080smart_pointer_payload_traits<Payload, BasePayload>::empty_payload = 0;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070081
Alexander Afanasyev8566f452012-12-10 15:21:51 -080082template<typename Payload, typename BasePayload = Payload>
Alexander Afanasyev0845c092012-07-13 17:45:33 -070083struct non_pointer_traits
84{
85 typedef Payload payload_type;
86 typedef Payload storage_type;
87 typedef const Payload & insert_type; // nothing to insert
88
89 typedef Payload& return_type;
90 typedef const Payload & const_return_type;
Alexander Afanasyeveec66292013-02-06 16:23:21 -080091
Alexander Afanasyev62304f22012-12-10 18:06:21 -080092 typedef BasePayload& base_type;
93 typedef const BasePayload& const_base_type;
Alexander Afanasyeveec66292013-02-06 16:23:21 -080094
Alexander Afanasyev0845c092012-07-13 17:45:33 -070095 static Payload empty_payload;
96};
97
Alexander Afanasyev8566f452012-12-10 15:21:51 -080098template<typename Payload, typename BasePayload>
Alexander Afanasyeveec66292013-02-06 16:23:21 -080099Payload
Alexander Afanasyev8566f452012-12-10 15:21:51 -0800100non_pointer_traits<Payload, BasePayload>::empty_payload = Payload ();
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700101
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700102
103////////////////////////////////////////////////////
104// forward declarations
105//
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700106template<typename FullKey,
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700107 typename PayloadTraits,
108 typename PolicyHook >
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800109class trie;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700110
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700111template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700112inline std::ostream&
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700113operator << (std::ostream &os,
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700114 const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700115
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700116template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700117bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700118operator== (const trie<FullKey, PayloadTraits, PolicyHook> &a,
119 const trie<FullKey, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700120
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700121template<typename FullKey, typename PayloadTraits, typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700122std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700123hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700124
125///////////////////////////////////////////////////
126// actual definition
127//
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700128template<class T, class NonConstT>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700129class trie_iterator;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700130
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700131template<class T>
132class trie_point_iterator;
133
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700134template<typename FullKey,
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700135 typename PayloadTraits,
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700136 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700137class trie
138{
139public:
140 typedef typename FullKey::partial_type Key;
141
142 typedef trie* iterator;
143 typedef const trie* const_iterator;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700144
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700145 typedef trie_iterator<trie, trie> recursive_iterator;
146 typedef trie_iterator<const trie, trie> const_recursive_iterator;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700147
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700148 typedef trie_point_iterator<trie> point_iterator;
149 typedef trie_point_iterator<const trie> const_point_iterator;
150
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700151 typedef PayloadTraits payload_traits;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800152
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700153 inline
Alexander Afanasyevac49cad2013-07-26 11:31:47 -0700154 trie (const Key &key, size_t bucketSize = 1, size_t bucketIncrement = 1)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700155 : key_ (key)
156 , initialBucketSize_ (bucketSize)
157 , bucketIncrement_ (bucketIncrement)
158 , bucketSize_ (initialBucketSize_)
159 , buckets_ (new bucket_type [bucketSize_]) //cannot use normal pointer, because lifetime of buckets should be larger than lifetime of the container
160 , children_ (bucket_traits (buckets_.get (), bucketSize_))
161 , payload_ (PayloadTraits::empty_payload)
162 , parent_ (0)
163 {
164 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700165
166 inline
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700167 ~trie ()
168 {
169 payload_ = PayloadTraits::empty_payload; // necessary for smart pointers...
170 children_.clear_and_dispose (trie_delete_disposer ());
171 }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700172
173 void
174 clear ()
175 {
176 children_.clear_and_dispose (trie_delete_disposer ());
177 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700178
179 template<class Predicate>
180 void
181 clear_if (Predicate cond)
182 {
183 recursive_iterator trieNode (this);
184 recursive_iterator end (0);
185
186 while (trieNode != end)
187 {
188 if (cond (*trieNode))
189 {
190 trieNode = recursive_iterator (trieNode->erase ());
191 }
192 trieNode ++;
193 }
194 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800195
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700196 // actual entry
197 friend bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700198 operator== <> (const trie<FullKey, PayloadTraits, PolicyHook> &a,
199 const trie<FullKey, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700200
201 friend std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700202 hash_value <> (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700203
204 inline std::pair<iterator, bool>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700205 insert (const FullKey &key,
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700206 typename PayloadTraits::insert_type payload)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700207 {
208 trie *trieNode = this;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800209
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700210 BOOST_FOREACH (const Key &subkey, key)
211 {
212 typename unordered_set::iterator item = trieNode->children_.find (subkey);
213 if (item == trieNode->children_.end ())
214 {
215 trie *newNode = new trie (subkey, initialBucketSize_, bucketIncrement_);
216 // std::cout << "new " << newNode << "\n";
217 newNode->parent_ = trieNode;
218
219 if (trieNode->children_.size () >= trieNode->bucketSize_)
220 {
221 trieNode->bucketSize_ += trieNode->bucketIncrement_;
Alexander Afanasyev424d5842012-09-03 17:35:34 -0700222 trieNode->bucketIncrement_ *= 2; // increase bucketIncrement exponentially
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800223
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700224 buckets_array newBuckets (new bucket_type [trieNode->bucketSize_]);
225 trieNode->children_.rehash (bucket_traits (newBuckets.get (), trieNode->bucketSize_));
226 trieNode->buckets_.swap (newBuckets);
227 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800228
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700229 std::pair< typename unordered_set::iterator, bool > ret =
230 trieNode->children_.insert (*newNode);
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800231
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700232 trieNode = &(*ret.first);
233 }
234 else
235 trieNode = &(*item);
236 }
237
238 if (trieNode->payload_ == PayloadTraits::empty_payload)
239 {
240 trieNode->payload_ = payload;
241 return std::make_pair (trieNode, true);
242 }
243 else
244 return std::make_pair (trieNode, false);
245 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700246
247 /**
248 * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
249 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700250 inline iterator
251 erase ()
252 {
253 payload_ = PayloadTraits::empty_payload;
254 return prune ();
255 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700256
257 /**
258 * @brief Do exactly as erase, but without erasing the payload
259 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700260 inline iterator
261 prune ()
262 {
263 if (payload_ == PayloadTraits::empty_payload &&
264 children_.size () == 0)
265 {
266 if (parent_ == 0) return this;
267
268 trie *parent = parent_;
269 parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
270
271 return parent->prune ();
272 }
273 return this;
274 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700275
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700276 /**
277 * @brief Perform prune of the node, but without attempting to parent of the node
278 */
279 inline void
280 prune_node ()
281 {
282 if (payload_ == PayloadTraits::empty_payload &&
283 children_.size () == 0)
284 {
285 if (parent_ == 0) return;
286
287 trie *parent = parent_;
288 parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
289 }
290 }
291
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700292 // inline boost::tuple<const iterator, bool, const iterator>
293 // find (const FullKey &key) const
294 // {
295 // return const_cast<trie*> (this)->find (key);
296 // }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700297
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700298 /**
299 * @brief Perform the longest prefix match
300 * @param key the key for which to perform the longest prefix match
301 *
302 * @return ->second is true if prefix in ->first is longer than key
303 */
304 inline boost::tuple<iterator, bool, iterator>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700305 find (const FullKey &key)
306 {
307 trie *trieNode = this;
308 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
309 bool reachLast = true;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800310
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700311 BOOST_FOREACH (const Key &subkey, key)
312 {
313 typename unordered_set::iterator item = trieNode->children_.find (subkey);
314 if (item == trieNode->children_.end ())
315 {
316 reachLast = false;
317 break;
318 }
319 else
320 {
321 trieNode = &(*item);
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800322
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700323 if (trieNode->payload_ != PayloadTraits::empty_payload)
324 foundNode = trieNode;
325 }
326 }
327
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800328 return boost::make_tuple (foundNode, reachLast, trieNode);
329 }
330
331 /**
332 * @brief Perform the longest prefix match satisfying preficate
333 * @param key the key for which to perform the longest prefix match
334 *
335 * @return ->second is true if prefix in ->first is longer than key
336 */
337 template<class Predicate>
338 inline boost::tuple<iterator, bool, iterator>
339 find_if (const FullKey &key, Predicate pred)
340 {
341 trie *trieNode = this;
342 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
343 bool reachLast = true;
344
345 BOOST_FOREACH (const Key &subkey, key)
346 {
347 typename unordered_set::iterator item = trieNode->children_.find (subkey);
348 if (item == trieNode->children_.end ())
349 {
350 reachLast = false;
351 break;
352 }
353 else
354 {
355 trieNode = &(*item);
356
357 if (trieNode->payload_ != PayloadTraits::empty_payload &&
358 pred (trieNode->payload_))
359 {
360 foundNode = trieNode;
361 }
362 }
363 }
364
365 return boost::make_tuple (foundNode, reachLast, trieNode);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700366 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700367
368 /**
369 * @brief Find next payload of the sub-trie
370 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
371 */
372 inline iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700373 find ()
374 {
375 if (payload_ != PayloadTraits::empty_payload)
376 return this;
377
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700378 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700379 for (typename trie::unordered_set::iterator subnode = children_.begin ();
380 subnode != children_.end ();
381 subnode++ )
382 // BOOST_FOREACH (trie &subnode, children_)
383 {
384 iterator value = subnode->find ();
385 if (value != 0)
386 return value;
387 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800388
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700389 return 0;
390 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700391
392 /**
393 * @brief Find next payload of the sub-trie satisfying the predicate
394 * @param pred predicate
395 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
396 */
397 template<class Predicate>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700398 inline const iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700399 find_if (Predicate pred)
400 {
401 if (payload_ != PayloadTraits::empty_payload && pred (payload_))
402 return this;
403
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700404 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700405 for (typename trie::unordered_set::iterator subnode = children_.begin ();
406 subnode != children_.end ();
407 subnode++ )
408 // BOOST_FOREACH (const trie &subnode, children_)
409 {
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800410 iterator value = subnode->find_if (pred);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700411 if (value != 0)
412 return value;
413 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800414
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700415 return 0;
416 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700417
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700418 /**
419 * @brief Find next payload of the sub-trie satisfying the predicate
420 * @param pred predicate
421 *
422 * This version check predicate only for the next level children
423 *
424 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
425 */
426 template<class Predicate>
427 inline const iterator
428 find_if_next_level (Predicate pred)
429 {
430 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
431 for (typename trie::unordered_set::iterator subnode = children_.begin ();
432 subnode != children_.end ();
433 subnode++ )
434 {
435 if (pred (subnode->key ()))
436 {
437 return subnode->find ();
438 }
439 }
440
441 return 0;
442 }
443
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700444 iterator end ()
445 {
446 return 0;
447 }
448
449 const_iterator end () const
450 {
451 return 0;
452 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700453
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700454 typename PayloadTraits::const_return_type
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700455 payload () const
456 {
457 return payload_;
458 }
459
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700460 typename PayloadTraits::return_type
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700461 payload ()
462 {
463 return payload_;
464 }
465
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700466 void
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700467 set_payload (typename PayloadTraits::insert_type payload)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700468 {
469 payload_ = payload;
470 }
Alexander Afanasyev0560eec2012-07-16 15:44:31 -0700471
472 Key key () const
473 {
474 return key_;
475 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800476
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700477 inline void
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800478 PrintStat (std::ostream &os) const;
479
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700480private:
481 //The disposer object function
482 struct trie_delete_disposer
483 {
484 void operator() (trie *delete_this)
485 {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700486 delete delete_this;
487 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700488 };
489
490 template<class D>
491 struct array_disposer
492 {
493 void operator() (D *array)
494 {
495 delete [] array;
496 }
497 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700498
499 friend
500 std::ostream&
501 operator<< < > (std::ostream &os, const trie &trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700502
503public:
504 PolicyHook policy_hook_;
505
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700506private:
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700507 boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700508
509 // necessary typedefs
510 typedef trie self_type;
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700511 typedef boost::intrusive::member_hook< trie,
512 boost::intrusive::unordered_set_member_hook< >,
513 &trie::unordered_set_member_hook_ > member_hook;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700514
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700515 typedef boost::intrusive::unordered_set< trie, member_hook > unordered_set;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700516 typedef typename unordered_set::bucket_type bucket_type;
517 typedef typename unordered_set::bucket_traits bucket_traits;
518
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700519 template<class T, class NonConstT>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700520 friend class trie_iterator;
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700521
522 template<class T>
523 friend class trie_point_iterator;
524
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700525 ////////////////////////////////////////////////
526 // Actual data
527 ////////////////////////////////////////////////
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800528
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700529 Key key_; ///< name component
530
531 size_t initialBucketSize_;
532 size_t bucketIncrement_;
533
534 size_t bucketSize_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700535 typedef boost::interprocess::unique_ptr< bucket_type, array_disposer<bucket_type> > buckets_array;
536 buckets_array buckets_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700537 unordered_set children_;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800538
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700539 typename PayloadTraits::storage_type payload_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700540 trie *parent_; // to make cleaning effective
541};
542
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700543
544
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700545
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700546template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700547inline std::ostream&
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700548operator << (std::ostream &os, const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700549{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700550 os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << std::endl;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700551 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700552
553 for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin ();
554 subnode != trie_node.children_.end ();
555 subnode++ )
556 // BOOST_FOREACH (const trie &subnode, trie_node.children_)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700557 {
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700558 os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]\n";
559 os << "\"" << &(*subnode) << "\"" << " [label=\"" << subnode->key_ << ((subnode->payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]""\n";
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800560
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700561 os << "\"" << &trie_node << "\"" << " -> " << "\"" << &(*subnode) << "\"" << "\n";
562 os << *subnode;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700563 }
564
565 return os;
566}
567
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700568template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700569inline void
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700570trie<FullKey, PayloadTraits, PolicyHook>
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700571::PrintStat (std::ostream &os) const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700572{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700573 os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload)?"*":"") << ": " << children_.size() << " children" << std::endl;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700574 for (size_t bucket = 0, maxbucket = children_.bucket_count ();
575 bucket < maxbucket;
576 bucket++)
577 {
578 os << " " << children_.bucket_size (bucket);
579 }
580 os << "\n";
581
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700582 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700583 for (typename trie::unordered_set::const_iterator subnode = children_.begin ();
584 subnode != children_.end ();
585 subnode++ )
586 // BOOST_FOREACH (const trie &subnode, children_)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700587 {
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700588 subnode->PrintStat (os);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700589 }
590}
591
592
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700593template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700594inline bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700595operator == (const trie<FullKey, PayloadTraits, PolicyHook> &a,
596 const trie<FullKey, PayloadTraits, PolicyHook> &b)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700597{
598 return a.key_ == b.key_;
599}
600
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700601template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700602inline std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700603hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700604{
605 return boost::hash_value (trie_node.key_);
606}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700607
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700608
609
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700610template<class Trie, class NonConstTrie> // hack for boost < 1.47
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700611class trie_iterator
612{
613public:
614 trie_iterator () : trie_ (0) {}
615 trie_iterator (typename Trie::iterator item) : trie_ (item) {}
616 trie_iterator (Trie &item) : trie_ (&item) {}
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800617
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700618 Trie & operator* () { return *trie_; }
619 const Trie & operator* () const { return *trie_; }
620 Trie * operator-> () { return trie_; }
621 const Trie * operator-> () const { return trie_; }
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700622 bool operator== (trie_iterator<const Trie, NonConstTrie> &other) const { return (trie_ == other.trie_); }
623 bool operator== (trie_iterator<Trie, NonConstTrie> &other) { return (trie_ == other.trie_); }
624 bool operator!= (trie_iterator<const Trie, NonConstTrie> &other) const { return !(*this == other); }
625 bool operator!= (trie_iterator<Trie, NonConstTrie> &other) { return !(*this == other); }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800626
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700627 trie_iterator<Trie,NonConstTrie> &
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700628 operator++ (int)
629 {
630 if (trie_->children_.size () > 0)
631 trie_ = &(*trie_->children_.begin ());
632 else
633 trie_ = goUp ();
634 return *this;
635 }
636
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700637 trie_iterator<Trie,NonConstTrie> &
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700638 operator++ ()
639 {
640 (*this)++;
641 return *this;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800642 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700643
644private:
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700645 typedef typename boost::mpl::if_< boost::is_same<Trie, NonConstTrie>,
646 typename Trie::unordered_set::iterator,
647 typename Trie::unordered_set::const_iterator>::type set_iterator;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800648
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700649 Trie* goUp ()
650 {
651 if (trie_->parent_ != 0)
652 {
653 // typename Trie::unordered_set::iterator item =
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700654 set_iterator item = const_cast<NonConstTrie*>(trie_)->parent_->children_.iterator_to (const_cast<NonConstTrie&> (*trie_));
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700655 item++;
656 if (item != trie_->parent_->children_.end ())
657 {
658 return &(*item);
659 }
660 else
661 {
662 trie_ = trie_->parent_;
663 return goUp ();
664 }
665 }
666 else
667 return 0;
668 }
669private:
670 Trie *trie_;
671};
672
673
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700674template<class Trie>
675class trie_point_iterator
676{
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800677private:
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700678 typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
679 typename Trie::unordered_set::const_iterator,
680 typename Trie::unordered_set::iterator>::type set_iterator;
681
682public:
683 trie_point_iterator () : trie_ (0) {}
684 trie_point_iterator (typename Trie::iterator item) : trie_ (item) {}
685 trie_point_iterator (Trie &item)
686 {
687 if (item.children_.size () != 0)
688 trie_ = &*item.children_.begin ();
689 else
690 trie_ = 0;
691 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800692
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700693 Trie & operator* () { return *trie_; }
694 const Trie & operator* () const { return *trie_; }
695 Trie * operator-> () { return trie_; }
696 const Trie * operator-> () const { return trie_; }
697 bool operator== (trie_point_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
698 bool operator== (trie_point_iterator<Trie> &other) { return (trie_ == other.trie_); }
699 bool operator!= (trie_point_iterator<const Trie> &other) const { return !(*this == other); }
700 bool operator!= (trie_point_iterator<Trie> &other) { return !(*this == other); }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800701
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700702 trie_point_iterator<Trie> &
703 operator++ (int)
704 {
705 if (trie_->parent_ != 0)
706 {
707 set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
708 item ++;
709 if (item == trie_->parent_->children_.end ())
710 trie_ = 0;
711 else
712 trie_ = &*item;
713 }
714 else
715 {
716 trie_ = 0;
717 }
718 return *this;
719 }
720
721 trie_point_iterator<Trie> &
722 operator++ ()
723 {
724 (*this)++;
725 return *this;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800726 }
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700727
728private:
729 Trie *trie_;
730};
731
732
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700733} // ndnSIM
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700734} // ndn
Alexander Afanasyeve77db792012-08-09 11:10:58 -0700735} // ns3
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700736
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700737#endif // TRIE_H_