blob: 4592fa58f8a8857a957c98f880a8bd6094a5a61b [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_;
213 buckets_array newBuckets (new bucket_type [trieNode->bucketSize_]);
214 trieNode->children_.rehash (bucket_traits (newBuckets.get (), trieNode->bucketSize_));
215 trieNode->buckets_.swap (newBuckets);
216 }
217
218 std::pair< typename unordered_set::iterator, bool > ret =
219 trieNode->children_.insert (*newNode);
220
221 trieNode = &(*ret.first);
222 }
223 else
224 trieNode = &(*item);
225 }
226
227 if (trieNode->payload_ == PayloadTraits::empty_payload)
228 {
229 trieNode->payload_ = payload;
230 return std::make_pair (trieNode, true);
231 }
232 else
233 return std::make_pair (trieNode, false);
234 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700235
236 /**
237 * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
238 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700239 inline iterator
240 erase ()
241 {
242 payload_ = PayloadTraits::empty_payload;
243 return prune ();
244 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700245
246 /**
247 * @brief Do exactly as erase, but without erasing the payload
248 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700249 inline iterator
250 prune ()
251 {
252 if (payload_ == PayloadTraits::empty_payload &&
253 children_.size () == 0)
254 {
255 if (parent_ == 0) return this;
256
257 trie *parent = parent_;
258 parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
259
260 return parent->prune ();
261 }
262 return this;
263 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700264
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700265 // inline boost::tuple<const iterator, bool, const iterator>
266 // find (const FullKey &key) const
267 // {
268 // return const_cast<trie*> (this)->find (key);
269 // }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700270
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700271 /**
272 * @brief Perform the longest prefix match
273 * @param key the key for which to perform the longest prefix match
274 *
275 * @return ->second is true if prefix in ->first is longer than key
276 */
277 inline boost::tuple<iterator, bool, iterator>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700278 find (const FullKey &key)
279 {
280 trie *trieNode = this;
281 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
282 bool reachLast = true;
283
284 BOOST_FOREACH (const Key &subkey, key)
285 {
286 typename unordered_set::iterator item = trieNode->children_.find (subkey);
287 if (item == trieNode->children_.end ())
288 {
289 reachLast = false;
290 break;
291 }
292 else
293 {
294 trieNode = &(*item);
295
296 if (trieNode->payload_ != PayloadTraits::empty_payload)
297 foundNode = trieNode;
298 }
299 }
300
301 return boost::make_tuple (foundNode, reachLast, trieNode);
302 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700303
304 /**
305 * @brief Find next payload of the sub-trie
306 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
307 */
308 inline iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700309 find ()
310 {
311 if (payload_ != PayloadTraits::empty_payload)
312 return this;
313
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700314 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700315 for (typename trie::unordered_set::iterator subnode = children_.begin ();
316 subnode != children_.end ();
317 subnode++ )
318 // BOOST_FOREACH (trie &subnode, children_)
319 {
320 iterator value = subnode->find ();
321 if (value != 0)
322 return value;
323 }
324
325 return 0;
326 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700327
328 /**
329 * @brief Find next payload of the sub-trie satisfying the predicate
330 * @param pred predicate
331 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
332 */
333 template<class Predicate>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700334 inline const iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700335 find_if (Predicate pred)
336 {
337 if (payload_ != PayloadTraits::empty_payload && pred (payload_))
338 return this;
339
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700340 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700341 for (typename trie::unordered_set::iterator subnode = children_.begin ();
342 subnode != children_.end ();
343 subnode++ )
344 // BOOST_FOREACH (const trie &subnode, children_)
345 {
346 iterator value = subnode->find ();
347 if (value != 0)
348 return value;
349 }
350
351 return 0;
352 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700353
354 iterator end ()
355 {
356 return 0;
357 }
358
359 const_iterator end () const
360 {
361 return 0;
362 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700363
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700364 typename PayloadTraits::const_return_type
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700365 payload () const
366 {
367 return payload_;
368 }
369
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700370 typename PayloadTraits::return_type
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700371 payload ()
372 {
373 return payload_;
374 }
375
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700376 void
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700377 set_payload (typename PayloadTraits::insert_type payload)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700378 {
379 payload_ = payload;
380 }
Alexander Afanasyev0560eec2012-07-16 15:44:31 -0700381
382 Key key () const
383 {
384 return key_;
385 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700386
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700387 inline void
388 PrintStat (std::ostream &os) const;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700389
390private:
391 //The disposer object function
392 struct trie_delete_disposer
393 {
394 void operator() (trie *delete_this)
395 {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700396 delete delete_this;
397 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700398 };
399
400 template<class D>
401 struct array_disposer
402 {
403 void operator() (D *array)
404 {
405 delete [] array;
406 }
407 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700408
409 friend
410 std::ostream&
411 operator<< < > (std::ostream &os, const trie &trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700412
413public:
414 PolicyHook policy_hook_;
415
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700416private:
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700417 boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700418
419 // necessary typedefs
420 typedef trie self_type;
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700421 typedef boost::intrusive::member_hook< trie,
422 boost::intrusive::unordered_set_member_hook< >,
423 &trie::unordered_set_member_hook_ > member_hook;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700424
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700425 typedef boost::intrusive::unordered_set< trie, member_hook > unordered_set;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700426 typedef typename unordered_set::bucket_type bucket_type;
427 typedef typename unordered_set::bucket_traits bucket_traits;
428
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700429 template<class T, class NonConstT>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700430 friend class trie_iterator;
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700431
432 template<class T>
433 friend class trie_point_iterator;
434
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700435 ////////////////////////////////////////////////
436 // Actual data
437 ////////////////////////////////////////////////
438
439 Key key_; ///< name component
440
441 size_t initialBucketSize_;
442 size_t bucketIncrement_;
443
444 size_t bucketSize_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700445 typedef boost::interprocess::unique_ptr< bucket_type, array_disposer<bucket_type> > buckets_array;
446 buckets_array buckets_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700447 unordered_set children_;
448
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700449 typename PayloadTraits::storage_type payload_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700450 trie *parent_; // to make cleaning effective
451};
452
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700453
454
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700455
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700456template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700457inline std::ostream&
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700458operator << (std::ostream &os, const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700459{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700460 os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << std::endl;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700461 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700462
463 for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin ();
464 subnode != trie_node.children_.end ();
465 subnode++ )
466 // BOOST_FOREACH (const trie &subnode, trie_node.children_)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700467 {
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700468 os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]\n";
469 os << "\"" << &(*subnode) << "\"" << " [label=\"" << subnode->key_ << ((subnode->payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]""\n";
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700470
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700471 os << "\"" << &trie_node << "\"" << " -> " << "\"" << &(*subnode) << "\"" << "\n";
472 os << *subnode;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700473 }
474
475 return os;
476}
477
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700478template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700479inline void
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700480trie<FullKey, PayloadTraits, PolicyHook>
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700481::PrintStat (std::ostream &os) const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700482{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700483 os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload)?"*":"") << ": " << children_.size() << " children" << std::endl;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700484 for (size_t bucket = 0, maxbucket = children_.bucket_count ();
485 bucket < maxbucket;
486 bucket++)
487 {
488 os << " " << children_.bucket_size (bucket);
489 }
490 os << "\n";
491
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700492 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700493 for (typename trie::unordered_set::const_iterator subnode = children_.begin ();
494 subnode != children_.end ();
495 subnode++ )
496 // BOOST_FOREACH (const trie &subnode, children_)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700497 {
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700498 subnode->PrintStat (os);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700499 }
500}
501
502
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700503template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700504inline bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700505operator == (const trie<FullKey, PayloadTraits, PolicyHook> &a,
506 const trie<FullKey, PayloadTraits, PolicyHook> &b)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700507{
508 return a.key_ == b.key_;
509}
510
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700511template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700512inline std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700513hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700514{
515 return boost::hash_value (trie_node.key_);
516}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700517
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700518
519
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700520template<class Trie, class NonConstTrie> // hack for boost < 1.47
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700521class trie_iterator
522{
523public:
524 trie_iterator () : trie_ (0) {}
525 trie_iterator (typename Trie::iterator item) : trie_ (item) {}
526 trie_iterator (Trie &item) : trie_ (&item) {}
527
528 Trie & operator* () { return *trie_; }
529 const Trie & operator* () const { return *trie_; }
530 Trie * operator-> () { return trie_; }
531 const Trie * operator-> () const { return trie_; }
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700532 bool operator== (trie_iterator<const Trie, NonConstTrie> &other) const { return (trie_ == other.trie_); }
533 bool operator== (trie_iterator<Trie, NonConstTrie> &other) { return (trie_ == other.trie_); }
534 bool operator!= (trie_iterator<const Trie, NonConstTrie> &other) const { return !(*this == other); }
535 bool operator!= (trie_iterator<Trie, NonConstTrie> &other) { return !(*this == other); }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700536
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700537 trie_iterator<Trie,NonConstTrie> &
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700538 operator++ (int)
539 {
540 if (trie_->children_.size () > 0)
541 trie_ = &(*trie_->children_.begin ());
542 else
543 trie_ = goUp ();
544 return *this;
545 }
546
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700547 trie_iterator<Trie,NonConstTrie> &
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700548 operator++ ()
549 {
550 (*this)++;
551 return *this;
552 }
553
554private:
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700555 typedef typename boost::mpl::if_< boost::is_same<Trie, NonConstTrie>,
556 typename Trie::unordered_set::iterator,
557 typename Trie::unordered_set::const_iterator>::type set_iterator;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700558
559 Trie* goUp ()
560 {
561 if (trie_->parent_ != 0)
562 {
563 // typename Trie::unordered_set::iterator item =
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700564 set_iterator item = const_cast<NonConstTrie*>(trie_)->parent_->children_.iterator_to (const_cast<NonConstTrie&> (*trie_));
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700565 item++;
566 if (item != trie_->parent_->children_.end ())
567 {
568 return &(*item);
569 }
570 else
571 {
572 trie_ = trie_->parent_;
573 return goUp ();
574 }
575 }
576 else
577 return 0;
578 }
579private:
580 Trie *trie_;
581};
582
583
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700584template<class Trie>
585class trie_point_iterator
586{
587private:
588 typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
589 typename Trie::unordered_set::const_iterator,
590 typename Trie::unordered_set::iterator>::type set_iterator;
591
592public:
593 trie_point_iterator () : trie_ (0) {}
594 trie_point_iterator (typename Trie::iterator item) : trie_ (item) {}
595 trie_point_iterator (Trie &item)
596 {
597 if (item.children_.size () != 0)
598 trie_ = &*item.children_.begin ();
599 else
600 trie_ = 0;
601 }
602
603 Trie & operator* () { return *trie_; }
604 const Trie & operator* () const { return *trie_; }
605 Trie * operator-> () { return trie_; }
606 const Trie * operator-> () const { return trie_; }
607 bool operator== (trie_point_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
608 bool operator== (trie_point_iterator<Trie> &other) { return (trie_ == other.trie_); }
609 bool operator!= (trie_point_iterator<const Trie> &other) const { return !(*this == other); }
610 bool operator!= (trie_point_iterator<Trie> &other) { return !(*this == other); }
611
612 trie_point_iterator<Trie> &
613 operator++ (int)
614 {
615 if (trie_->parent_ != 0)
616 {
617 set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
618 item ++;
619 if (item == trie_->parent_->children_.end ())
620 trie_ = 0;
621 else
622 trie_ = &*item;
623 }
624 else
625 {
626 trie_ = 0;
627 }
628 return *this;
629 }
630
631 trie_point_iterator<Trie> &
632 operator++ ()
633 {
634 (*this)++;
635 return *this;
636 }
637
638private:
639 Trie *trie_;
640};
641
642
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700643} // ndnSIM
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700644} // ndn
Alexander Afanasyeve77db792012-08-09 11:10:58 -0700645} // ns3
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700646
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700647#endif // TRIE_H_