blob: 51a76785566f98dcaf567a19a748aa144cfc6866 [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 Afanasyevfd0c41c2012-06-11 22:15:49 -0700380
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700381 inline void
382 PrintStat (std::ostream &os) const;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700383
384private:
385 //The disposer object function
386 struct trie_delete_disposer
387 {
388 void operator() (trie *delete_this)
389 {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700390 delete delete_this;
391 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700392 };
393
394 template<class D>
395 struct array_disposer
396 {
397 void operator() (D *array)
398 {
399 delete [] array;
400 }
401 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700402
403 friend
404 std::ostream&
405 operator<< < > (std::ostream &os, const trie &trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700406
407public:
408 PolicyHook policy_hook_;
409
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700410private:
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700411 boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700412
413 // necessary typedefs
414 typedef trie self_type;
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700415 typedef boost::intrusive::member_hook< trie,
416 boost::intrusive::unordered_set_member_hook< >,
417 &trie::unordered_set_member_hook_ > member_hook;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700418
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700419 typedef boost::intrusive::unordered_set< trie, member_hook > unordered_set;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700420 typedef typename unordered_set::bucket_type bucket_type;
421 typedef typename unordered_set::bucket_traits bucket_traits;
422
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700423 template<class T>
424 friend class trie_iterator;
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700425
426 template<class T>
427 friend class trie_point_iterator;
428
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700429 ////////////////////////////////////////////////
430 // Actual data
431 ////////////////////////////////////////////////
432
433 Key key_; ///< name component
434
435 size_t initialBucketSize_;
436 size_t bucketIncrement_;
437
438 size_t bucketSize_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700439 typedef boost::interprocess::unique_ptr< bucket_type, array_disposer<bucket_type> > buckets_array;
440 buckets_array buckets_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700441 unordered_set children_;
442
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700443 typename PayloadTraits::storage_type payload_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700444 trie *parent_; // to make cleaning effective
445};
446
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700447
448
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700449
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700450template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700451inline std::ostream&
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700452operator << (std::ostream &os, const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700453{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700454 os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << std::endl;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700455 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700456
457 for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin ();
458 subnode != trie_node.children_.end ();
459 subnode++ )
460 // BOOST_FOREACH (const trie &subnode, trie_node.children_)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700461 {
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700462 os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]\n";
463 os << "\"" << &(*subnode) << "\"" << " [label=\"" << subnode->key_ << ((subnode->payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]""\n";
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700464
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700465 os << "\"" << &trie_node << "\"" << " -> " << "\"" << &(*subnode) << "\"" << "\n";
466 os << *subnode;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700467 }
468
469 return os;
470}
471
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700472template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700473inline void
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700474trie<FullKey, PayloadTraits, PolicyHook>
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700475::PrintStat (std::ostream &os) const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700476{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700477 os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload)?"*":"") << ": " << children_.size() << " children" << std::endl;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700478 for (size_t bucket = 0, maxbucket = children_.bucket_count ();
479 bucket < maxbucket;
480 bucket++)
481 {
482 os << " " << children_.bucket_size (bucket);
483 }
484 os << "\n";
485
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700486 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700487 for (typename trie::unordered_set::const_iterator subnode = children_.begin ();
488 subnode != children_.end ();
489 subnode++ )
490 // BOOST_FOREACH (const trie &subnode, children_)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700491 {
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700492 subnode->PrintStat (os);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700493 }
494}
495
496
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700497template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700498inline bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700499operator == (const trie<FullKey, PayloadTraits, PolicyHook> &a,
500 const trie<FullKey, PayloadTraits, PolicyHook> &b)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700501{
502 return a.key_ == b.key_;
503}
504
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700505template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700506inline std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700507hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700508{
509 return boost::hash_value (trie_node.key_);
510}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700511
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700512
513
514template<class Trie>
515class trie_iterator
516{
517public:
518 trie_iterator () : trie_ (0) {}
519 trie_iterator (typename Trie::iterator item) : trie_ (item) {}
520 trie_iterator (Trie &item) : trie_ (&item) {}
521
522 Trie & operator* () { return *trie_; }
523 const Trie & operator* () const { return *trie_; }
524 Trie * operator-> () { return trie_; }
525 const Trie * operator-> () const { return trie_; }
526 bool operator== (trie_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
527 bool operator== (trie_iterator<Trie> &other) { return (trie_ == other.trie_); }
528 bool operator!= (trie_iterator<const Trie> &other) const { return !(*this == other); }
529 bool operator!= (trie_iterator<Trie> &other) { return !(*this == other); }
530
531 trie_iterator<Trie> &
532 operator++ (int)
533 {
534 if (trie_->children_.size () > 0)
535 trie_ = &(*trie_->children_.begin ());
536 else
537 trie_ = goUp ();
538 return *this;
539 }
540
541 trie_iterator<Trie> &
542 operator++ ()
543 {
544 (*this)++;
545 return *this;
546 }
547
548private:
549 typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
550 typename Trie::unordered_set::const_iterator,
551 typename Trie::unordered_set::iterator>::type set_iterator;
552
553 Trie* goUp ()
554 {
555 if (trie_->parent_ != 0)
556 {
557 // typename Trie::unordered_set::iterator item =
558 set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
559 item++;
560 if (item != trie_->parent_->children_.end ())
561 {
562 return &(*item);
563 }
564 else
565 {
566 trie_ = trie_->parent_;
567 return goUp ();
568 }
569 }
570 else
571 return 0;
572 }
573private:
574 Trie *trie_;
575};
576
577
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700578template<class Trie>
579class trie_point_iterator
580{
581private:
582 typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
583 typename Trie::unordered_set::const_iterator,
584 typename Trie::unordered_set::iterator>::type set_iterator;
585
586public:
587 trie_point_iterator () : trie_ (0) {}
588 trie_point_iterator (typename Trie::iterator item) : trie_ (item) {}
589 trie_point_iterator (Trie &item)
590 {
591 if (item.children_.size () != 0)
592 trie_ = &*item.children_.begin ();
593 else
594 trie_ = 0;
595 }
596
597 Trie & operator* () { return *trie_; }
598 const Trie & operator* () const { return *trie_; }
599 Trie * operator-> () { return trie_; }
600 const Trie * operator-> () const { return trie_; }
601 bool operator== (trie_point_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
602 bool operator== (trie_point_iterator<Trie> &other) { return (trie_ == other.trie_); }
603 bool operator!= (trie_point_iterator<const Trie> &other) const { return !(*this == other); }
604 bool operator!= (trie_point_iterator<Trie> &other) { return !(*this == other); }
605
606 trie_point_iterator<Trie> &
607 operator++ (int)
608 {
609 if (trie_->parent_ != 0)
610 {
611 set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
612 item ++;
613 if (item == trie_->parent_->children_.end ())
614 trie_ = 0;
615 else
616 trie_ = &*item;
617 }
618 else
619 {
620 trie_ = 0;
621 }
622 return *this;
623 }
624
625 trie_point_iterator<Trie> &
626 operator++ ()
627 {
628 (*this)++;
629 return *this;
630 }
631
632private:
633 Trie *trie_;
634};
635
636
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700637} // ndnSIM
638
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700639#endif // TRIE_H_