blob: bcffdc3dd50c0500b15bbcd3b1af0149a6070c94 [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//
42template<typename Payload>
43struct 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 Afanasyev78057c32012-07-06 15:18:46 -070052 static Payload* empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070053};
54
55template<typename Payload>
Alexander Afanasyev78057c32012-07-06 15:18:46 -070056Payload*
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070057pointer_payload_traits<Payload>::empty_payload = 0;
58
59template<typename Payload>
60struct smart_pointer_payload_traits
61{
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070062 typedef Payload payload_type;
Alexander Afanasyev0845c092012-07-13 17:45:33 -070063 typedef ns3::Ptr<Payload> storage_type;
64 typedef ns3::Ptr<Payload> insert_type;
65
66 typedef ns3::Ptr<Payload> return_type;
67 typedef ns3::Ptr<const Payload> const_return_type;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070068
Alexander Afanasyev78057c32012-07-06 15:18:46 -070069 static ns3::Ptr<Payload> empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070070};
71
72template<typename Payload>
Alexander Afanasyev78057c32012-07-06 15:18:46 -070073ns3::Ptr<Payload>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070074smart_pointer_payload_traits<Payload>::empty_payload = 0;
75
Alexander Afanasyev0845c092012-07-13 17:45:33 -070076template<typename Payload>
77struct non_pointer_traits
78{
79 typedef Payload payload_type;
80 typedef Payload storage_type;
81 typedef const Payload & insert_type; // nothing to insert
82
83 typedef Payload& return_type;
84 typedef const Payload & const_return_type;
85
86 static Payload empty_payload;
87};
88
89template<typename Payload>
90Payload
91non_pointer_traits<Payload>::empty_payload = Payload ();
92
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070093
94////////////////////////////////////////////////////
95// forward declarations
96//
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070097template<typename FullKey,
Alexander Afanasyev9a989702012-06-29 17:44:00 -070098 typename PayloadTraits,
99 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700100class trie;
101
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700102template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700103inline std::ostream&
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700104operator << (std::ostream &os,
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700105 const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700106
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700107template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700108bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700109operator== (const trie<FullKey, PayloadTraits, PolicyHook> &a,
110 const trie<FullKey, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700111
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700112template<typename FullKey, typename PayloadTraits, typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700113std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700114hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700115
116///////////////////////////////////////////////////
117// actual definition
118//
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700119template<class T, class NonConstT>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700120class trie_iterator;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700121
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700122template<class T>
123class trie_point_iterator;
124
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700125template<typename FullKey,
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700126 typename PayloadTraits,
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700127 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700128class trie
129{
130public:
131 typedef typename FullKey::partial_type Key;
132
133 typedef trie* iterator;
134 typedef const trie* const_iterator;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700135
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700136 typedef trie_iterator<trie, trie> recursive_iterator;
137 typedef trie_iterator<const trie, trie> const_recursive_iterator;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700138
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700139 typedef trie_point_iterator<trie> point_iterator;
140 typedef trie_point_iterator<const trie> const_point_iterator;
141
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700142 typedef PayloadTraits payload_traits;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700143
144 inline
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700145 trie (const Key &key, size_t bucketSize = 10, size_t bucketIncrement = 10)
146 : key_ (key)
147 , initialBucketSize_ (bucketSize)
148 , bucketIncrement_ (bucketIncrement)
149 , bucketSize_ (initialBucketSize_)
150 , buckets_ (new bucket_type [bucketSize_]) //cannot use normal pointer, because lifetime of buckets should be larger than lifetime of the container
151 , children_ (bucket_traits (buckets_.get (), bucketSize_))
152 , payload_ (PayloadTraits::empty_payload)
153 , parent_ (0)
154 {
155 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700156
157 inline
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700158 ~trie ()
159 {
160 payload_ = PayloadTraits::empty_payload; // necessary for smart pointers...
161 children_.clear_and_dispose (trie_delete_disposer ());
162 }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700163
164 void
165 clear ()
166 {
167 children_.clear_and_dispose (trie_delete_disposer ());
168 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700169
170 template<class Predicate>
171 void
172 clear_if (Predicate cond)
173 {
174 recursive_iterator trieNode (this);
175 recursive_iterator end (0);
176
177 while (trieNode != end)
178 {
179 if (cond (*trieNode))
180 {
181 trieNode = recursive_iterator (trieNode->erase ());
182 }
183 trieNode ++;
184 }
185 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700186
187 // actual entry
188 friend bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700189 operator== <> (const trie<FullKey, PayloadTraits, PolicyHook> &a,
190 const trie<FullKey, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700191
192 friend std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700193 hash_value <> (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700194
195 inline std::pair<iterator, bool>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700196 insert (const FullKey &key,
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700197 typename PayloadTraits::insert_type payload)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700198 {
199 trie *trieNode = this;
200
201 BOOST_FOREACH (const Key &subkey, key)
202 {
203 typename unordered_set::iterator item = trieNode->children_.find (subkey);
204 if (item == trieNode->children_.end ())
205 {
206 trie *newNode = new trie (subkey, initialBucketSize_, bucketIncrement_);
207 // std::cout << "new " << newNode << "\n";
208 newNode->parent_ = trieNode;
209
210 if (trieNode->children_.size () >= trieNode->bucketSize_)
211 {
212 trieNode->bucketSize_ += trieNode->bucketIncrement_;
Alexander Afanasyev424d5842012-09-03 17:35:34 -0700213 trieNode->bucketIncrement_ *= 2; // increase bucketIncrement exponentially
214
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700215 buckets_array newBuckets (new bucket_type [trieNode->bucketSize_]);
216 trieNode->children_.rehash (bucket_traits (newBuckets.get (), trieNode->bucketSize_));
217 trieNode->buckets_.swap (newBuckets);
218 }
219
220 std::pair< typename unordered_set::iterator, bool > ret =
221 trieNode->children_.insert (*newNode);
222
223 trieNode = &(*ret.first);
224 }
225 else
226 trieNode = &(*item);
227 }
228
229 if (trieNode->payload_ == PayloadTraits::empty_payload)
230 {
231 trieNode->payload_ = payload;
232 return std::make_pair (trieNode, true);
233 }
234 else
235 return std::make_pair (trieNode, false);
236 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700237
238 /**
239 * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
240 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700241 inline iterator
242 erase ()
243 {
244 payload_ = PayloadTraits::empty_payload;
245 return prune ();
246 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700247
248 /**
249 * @brief Do exactly as erase, but without erasing the payload
250 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700251 inline iterator
252 prune ()
253 {
254 if (payload_ == PayloadTraits::empty_payload &&
255 children_.size () == 0)
256 {
257 if (parent_ == 0) return this;
258
259 trie *parent = parent_;
260 parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
261
262 return parent->prune ();
263 }
264 return this;
265 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700266
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700267 /**
268 * @brief Perform prune of the node, but without attempting to parent of the node
269 */
270 inline void
271 prune_node ()
272 {
273 if (payload_ == PayloadTraits::empty_payload &&
274 children_.size () == 0)
275 {
276 if (parent_ == 0) return;
277
278 trie *parent = parent_;
279 parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
280 }
281 }
282
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700283 // inline boost::tuple<const iterator, bool, const iterator>
284 // find (const FullKey &key) const
285 // {
286 // return const_cast<trie*> (this)->find (key);
287 // }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700288
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700289 /**
290 * @brief Perform the longest prefix match
291 * @param key the key for which to perform the longest prefix match
292 *
293 * @return ->second is true if prefix in ->first is longer than key
294 */
295 inline boost::tuple<iterator, bool, iterator>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700296 find (const FullKey &key)
297 {
298 trie *trieNode = this;
299 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
300 bool reachLast = true;
301
302 BOOST_FOREACH (const Key &subkey, key)
303 {
304 typename unordered_set::iterator item = trieNode->children_.find (subkey);
305 if (item == trieNode->children_.end ())
306 {
307 reachLast = false;
308 break;
309 }
310 else
311 {
312 trieNode = &(*item);
313
314 if (trieNode->payload_ != PayloadTraits::empty_payload)
315 foundNode = trieNode;
316 }
317 }
318
319 return boost::make_tuple (foundNode, reachLast, trieNode);
320 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700321
322 /**
323 * @brief Find next payload of the sub-trie
324 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
325 */
326 inline iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700327 find ()
328 {
329 if (payload_ != PayloadTraits::empty_payload)
330 return this;
331
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700332 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700333 for (typename trie::unordered_set::iterator subnode = children_.begin ();
334 subnode != children_.end ();
335 subnode++ )
336 // BOOST_FOREACH (trie &subnode, children_)
337 {
338 iterator value = subnode->find ();
339 if (value != 0)
340 return value;
341 }
342
343 return 0;
344 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700345
346 /**
347 * @brief Find next payload of the sub-trie satisfying the predicate
348 * @param pred predicate
349 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
350 */
351 template<class Predicate>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700352 inline const iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700353 find_if (Predicate pred)
354 {
355 if (payload_ != PayloadTraits::empty_payload && pred (payload_))
356 return this;
357
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700358 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700359 for (typename trie::unordered_set::iterator subnode = children_.begin ();
360 subnode != children_.end ();
361 subnode++ )
362 // BOOST_FOREACH (const trie &subnode, children_)
363 {
364 iterator value = subnode->find ();
365 if (value != 0)
366 return value;
367 }
368
369 return 0;
370 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700371
372 iterator end ()
373 {
374 return 0;
375 }
376
377 const_iterator end () const
378 {
379 return 0;
380 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700381
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700382 typename PayloadTraits::const_return_type
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700383 payload () const
384 {
385 return payload_;
386 }
387
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700388 typename PayloadTraits::return_type
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700389 payload ()
390 {
391 return payload_;
392 }
393
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700394 void
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700395 set_payload (typename PayloadTraits::insert_type payload)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700396 {
397 payload_ = payload;
398 }
Alexander Afanasyev0560eec2012-07-16 15:44:31 -0700399
400 Key key () const
401 {
402 return key_;
403 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700404
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700405 inline void
406 PrintStat (std::ostream &os) const;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700407
408private:
409 //The disposer object function
410 struct trie_delete_disposer
411 {
412 void operator() (trie *delete_this)
413 {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700414 delete delete_this;
415 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700416 };
417
418 template<class D>
419 struct array_disposer
420 {
421 void operator() (D *array)
422 {
423 delete [] array;
424 }
425 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700426
427 friend
428 std::ostream&
429 operator<< < > (std::ostream &os, const trie &trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700430
431public:
432 PolicyHook policy_hook_;
433
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700434private:
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700435 boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700436
437 // necessary typedefs
438 typedef trie self_type;
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700439 typedef boost::intrusive::member_hook< trie,
440 boost::intrusive::unordered_set_member_hook< >,
441 &trie::unordered_set_member_hook_ > member_hook;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700442
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700443 typedef boost::intrusive::unordered_set< trie, member_hook > unordered_set;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700444 typedef typename unordered_set::bucket_type bucket_type;
445 typedef typename unordered_set::bucket_traits bucket_traits;
446
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700447 template<class T, class NonConstT>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700448 friend class trie_iterator;
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700449
450 template<class T>
451 friend class trie_point_iterator;
452
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700453 ////////////////////////////////////////////////
454 // Actual data
455 ////////////////////////////////////////////////
456
457 Key key_; ///< name component
458
459 size_t initialBucketSize_;
460 size_t bucketIncrement_;
461
462 size_t bucketSize_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700463 typedef boost::interprocess::unique_ptr< bucket_type, array_disposer<bucket_type> > buckets_array;
464 buckets_array buckets_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700465 unordered_set children_;
466
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700467 typename PayloadTraits::storage_type payload_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700468 trie *parent_; // to make cleaning effective
469};
470
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700471
472
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700473
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700474template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700475inline std::ostream&
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700476operator << (std::ostream &os, const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700477{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700478 os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << std::endl;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700479 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700480
481 for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin ();
482 subnode != trie_node.children_.end ();
483 subnode++ )
484 // BOOST_FOREACH (const trie &subnode, trie_node.children_)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700485 {
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700486 os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]\n";
487 os << "\"" << &(*subnode) << "\"" << " [label=\"" << subnode->key_ << ((subnode->payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]""\n";
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700488
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700489 os << "\"" << &trie_node << "\"" << " -> " << "\"" << &(*subnode) << "\"" << "\n";
490 os << *subnode;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700491 }
492
493 return os;
494}
495
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700496template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700497inline void
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700498trie<FullKey, PayloadTraits, PolicyHook>
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700499::PrintStat (std::ostream &os) const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700500{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700501 os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload)?"*":"") << ": " << children_.size() << " children" << std::endl;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700502 for (size_t bucket = 0, maxbucket = children_.bucket_count ();
503 bucket < maxbucket;
504 bucket++)
505 {
506 os << " " << children_.bucket_size (bucket);
507 }
508 os << "\n";
509
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700510 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700511 for (typename trie::unordered_set::const_iterator subnode = children_.begin ();
512 subnode != children_.end ();
513 subnode++ )
514 // BOOST_FOREACH (const trie &subnode, children_)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700515 {
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700516 subnode->PrintStat (os);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700517 }
518}
519
520
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700521template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700522inline bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700523operator == (const trie<FullKey, PayloadTraits, PolicyHook> &a,
524 const trie<FullKey, PayloadTraits, PolicyHook> &b)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700525{
526 return a.key_ == b.key_;
527}
528
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700529template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700530inline std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700531hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700532{
533 return boost::hash_value (trie_node.key_);
534}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700535
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700536
537
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700538template<class Trie, class NonConstTrie> // hack for boost < 1.47
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700539class trie_iterator
540{
541public:
542 trie_iterator () : trie_ (0) {}
543 trie_iterator (typename Trie::iterator item) : trie_ (item) {}
544 trie_iterator (Trie &item) : trie_ (&item) {}
545
546 Trie & operator* () { return *trie_; }
547 const Trie & operator* () const { return *trie_; }
548 Trie * operator-> () { return trie_; }
549 const Trie * operator-> () const { return trie_; }
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700550 bool operator== (trie_iterator<const Trie, NonConstTrie> &other) const { return (trie_ == other.trie_); }
551 bool operator== (trie_iterator<Trie, NonConstTrie> &other) { return (trie_ == other.trie_); }
552 bool operator!= (trie_iterator<const Trie, NonConstTrie> &other) const { return !(*this == other); }
553 bool operator!= (trie_iterator<Trie, NonConstTrie> &other) { return !(*this == other); }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700554
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700555 trie_iterator<Trie,NonConstTrie> &
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700556 operator++ (int)
557 {
558 if (trie_->children_.size () > 0)
559 trie_ = &(*trie_->children_.begin ());
560 else
561 trie_ = goUp ();
562 return *this;
563 }
564
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700565 trie_iterator<Trie,NonConstTrie> &
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700566 operator++ ()
567 {
568 (*this)++;
569 return *this;
570 }
571
572private:
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700573 typedef typename boost::mpl::if_< boost::is_same<Trie, NonConstTrie>,
574 typename Trie::unordered_set::iterator,
575 typename Trie::unordered_set::const_iterator>::type set_iterator;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700576
577 Trie* goUp ()
578 {
579 if (trie_->parent_ != 0)
580 {
581 // typename Trie::unordered_set::iterator item =
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700582 set_iterator item = const_cast<NonConstTrie*>(trie_)->parent_->children_.iterator_to (const_cast<NonConstTrie&> (*trie_));
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700583 item++;
584 if (item != trie_->parent_->children_.end ())
585 {
586 return &(*item);
587 }
588 else
589 {
590 trie_ = trie_->parent_;
591 return goUp ();
592 }
593 }
594 else
595 return 0;
596 }
597private:
598 Trie *trie_;
599};
600
601
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700602template<class Trie>
603class trie_point_iterator
604{
605private:
606 typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
607 typename Trie::unordered_set::const_iterator,
608 typename Trie::unordered_set::iterator>::type set_iterator;
609
610public:
611 trie_point_iterator () : trie_ (0) {}
612 trie_point_iterator (typename Trie::iterator item) : trie_ (item) {}
613 trie_point_iterator (Trie &item)
614 {
615 if (item.children_.size () != 0)
616 trie_ = &*item.children_.begin ();
617 else
618 trie_ = 0;
619 }
620
621 Trie & operator* () { return *trie_; }
622 const Trie & operator* () const { return *trie_; }
623 Trie * operator-> () { return trie_; }
624 const Trie * operator-> () const { return trie_; }
625 bool operator== (trie_point_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
626 bool operator== (trie_point_iterator<Trie> &other) { return (trie_ == other.trie_); }
627 bool operator!= (trie_point_iterator<const Trie> &other) const { return !(*this == other); }
628 bool operator!= (trie_point_iterator<Trie> &other) { return !(*this == other); }
629
630 trie_point_iterator<Trie> &
631 operator++ (int)
632 {
633 if (trie_->parent_ != 0)
634 {
635 set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
636 item ++;
637 if (item == trie_->parent_->children_.end ())
638 trie_ = 0;
639 else
640 trie_ = &*item;
641 }
642 else
643 {
644 trie_ = 0;
645 }
646 return *this;
647 }
648
649 trie_point_iterator<Trie> &
650 operator++ ()
651 {
652 (*this)++;
653 return *this;
654 }
655
656private:
657 Trie *trie_;
658};
659
660
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700661} // ndnSIM
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700662} // ndn
Alexander Afanasyeve77db792012-08-09 11:10:58 -0700663} // ns3
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700664
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700665#endif // TRIE_H_