blob: dbd3e1d81b153085980da7df2b71d5ed8a0b3a48 [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 Afanasyev30cb1172012-07-06 10:47:39 -070035namespace ndnSIM
36{
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070037
38/////////////////////////////////////////////////////
39// Allow customization for payload
40//
41template<typename Payload>
42struct pointer_payload_traits
43{
Alexander Afanasyev0845c092012-07-13 17:45:33 -070044 typedef Payload payload_type; // general type of the payload
45 typedef Payload* storage_type; // how the payload is actually stored
46 typedef Payload* insert_type; // what parameter is inserted
47
48 typedef Payload* return_type; // what is returned on access
49 typedef const Payload* const_return_type; // what is returned on const access
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070050
Alexander Afanasyev78057c32012-07-06 15:18:46 -070051 static Payload* empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070052};
53
54template<typename Payload>
Alexander Afanasyev78057c32012-07-06 15:18:46 -070055Payload*
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070056pointer_payload_traits<Payload>::empty_payload = 0;
57
58template<typename Payload>
59struct smart_pointer_payload_traits
60{
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070061 typedef Payload payload_type;
Alexander Afanasyev0845c092012-07-13 17:45:33 -070062 typedef ns3::Ptr<Payload> storage_type;
63 typedef ns3::Ptr<Payload> insert_type;
64
65 typedef ns3::Ptr<Payload> return_type;
66 typedef ns3::Ptr<const Payload> const_return_type;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070067
Alexander Afanasyev78057c32012-07-06 15:18:46 -070068 static ns3::Ptr<Payload> empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070069};
70
71template<typename Payload>
Alexander Afanasyev78057c32012-07-06 15:18:46 -070072ns3::Ptr<Payload>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070073smart_pointer_payload_traits<Payload>::empty_payload = 0;
74
Alexander Afanasyev0845c092012-07-13 17:45:33 -070075template<typename Payload>
76struct non_pointer_traits
77{
78 typedef Payload payload_type;
79 typedef Payload storage_type;
80 typedef const Payload & insert_type; // nothing to insert
81
82 typedef Payload& return_type;
83 typedef const Payload & const_return_type;
84
85 static Payload empty_payload;
86};
87
88template<typename Payload>
89Payload
90non_pointer_traits<Payload>::empty_payload = Payload ();
91
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070092
93////////////////////////////////////////////////////
94// forward declarations
95//
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070096template<typename FullKey,
Alexander Afanasyev9a989702012-06-29 17:44:00 -070097 typename PayloadTraits,
98 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070099class trie;
100
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700101template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700102inline std::ostream&
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700103operator << (std::ostream &os,
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700104 const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700105
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700106template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700107bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700108operator== (const trie<FullKey, PayloadTraits, PolicyHook> &a,
109 const trie<FullKey, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700110
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700111template<typename FullKey, typename PayloadTraits, typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700112std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700113hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700114
115///////////////////////////////////////////////////
116// actual definition
117//
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700118template<class T>
119class trie_iterator;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700120
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700121template<class T>
122class trie_point_iterator;
123
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700124template<typename FullKey,
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700125 typename PayloadTraits,
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700126 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700127class trie
128{
129public:
130 typedef typename FullKey::partial_type Key;
131
132 typedef trie* iterator;
133 typedef const trie* const_iterator;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700134
135 typedef trie_iterator<trie> recursive_iterator;
136 typedef trie_iterator<const trie> const_recursive_iterator;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700137
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700138 typedef trie_point_iterator<trie> point_iterator;
139 typedef trie_point_iterator<const trie> const_point_iterator;
140
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700141 typedef PayloadTraits payload_traits;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700142
143 inline
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700144 trie (const Key &key, size_t bucketSize = 10, size_t bucketIncrement = 10)
145 : key_ (key)
146 , initialBucketSize_ (bucketSize)
147 , bucketIncrement_ (bucketIncrement)
148 , bucketSize_ (initialBucketSize_)
149 , buckets_ (new bucket_type [bucketSize_]) //cannot use normal pointer, because lifetime of buckets should be larger than lifetime of the container
150 , children_ (bucket_traits (buckets_.get (), bucketSize_))
151 , payload_ (PayloadTraits::empty_payload)
152 , parent_ (0)
153 {
154 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700155
156 inline
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700157 ~trie ()
158 {
159 payload_ = PayloadTraits::empty_payload; // necessary for smart pointers...
160 children_.clear_and_dispose (trie_delete_disposer ());
161 }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700162
163 void
164 clear ()
165 {
166 children_.clear_and_dispose (trie_delete_disposer ());
167 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700168
169 template<class Predicate>
170 void
171 clear_if (Predicate cond)
172 {
173 recursive_iterator trieNode (this);
174 recursive_iterator end (0);
175
176 while (trieNode != end)
177 {
178 if (cond (*trieNode))
179 {
180 trieNode = recursive_iterator (trieNode->erase ());
181 }
182 trieNode ++;
183 }
184 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700185
186 // actual entry
187 friend bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700188 operator== <> (const trie<FullKey, PayloadTraits, PolicyHook> &a,
189 const trie<FullKey, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700190
191 friend std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700192 hash_value <> (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700193
194 inline std::pair<iterator, bool>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700195 insert (const FullKey &key,
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700196 typename PayloadTraits::insert_type payload)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700197 {
198 trie *trieNode = this;
199
200 BOOST_FOREACH (const Key &subkey, key)
201 {
202 typename unordered_set::iterator item = trieNode->children_.find (subkey);
203 if (item == trieNode->children_.end ())
204 {
205 trie *newNode = new trie (subkey, initialBucketSize_, bucketIncrement_);
206 // std::cout << "new " << newNode << "\n";
207 newNode->parent_ = trieNode;
208
209 if (trieNode->children_.size () >= trieNode->bucketSize_)
210 {
211 trieNode->bucketSize_ += trieNode->bucketIncrement_;
212 buckets_array newBuckets (new bucket_type [trieNode->bucketSize_]);
213 trieNode->children_.rehash (bucket_traits (newBuckets.get (), trieNode->bucketSize_));
214 trieNode->buckets_.swap (newBuckets);
215 }
216
217 std::pair< typename unordered_set::iterator, bool > ret =
218 trieNode->children_.insert (*newNode);
219
220 trieNode = &(*ret.first);
221 }
222 else
223 trieNode = &(*item);
224 }
225
226 if (trieNode->payload_ == PayloadTraits::empty_payload)
227 {
228 trieNode->payload_ = payload;
229 return std::make_pair (trieNode, true);
230 }
231 else
232 return std::make_pair (trieNode, false);
233 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700234
235 /**
236 * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
237 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700238 inline iterator
239 erase ()
240 {
241 payload_ = PayloadTraits::empty_payload;
242 return prune ();
243 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700244
245 /**
246 * @brief Do exactly as erase, but without erasing the payload
247 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700248 inline iterator
249 prune ()
250 {
251 if (payload_ == PayloadTraits::empty_payload &&
252 children_.size () == 0)
253 {
254 if (parent_ == 0) return this;
255
256 trie *parent = parent_;
257 parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
258
259 return parent->prune ();
260 }
261 return this;
262 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700263
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700264 // inline boost::tuple<const iterator, bool, const iterator>
265 // find (const FullKey &key) const
266 // {
267 // return const_cast<trie*> (this)->find (key);
268 // }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700269
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700270 /**
271 * @brief Perform the longest prefix match
272 * @param key the key for which to perform the longest prefix match
273 *
274 * @return ->second is true if prefix in ->first is longer than key
275 */
276 inline boost::tuple<iterator, bool, iterator>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700277 find (const FullKey &key)
278 {
279 trie *trieNode = this;
280 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
281 bool reachLast = true;
282
283 BOOST_FOREACH (const Key &subkey, key)
284 {
285 typename unordered_set::iterator item = trieNode->children_.find (subkey);
286 if (item == trieNode->children_.end ())
287 {
288 reachLast = false;
289 break;
290 }
291 else
292 {
293 trieNode = &(*item);
294
295 if (trieNode->payload_ != PayloadTraits::empty_payload)
296 foundNode = trieNode;
297 }
298 }
299
300 return boost::make_tuple (foundNode, reachLast, trieNode);
301 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700302
303 /**
304 * @brief Find next payload of the sub-trie
305 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
306 */
307 inline iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700308 find ()
309 {
310 if (payload_ != PayloadTraits::empty_payload)
311 return this;
312
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700313 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700314 for (typename trie::unordered_set::iterator subnode = children_.begin ();
315 subnode != children_.end ();
316 subnode++ )
317 // BOOST_FOREACH (trie &subnode, children_)
318 {
319 iterator value = subnode->find ();
320 if (value != 0)
321 return value;
322 }
323
324 return 0;
325 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700326
327 /**
328 * @brief Find next payload of the sub-trie satisfying the predicate
329 * @param pred predicate
330 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
331 */
332 template<class Predicate>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700333 inline const iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700334 find_if (Predicate pred)
335 {
336 if (payload_ != PayloadTraits::empty_payload && pred (payload_))
337 return this;
338
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700339 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700340 for (typename trie::unordered_set::iterator subnode = children_.begin ();
341 subnode != children_.end ();
342 subnode++ )
343 // BOOST_FOREACH (const trie &subnode, children_)
344 {
345 iterator value = subnode->find ();
346 if (value != 0)
347 return value;
348 }
349
350 return 0;
351 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700352
353 iterator end ()
354 {
355 return 0;
356 }
357
358 const_iterator end () const
359 {
360 return 0;
361 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700362
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700363 typename PayloadTraits::const_return_type
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700364 payload () const
365 {
366 return payload_;
367 }
368
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700369 typename PayloadTraits::return_type
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700370 payload ()
371 {
372 return payload_;
373 }
374
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700375 void
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700376 set_payload (typename PayloadTraits::insert_type payload)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700377 {
378 payload_ = payload;
379 }
Alexander Afanasyev0560eec2012-07-16 15:44:31 -0700380
381 Key key () const
382 {
383 return key_;
384 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700385
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700386 inline void
387 PrintStat (std::ostream &os) const;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700388
389private:
390 //The disposer object function
391 struct trie_delete_disposer
392 {
393 void operator() (trie *delete_this)
394 {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700395 delete delete_this;
396 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700397 };
398
399 template<class D>
400 struct array_disposer
401 {
402 void operator() (D *array)
403 {
404 delete [] array;
405 }
406 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700407
408 friend
409 std::ostream&
410 operator<< < > (std::ostream &os, const trie &trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700411
412public:
413 PolicyHook policy_hook_;
414
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700415private:
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700416 boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700417
418 // necessary typedefs
419 typedef trie self_type;
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700420 typedef boost::intrusive::member_hook< trie,
421 boost::intrusive::unordered_set_member_hook< >,
422 &trie::unordered_set_member_hook_ > member_hook;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700423
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700424 typedef boost::intrusive::unordered_set< trie, member_hook > unordered_set;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700425 typedef typename unordered_set::bucket_type bucket_type;
426 typedef typename unordered_set::bucket_traits bucket_traits;
427
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700428 template<class T>
429 friend class trie_iterator;
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700430
431 template<class T>
432 friend class trie_point_iterator;
433
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700434 ////////////////////////////////////////////////
435 // Actual data
436 ////////////////////////////////////////////////
437
438 Key key_; ///< name component
439
440 size_t initialBucketSize_;
441 size_t bucketIncrement_;
442
443 size_t bucketSize_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700444 typedef boost::interprocess::unique_ptr< bucket_type, array_disposer<bucket_type> > buckets_array;
445 buckets_array buckets_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700446 unordered_set children_;
447
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700448 typename PayloadTraits::storage_type payload_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700449 trie *parent_; // to make cleaning effective
450};
451
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700452
453
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700454
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700455template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700456inline std::ostream&
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700457operator << (std::ostream &os, const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700458{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700459 os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << std::endl;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700460 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700461
462 for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin ();
463 subnode != trie_node.children_.end ();
464 subnode++ )
465 // BOOST_FOREACH (const trie &subnode, trie_node.children_)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700466 {
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700467 os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]\n";
468 os << "\"" << &(*subnode) << "\"" << " [label=\"" << subnode->key_ << ((subnode->payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]""\n";
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700469
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700470 os << "\"" << &trie_node << "\"" << " -> " << "\"" << &(*subnode) << "\"" << "\n";
471 os << *subnode;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700472 }
473
474 return os;
475}
476
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700477template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700478inline void
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700479trie<FullKey, PayloadTraits, PolicyHook>
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700480::PrintStat (std::ostream &os) const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700481{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700482 os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload)?"*":"") << ": " << children_.size() << " children" << std::endl;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700483 for (size_t bucket = 0, maxbucket = children_.bucket_count ();
484 bucket < maxbucket;
485 bucket++)
486 {
487 os << " " << children_.bucket_size (bucket);
488 }
489 os << "\n";
490
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700491 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700492 for (typename trie::unordered_set::const_iterator subnode = children_.begin ();
493 subnode != children_.end ();
494 subnode++ )
495 // BOOST_FOREACH (const trie &subnode, children_)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700496 {
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700497 subnode->PrintStat (os);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700498 }
499}
500
501
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700502template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700503inline bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700504operator == (const trie<FullKey, PayloadTraits, PolicyHook> &a,
505 const trie<FullKey, PayloadTraits, PolicyHook> &b)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700506{
507 return a.key_ == b.key_;
508}
509
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700510template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700511inline std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700512hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700513{
514 return boost::hash_value (trie_node.key_);
515}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700516
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700517
518
519template<class Trie>
520class trie_iterator
521{
522public:
523 trie_iterator () : trie_ (0) {}
524 trie_iterator (typename Trie::iterator item) : trie_ (item) {}
525 trie_iterator (Trie &item) : trie_ (&item) {}
526
527 Trie & operator* () { return *trie_; }
528 const Trie & operator* () const { return *trie_; }
529 Trie * operator-> () { return trie_; }
530 const Trie * operator-> () const { return trie_; }
531 bool operator== (trie_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
532 bool operator== (trie_iterator<Trie> &other) { return (trie_ == other.trie_); }
533 bool operator!= (trie_iterator<const Trie> &other) const { return !(*this == other); }
534 bool operator!= (trie_iterator<Trie> &other) { return !(*this == other); }
535
536 trie_iterator<Trie> &
537 operator++ (int)
538 {
539 if (trie_->children_.size () > 0)
540 trie_ = &(*trie_->children_.begin ());
541 else
542 trie_ = goUp ();
543 return *this;
544 }
545
546 trie_iterator<Trie> &
547 operator++ ()
548 {
549 (*this)++;
550 return *this;
551 }
552
553private:
554 typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
555 typename Trie::unordered_set::const_iterator,
556 typename Trie::unordered_set::iterator>::type set_iterator;
557
558 Trie* goUp ()
559 {
560 if (trie_->parent_ != 0)
561 {
562 // typename Trie::unordered_set::iterator item =
563 set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
564 item++;
565 if (item != trie_->parent_->children_.end ())
566 {
567 return &(*item);
568 }
569 else
570 {
571 trie_ = trie_->parent_;
572 return goUp ();
573 }
574 }
575 else
576 return 0;
577 }
578private:
579 Trie *trie_;
580};
581
582
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700583template<class Trie>
584class trie_point_iterator
585{
586private:
587 typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
588 typename Trie::unordered_set::const_iterator,
589 typename Trie::unordered_set::iterator>::type set_iterator;
590
591public:
592 trie_point_iterator () : trie_ (0) {}
593 trie_point_iterator (typename Trie::iterator item) : trie_ (item) {}
594 trie_point_iterator (Trie &item)
595 {
596 if (item.children_.size () != 0)
597 trie_ = &*item.children_.begin ();
598 else
599 trie_ = 0;
600 }
601
602 Trie & operator* () { return *trie_; }
603 const Trie & operator* () const { return *trie_; }
604 Trie * operator-> () { return trie_; }
605 const Trie * operator-> () const { return trie_; }
606 bool operator== (trie_point_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
607 bool operator== (trie_point_iterator<Trie> &other) { return (trie_ == other.trie_); }
608 bool operator!= (trie_point_iterator<const Trie> &other) const { return !(*this == other); }
609 bool operator!= (trie_point_iterator<Trie> &other) { return !(*this == other); }
610
611 trie_point_iterator<Trie> &
612 operator++ (int)
613 {
614 if (trie_->parent_ != 0)
615 {
616 set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
617 item ++;
618 if (item == trie_->parent_->children_.end ())
619 trie_ = 0;
620 else
621 trie_ = &*item;
622 }
623 else
624 {
625 trie_ = 0;
626 }
627 return *this;
628 }
629
630 trie_point_iterator<Trie> &
631 operator++ ()
632 {
633 (*this)++;
634 return *this;
635 }
636
637private:
638 Trie *trie_;
639};
640
641
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700642} // ndnSIM
643
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700644#endif // TRIE_H_