blob: a1f9dc728599e3996f66a37b1fad116bb761e71b [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 Afanasyev30f60e32012-07-10 14:21:16 -0700267 // inline boost::tuple<const iterator, bool, const iterator>
268 // find (const FullKey &key) const
269 // {
270 // return const_cast<trie*> (this)->find (key);
271 // }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700272
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700273 /**
274 * @brief Perform the longest prefix match
275 * @param key the key for which to perform the longest prefix match
276 *
277 * @return ->second is true if prefix in ->first is longer than key
278 */
279 inline boost::tuple<iterator, bool, iterator>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700280 find (const FullKey &key)
281 {
282 trie *trieNode = this;
283 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
284 bool reachLast = true;
285
286 BOOST_FOREACH (const Key &subkey, key)
287 {
288 typename unordered_set::iterator item = trieNode->children_.find (subkey);
289 if (item == trieNode->children_.end ())
290 {
291 reachLast = false;
292 break;
293 }
294 else
295 {
296 trieNode = &(*item);
297
298 if (trieNode->payload_ != PayloadTraits::empty_payload)
299 foundNode = trieNode;
300 }
301 }
302
303 return boost::make_tuple (foundNode, reachLast, trieNode);
304 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700305
306 /**
307 * @brief Find next payload of the sub-trie
308 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
309 */
310 inline iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700311 find ()
312 {
313 if (payload_ != PayloadTraits::empty_payload)
314 return this;
315
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700316 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700317 for (typename trie::unordered_set::iterator subnode = children_.begin ();
318 subnode != children_.end ();
319 subnode++ )
320 // BOOST_FOREACH (trie &subnode, children_)
321 {
322 iterator value = subnode->find ();
323 if (value != 0)
324 return value;
325 }
326
327 return 0;
328 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700329
330 /**
331 * @brief Find next payload of the sub-trie satisfying the predicate
332 * @param pred predicate
333 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
334 */
335 template<class Predicate>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700336 inline const iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700337 find_if (Predicate pred)
338 {
339 if (payload_ != PayloadTraits::empty_payload && pred (payload_))
340 return this;
341
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700342 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700343 for (typename trie::unordered_set::iterator subnode = children_.begin ();
344 subnode != children_.end ();
345 subnode++ )
346 // BOOST_FOREACH (const trie &subnode, children_)
347 {
348 iterator value = subnode->find ();
349 if (value != 0)
350 return value;
351 }
352
353 return 0;
354 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700355
356 iterator end ()
357 {
358 return 0;
359 }
360
361 const_iterator end () const
362 {
363 return 0;
364 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700365
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700366 typename PayloadTraits::const_return_type
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700367 payload () const
368 {
369 return payload_;
370 }
371
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700372 typename PayloadTraits::return_type
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700373 payload ()
374 {
375 return payload_;
376 }
377
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700378 void
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700379 set_payload (typename PayloadTraits::insert_type payload)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700380 {
381 payload_ = payload;
382 }
Alexander Afanasyev0560eec2012-07-16 15:44:31 -0700383
384 Key key () const
385 {
386 return key_;
387 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700388
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700389 inline void
390 PrintStat (std::ostream &os) const;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700391
392private:
393 //The disposer object function
394 struct trie_delete_disposer
395 {
396 void operator() (trie *delete_this)
397 {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700398 delete delete_this;
399 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700400 };
401
402 template<class D>
403 struct array_disposer
404 {
405 void operator() (D *array)
406 {
407 delete [] array;
408 }
409 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700410
411 friend
412 std::ostream&
413 operator<< < > (std::ostream &os, const trie &trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700414
415public:
416 PolicyHook policy_hook_;
417
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700418private:
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700419 boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700420
421 // necessary typedefs
422 typedef trie self_type;
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700423 typedef boost::intrusive::member_hook< trie,
424 boost::intrusive::unordered_set_member_hook< >,
425 &trie::unordered_set_member_hook_ > member_hook;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700426
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700427 typedef boost::intrusive::unordered_set< trie, member_hook > unordered_set;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700428 typedef typename unordered_set::bucket_type bucket_type;
429 typedef typename unordered_set::bucket_traits bucket_traits;
430
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700431 template<class T, class NonConstT>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700432 friend class trie_iterator;
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700433
434 template<class T>
435 friend class trie_point_iterator;
436
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700437 ////////////////////////////////////////////////
438 // Actual data
439 ////////////////////////////////////////////////
440
441 Key key_; ///< name component
442
443 size_t initialBucketSize_;
444 size_t bucketIncrement_;
445
446 size_t bucketSize_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700447 typedef boost::interprocess::unique_ptr< bucket_type, array_disposer<bucket_type> > buckets_array;
448 buckets_array buckets_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700449 unordered_set children_;
450
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700451 typename PayloadTraits::storage_type payload_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700452 trie *parent_; // to make cleaning effective
453};
454
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700455
456
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700457
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700458template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700459inline std::ostream&
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700460operator << (std::ostream &os, const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700461{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700462 os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << std::endl;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700463 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700464
465 for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin ();
466 subnode != trie_node.children_.end ();
467 subnode++ )
468 // BOOST_FOREACH (const trie &subnode, trie_node.children_)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700469 {
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700470 os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]\n";
471 os << "\"" << &(*subnode) << "\"" << " [label=\"" << subnode->key_ << ((subnode->payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]""\n";
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700472
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700473 os << "\"" << &trie_node << "\"" << " -> " << "\"" << &(*subnode) << "\"" << "\n";
474 os << *subnode;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700475 }
476
477 return os;
478}
479
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700480template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700481inline void
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700482trie<FullKey, PayloadTraits, PolicyHook>
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700483::PrintStat (std::ostream &os) const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700484{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700485 os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload)?"*":"") << ": " << children_.size() << " children" << std::endl;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700486 for (size_t bucket = 0, maxbucket = children_.bucket_count ();
487 bucket < maxbucket;
488 bucket++)
489 {
490 os << " " << children_.bucket_size (bucket);
491 }
492 os << "\n";
493
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700494 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700495 for (typename trie::unordered_set::const_iterator subnode = children_.begin ();
496 subnode != children_.end ();
497 subnode++ )
498 // BOOST_FOREACH (const trie &subnode, children_)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700499 {
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700500 subnode->PrintStat (os);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700501 }
502}
503
504
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700505template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700506inline bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700507operator == (const trie<FullKey, PayloadTraits, PolicyHook> &a,
508 const trie<FullKey, PayloadTraits, PolicyHook> &b)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700509{
510 return a.key_ == b.key_;
511}
512
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700513template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700514inline std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700515hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700516{
517 return boost::hash_value (trie_node.key_);
518}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700519
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700520
521
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700522template<class Trie, class NonConstTrie> // hack for boost < 1.47
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700523class trie_iterator
524{
525public:
526 trie_iterator () : trie_ (0) {}
527 trie_iterator (typename Trie::iterator item) : trie_ (item) {}
528 trie_iterator (Trie &item) : trie_ (&item) {}
529
530 Trie & operator* () { return *trie_; }
531 const Trie & operator* () const { return *trie_; }
532 Trie * operator-> () { return trie_; }
533 const Trie * operator-> () const { return trie_; }
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700534 bool operator== (trie_iterator<const Trie, NonConstTrie> &other) const { return (trie_ == other.trie_); }
535 bool operator== (trie_iterator<Trie, NonConstTrie> &other) { return (trie_ == other.trie_); }
536 bool operator!= (trie_iterator<const Trie, NonConstTrie> &other) const { return !(*this == other); }
537 bool operator!= (trie_iterator<Trie, NonConstTrie> &other) { return !(*this == other); }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700538
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700539 trie_iterator<Trie,NonConstTrie> &
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700540 operator++ (int)
541 {
542 if (trie_->children_.size () > 0)
543 trie_ = &(*trie_->children_.begin ());
544 else
545 trie_ = goUp ();
546 return *this;
547 }
548
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700549 trie_iterator<Trie,NonConstTrie> &
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700550 operator++ ()
551 {
552 (*this)++;
553 return *this;
554 }
555
556private:
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700557 typedef typename boost::mpl::if_< boost::is_same<Trie, NonConstTrie>,
558 typename Trie::unordered_set::iterator,
559 typename Trie::unordered_set::const_iterator>::type set_iterator;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700560
561 Trie* goUp ()
562 {
563 if (trie_->parent_ != 0)
564 {
565 // typename Trie::unordered_set::iterator item =
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700566 set_iterator item = const_cast<NonConstTrie*>(trie_)->parent_->children_.iterator_to (const_cast<NonConstTrie&> (*trie_));
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700567 item++;
568 if (item != trie_->parent_->children_.end ())
569 {
570 return &(*item);
571 }
572 else
573 {
574 trie_ = trie_->parent_;
575 return goUp ();
576 }
577 }
578 else
579 return 0;
580 }
581private:
582 Trie *trie_;
583};
584
585
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700586template<class Trie>
587class trie_point_iterator
588{
589private:
590 typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
591 typename Trie::unordered_set::const_iterator,
592 typename Trie::unordered_set::iterator>::type set_iterator;
593
594public:
595 trie_point_iterator () : trie_ (0) {}
596 trie_point_iterator (typename Trie::iterator item) : trie_ (item) {}
597 trie_point_iterator (Trie &item)
598 {
599 if (item.children_.size () != 0)
600 trie_ = &*item.children_.begin ();
601 else
602 trie_ = 0;
603 }
604
605 Trie & operator* () { return *trie_; }
606 const Trie & operator* () const { return *trie_; }
607 Trie * operator-> () { return trie_; }
608 const Trie * operator-> () const { return trie_; }
609 bool operator== (trie_point_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
610 bool operator== (trie_point_iterator<Trie> &other) { return (trie_ == other.trie_); }
611 bool operator!= (trie_point_iterator<const Trie> &other) const { return !(*this == other); }
612 bool operator!= (trie_point_iterator<Trie> &other) { return !(*this == other); }
613
614 trie_point_iterator<Trie> &
615 operator++ (int)
616 {
617 if (trie_->parent_ != 0)
618 {
619 set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
620 item ++;
621 if (item == trie_->parent_->children_.end ())
622 trie_ = 0;
623 else
624 trie_ = &*item;
625 }
626 else
627 {
628 trie_ = 0;
629 }
630 return *this;
631 }
632
633 trie_point_iterator<Trie> &
634 operator++ ()
635 {
636 (*this)++;
637 return *this;
638 }
639
640private:
641 Trie *trie_;
642};
643
644
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700645} // ndnSIM
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700646} // ndn
Alexander Afanasyeve77db792012-08-09 11:10:58 -0700647} // ns3
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700648
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700649#endif // TRIE_H_