blob: fe52d594ad30ee3891df49707e8642d31902b5ac [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 Afanasyeve77db792012-08-09 11:10:58 -070035namespace ns3
36{
Alexander Afanasyev30cb1172012-07-06 10:47:39 -070037namespace ndnSIM
38{
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070039
40/////////////////////////////////////////////////////
41// Allow customization for payload
42//
43template<typename Payload>
44struct pointer_payload_traits
45{
Alexander Afanasyev0845c092012-07-13 17:45:33 -070046 typedef Payload payload_type; // general type of the payload
47 typedef Payload* storage_type; // how the payload is actually stored
48 typedef Payload* insert_type; // what parameter is inserted
49
50 typedef Payload* return_type; // what is returned on access
51 typedef const Payload* const_return_type; // what is returned on const access
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070052
Alexander Afanasyev78057c32012-07-06 15:18:46 -070053 static Payload* empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070054};
55
56template<typename Payload>
Alexander Afanasyev78057c32012-07-06 15:18:46 -070057Payload*
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070058pointer_payload_traits<Payload>::empty_payload = 0;
59
60template<typename Payload>
61struct smart_pointer_payload_traits
62{
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070063 typedef Payload payload_type;
Alexander Afanasyev0845c092012-07-13 17:45:33 -070064 typedef ns3::Ptr<Payload> storage_type;
65 typedef ns3::Ptr<Payload> insert_type;
66
67 typedef ns3::Ptr<Payload> return_type;
68 typedef ns3::Ptr<const Payload> const_return_type;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070069
Alexander Afanasyev78057c32012-07-06 15:18:46 -070070 static ns3::Ptr<Payload> empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070071};
72
73template<typename Payload>
Alexander Afanasyev78057c32012-07-06 15:18:46 -070074ns3::Ptr<Payload>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070075smart_pointer_payload_traits<Payload>::empty_payload = 0;
76
Alexander Afanasyev0845c092012-07-13 17:45:33 -070077template<typename Payload>
78struct non_pointer_traits
79{
80 typedef Payload payload_type;
81 typedef Payload storage_type;
82 typedef const Payload & insert_type; // nothing to insert
83
84 typedef Payload& return_type;
85 typedef const Payload & const_return_type;
86
87 static Payload empty_payload;
88};
89
90template<typename Payload>
91Payload
92non_pointer_traits<Payload>::empty_payload = Payload ();
93
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070094
95////////////////////////////////////////////////////
96// forward declarations
97//
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070098template<typename FullKey,
Alexander Afanasyev9a989702012-06-29 17:44:00 -070099 typename PayloadTraits,
100 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700101class trie;
102
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700103template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700104inline std::ostream&
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700105operator << (std::ostream &os,
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700106 const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700107
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700108template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700109bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700110operator== (const trie<FullKey, PayloadTraits, PolicyHook> &a,
111 const trie<FullKey, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700112
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700113template<typename FullKey, typename PayloadTraits, typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700114std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700115hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700116
117///////////////////////////////////////////////////
118// actual definition
119//
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700120template<class T, class NonConstT>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700121class trie_iterator;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700122
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700123template<class T>
124class trie_point_iterator;
125
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700126template<typename FullKey,
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700127 typename PayloadTraits,
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700128 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700129class trie
130{
131public:
132 typedef typename FullKey::partial_type Key;
133
134 typedef trie* iterator;
135 typedef const trie* const_iterator;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700136
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700137 typedef trie_iterator<trie, trie> recursive_iterator;
138 typedef trie_iterator<const trie, trie> const_recursive_iterator;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700139
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700140 typedef trie_point_iterator<trie> point_iterator;
141 typedef trie_point_iterator<const trie> const_point_iterator;
142
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700143 typedef PayloadTraits payload_traits;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700144
145 inline
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700146 trie (const Key &key, size_t bucketSize = 10, size_t bucketIncrement = 10)
147 : key_ (key)
148 , initialBucketSize_ (bucketSize)
149 , bucketIncrement_ (bucketIncrement)
150 , bucketSize_ (initialBucketSize_)
151 , buckets_ (new bucket_type [bucketSize_]) //cannot use normal pointer, because lifetime of buckets should be larger than lifetime of the container
152 , children_ (bucket_traits (buckets_.get (), bucketSize_))
153 , payload_ (PayloadTraits::empty_payload)
154 , parent_ (0)
155 {
156 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700157
158 inline
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700159 ~trie ()
160 {
161 payload_ = PayloadTraits::empty_payload; // necessary for smart pointers...
162 children_.clear_and_dispose (trie_delete_disposer ());
163 }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700164
165 void
166 clear ()
167 {
168 children_.clear_and_dispose (trie_delete_disposer ());
169 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700170
171 template<class Predicate>
172 void
173 clear_if (Predicate cond)
174 {
175 recursive_iterator trieNode (this);
176 recursive_iterator end (0);
177
178 while (trieNode != end)
179 {
180 if (cond (*trieNode))
181 {
182 trieNode = recursive_iterator (trieNode->erase ());
183 }
184 trieNode ++;
185 }
186 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700187
188 // actual entry
189 friend bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700190 operator== <> (const trie<FullKey, PayloadTraits, PolicyHook> &a,
191 const trie<FullKey, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700192
193 friend std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700194 hash_value <> (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700195
196 inline std::pair<iterator, bool>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700197 insert (const FullKey &key,
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700198 typename PayloadTraits::insert_type payload)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700199 {
200 trie *trieNode = this;
201
202 BOOST_FOREACH (const Key &subkey, key)
203 {
204 typename unordered_set::iterator item = trieNode->children_.find (subkey);
205 if (item == trieNode->children_.end ())
206 {
207 trie *newNode = new trie (subkey, initialBucketSize_, bucketIncrement_);
208 // std::cout << "new " << newNode << "\n";
209 newNode->parent_ = trieNode;
210
211 if (trieNode->children_.size () >= trieNode->bucketSize_)
212 {
213 trieNode->bucketSize_ += trieNode->bucketIncrement_;
214 buckets_array newBuckets (new bucket_type [trieNode->bucketSize_]);
215 trieNode->children_.rehash (bucket_traits (newBuckets.get (), trieNode->bucketSize_));
216 trieNode->buckets_.swap (newBuckets);
217 }
218
219 std::pair< typename unordered_set::iterator, bool > ret =
220 trieNode->children_.insert (*newNode);
221
222 trieNode = &(*ret.first);
223 }
224 else
225 trieNode = &(*item);
226 }
227
228 if (trieNode->payload_ == PayloadTraits::empty_payload)
229 {
230 trieNode->payload_ = payload;
231 return std::make_pair (trieNode, true);
232 }
233 else
234 return std::make_pair (trieNode, false);
235 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700236
237 /**
238 * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
239 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700240 inline iterator
241 erase ()
242 {
243 payload_ = PayloadTraits::empty_payload;
244 return prune ();
245 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700246
247 /**
248 * @brief Do exactly as erase, but without erasing the payload
249 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700250 inline iterator
251 prune ()
252 {
253 if (payload_ == PayloadTraits::empty_payload &&
254 children_.size () == 0)
255 {
256 if (parent_ == 0) return this;
257
258 trie *parent = parent_;
259 parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
260
261 return parent->prune ();
262 }
263 return this;
264 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700265
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700266 // inline boost::tuple<const iterator, bool, const iterator>
267 // find (const FullKey &key) const
268 // {
269 // return const_cast<trie*> (this)->find (key);
270 // }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700271
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700272 /**
273 * @brief Perform the longest prefix match
274 * @param key the key for which to perform the longest prefix match
275 *
276 * @return ->second is true if prefix in ->first is longer than key
277 */
278 inline boost::tuple<iterator, bool, iterator>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700279 find (const FullKey &key)
280 {
281 trie *trieNode = this;
282 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
283 bool reachLast = true;
284
285 BOOST_FOREACH (const Key &subkey, key)
286 {
287 typename unordered_set::iterator item = trieNode->children_.find (subkey);
288 if (item == trieNode->children_.end ())
289 {
290 reachLast = false;
291 break;
292 }
293 else
294 {
295 trieNode = &(*item);
296
297 if (trieNode->payload_ != PayloadTraits::empty_payload)
298 foundNode = trieNode;
299 }
300 }
301
302 return boost::make_tuple (foundNode, reachLast, trieNode);
303 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700304
305 /**
306 * @brief Find next payload of the sub-trie
307 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
308 */
309 inline iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700310 find ()
311 {
312 if (payload_ != PayloadTraits::empty_payload)
313 return this;
314
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700315 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700316 for (typename trie::unordered_set::iterator subnode = children_.begin ();
317 subnode != children_.end ();
318 subnode++ )
319 // BOOST_FOREACH (trie &subnode, children_)
320 {
321 iterator value = subnode->find ();
322 if (value != 0)
323 return value;
324 }
325
326 return 0;
327 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700328
329 /**
330 * @brief Find next payload of the sub-trie satisfying the predicate
331 * @param pred predicate
332 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
333 */
334 template<class Predicate>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700335 inline const iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700336 find_if (Predicate pred)
337 {
338 if (payload_ != PayloadTraits::empty_payload && pred (payload_))
339 return this;
340
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700341 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700342 for (typename trie::unordered_set::iterator subnode = children_.begin ();
343 subnode != children_.end ();
344 subnode++ )
345 // BOOST_FOREACH (const trie &subnode, children_)
346 {
347 iterator value = subnode->find ();
348 if (value != 0)
349 return value;
350 }
351
352 return 0;
353 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700354
355 iterator end ()
356 {
357 return 0;
358 }
359
360 const_iterator end () const
361 {
362 return 0;
363 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700364
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700365 typename PayloadTraits::const_return_type
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700366 payload () const
367 {
368 return payload_;
369 }
370
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700371 typename PayloadTraits::return_type
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700372 payload ()
373 {
374 return payload_;
375 }
376
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700377 void
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700378 set_payload (typename PayloadTraits::insert_type payload)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700379 {
380 payload_ = payload;
381 }
Alexander Afanasyev0560eec2012-07-16 15:44:31 -0700382
383 Key key () const
384 {
385 return key_;
386 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700387
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700388 inline void
389 PrintStat (std::ostream &os) const;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700390
391private:
392 //The disposer object function
393 struct trie_delete_disposer
394 {
395 void operator() (trie *delete_this)
396 {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700397 delete delete_this;
398 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700399 };
400
401 template<class D>
402 struct array_disposer
403 {
404 void operator() (D *array)
405 {
406 delete [] array;
407 }
408 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700409
410 friend
411 std::ostream&
412 operator<< < > (std::ostream &os, const trie &trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700413
414public:
415 PolicyHook policy_hook_;
416
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700417private:
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700418 boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700419
420 // necessary typedefs
421 typedef trie self_type;
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700422 typedef boost::intrusive::member_hook< trie,
423 boost::intrusive::unordered_set_member_hook< >,
424 &trie::unordered_set_member_hook_ > member_hook;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700425
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700426 typedef boost::intrusive::unordered_set< trie, member_hook > unordered_set;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700427 typedef typename unordered_set::bucket_type bucket_type;
428 typedef typename unordered_set::bucket_traits bucket_traits;
429
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700430 template<class T, class NonConstT>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700431 friend class trie_iterator;
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700432
433 template<class T>
434 friend class trie_point_iterator;
435
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700436 ////////////////////////////////////////////////
437 // Actual data
438 ////////////////////////////////////////////////
439
440 Key key_; ///< name component
441
442 size_t initialBucketSize_;
443 size_t bucketIncrement_;
444
445 size_t bucketSize_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700446 typedef boost::interprocess::unique_ptr< bucket_type, array_disposer<bucket_type> > buckets_array;
447 buckets_array buckets_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700448 unordered_set children_;
449
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700450 typename PayloadTraits::storage_type payload_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700451 trie *parent_; // to make cleaning effective
452};
453
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700454
455
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700456
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700457template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700458inline std::ostream&
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700459operator << (std::ostream &os, const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700460{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700461 os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << std::endl;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700462 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700463
464 for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin ();
465 subnode != trie_node.children_.end ();
466 subnode++ )
467 // BOOST_FOREACH (const trie &subnode, trie_node.children_)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700468 {
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700469 os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]\n";
470 os << "\"" << &(*subnode) << "\"" << " [label=\"" << subnode->key_ << ((subnode->payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]""\n";
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700471
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700472 os << "\"" << &trie_node << "\"" << " -> " << "\"" << &(*subnode) << "\"" << "\n";
473 os << *subnode;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700474 }
475
476 return os;
477}
478
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700479template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700480inline void
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700481trie<FullKey, PayloadTraits, PolicyHook>
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700482::PrintStat (std::ostream &os) const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700483{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700484 os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload)?"*":"") << ": " << children_.size() << " children" << std::endl;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700485 for (size_t bucket = 0, maxbucket = children_.bucket_count ();
486 bucket < maxbucket;
487 bucket++)
488 {
489 os << " " << children_.bucket_size (bucket);
490 }
491 os << "\n";
492
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700493 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700494 for (typename trie::unordered_set::const_iterator subnode = children_.begin ();
495 subnode != children_.end ();
496 subnode++ )
497 // BOOST_FOREACH (const trie &subnode, children_)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700498 {
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700499 subnode->PrintStat (os);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700500 }
501}
502
503
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700504template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700505inline bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700506operator == (const trie<FullKey, PayloadTraits, PolicyHook> &a,
507 const trie<FullKey, PayloadTraits, PolicyHook> &b)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700508{
509 return a.key_ == b.key_;
510}
511
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700512template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700513inline std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700514hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700515{
516 return boost::hash_value (trie_node.key_);
517}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700518
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700519
520
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700521template<class Trie, class NonConstTrie> // hack for boost < 1.47
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700522class trie_iterator
523{
524public:
525 trie_iterator () : trie_ (0) {}
526 trie_iterator (typename Trie::iterator item) : trie_ (item) {}
527 trie_iterator (Trie &item) : trie_ (&item) {}
528
529 Trie & operator* () { return *trie_; }
530 const Trie & operator* () const { return *trie_; }
531 Trie * operator-> () { return trie_; }
532 const Trie * operator-> () const { return trie_; }
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700533 bool operator== (trie_iterator<const Trie, NonConstTrie> &other) const { return (trie_ == other.trie_); }
534 bool operator== (trie_iterator<Trie, NonConstTrie> &other) { return (trie_ == other.trie_); }
535 bool operator!= (trie_iterator<const Trie, NonConstTrie> &other) const { return !(*this == other); }
536 bool operator!= (trie_iterator<Trie, NonConstTrie> &other) { return !(*this == other); }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700537
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700538 trie_iterator<Trie,NonConstTrie> &
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700539 operator++ (int)
540 {
541 if (trie_->children_.size () > 0)
542 trie_ = &(*trie_->children_.begin ());
543 else
544 trie_ = goUp ();
545 return *this;
546 }
547
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700548 trie_iterator<Trie,NonConstTrie> &
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700549 operator++ ()
550 {
551 (*this)++;
552 return *this;
553 }
554
555private:
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700556 typedef typename boost::mpl::if_< boost::is_same<Trie, NonConstTrie>,
557 typename Trie::unordered_set::iterator,
558 typename Trie::unordered_set::const_iterator>::type set_iterator;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700559
560 Trie* goUp ()
561 {
562 if (trie_->parent_ != 0)
563 {
564 // typename Trie::unordered_set::iterator item =
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700565 set_iterator item = const_cast<NonConstTrie*>(trie_)->parent_->children_.iterator_to (const_cast<NonConstTrie&> (*trie_));
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700566 item++;
567 if (item != trie_->parent_->children_.end ())
568 {
569 return &(*item);
570 }
571 else
572 {
573 trie_ = trie_->parent_;
574 return goUp ();
575 }
576 }
577 else
578 return 0;
579 }
580private:
581 Trie *trie_;
582};
583
584
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700585template<class Trie>
586class trie_point_iterator
587{
588private:
589 typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
590 typename Trie::unordered_set::const_iterator,
591 typename Trie::unordered_set::iterator>::type set_iterator;
592
593public:
594 trie_point_iterator () : trie_ (0) {}
595 trie_point_iterator (typename Trie::iterator item) : trie_ (item) {}
596 trie_point_iterator (Trie &item)
597 {
598 if (item.children_.size () != 0)
599 trie_ = &*item.children_.begin ();
600 else
601 trie_ = 0;
602 }
603
604 Trie & operator* () { return *trie_; }
605 const Trie & operator* () const { return *trie_; }
606 Trie * operator-> () { return trie_; }
607 const Trie * operator-> () const { return trie_; }
608 bool operator== (trie_point_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
609 bool operator== (trie_point_iterator<Trie> &other) { return (trie_ == other.trie_); }
610 bool operator!= (trie_point_iterator<const Trie> &other) const { return !(*this == other); }
611 bool operator!= (trie_point_iterator<Trie> &other) { return !(*this == other); }
612
613 trie_point_iterator<Trie> &
614 operator++ (int)
615 {
616 if (trie_->parent_ != 0)
617 {
618 set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
619 item ++;
620 if (item == trie_->parent_->children_.end ())
621 trie_ = 0;
622 else
623 trie_ = &*item;
624 }
625 else
626 {
627 trie_ = 0;
628 }
629 return *this;
630 }
631
632 trie_point_iterator<Trie> &
633 operator++ ()
634 {
635 (*this)++;
636 return *this;
637 }
638
639private:
640 Trie *trie_;
641};
642
643
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700644} // ndnSIM
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_