blob: 1b2056e50bd49a9b2c0f105278348e83f342308a [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 Afanasyev9e96e362012-07-02 23:04:39 -070044 typedef Payload payload_type;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070045 typedef Payload* pointer_type;
46 typedef const Payload* const_pointer_type;
47
Alexander Afanasyev78057c32012-07-06 15:18:46 -070048 static Payload* empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070049};
50
51template<typename Payload>
Alexander Afanasyev78057c32012-07-06 15:18:46 -070052Payload*
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070053pointer_payload_traits<Payload>::empty_payload = 0;
54
55template<typename Payload>
56struct smart_pointer_payload_traits
57{
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070058 typedef Payload payload_type;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070059 typedef ns3::Ptr<Payload> pointer_type;
60 typedef ns3::Ptr<const Payload> const_pointer_type;
61
Alexander Afanasyev78057c32012-07-06 15:18:46 -070062 static ns3::Ptr<Payload> empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070063};
64
65template<typename Payload>
Alexander Afanasyev78057c32012-07-06 15:18:46 -070066ns3::Ptr<Payload>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070067smart_pointer_payload_traits<Payload>::empty_payload = 0;
68
69
70////////////////////////////////////////////////////
71// forward declarations
72//
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070073template<typename FullKey,
74 typename Payload,
Alexander Afanasyev9a989702012-06-29 17:44:00 -070075 typename PayloadTraits,
76 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070077class trie;
78
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070079template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070080inline std::ostream&
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070081operator << (std::ostream &os,
82 const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070083
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070084template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070085bool
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070086operator== (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &a,
87 const trie<FullKey, Payload, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070088
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070089template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070090std::size_t
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070091hash_value (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070092
93///////////////////////////////////////////////////
94// actual definition
95//
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -070096template<class T>
97class trie_iterator;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070098
99template<typename FullKey,
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700100 typename Payload, typename PayloadTraits,
101 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700102class trie
103{
104public:
105 typedef typename FullKey::partial_type Key;
106
107 typedef trie* iterator;
108 typedef const trie* const_iterator;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700109
110 typedef trie_iterator<trie> recursive_iterator;
111 typedef trie_iterator<const trie> const_recursive_iterator;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700112
113 inline
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700114 trie (const Key &key, size_t bucketSize = 10, size_t bucketIncrement = 10)
115 : key_ (key)
116 , initialBucketSize_ (bucketSize)
117 , bucketIncrement_ (bucketIncrement)
118 , bucketSize_ (initialBucketSize_)
119 , buckets_ (new bucket_type [bucketSize_]) //cannot use normal pointer, because lifetime of buckets should be larger than lifetime of the container
120 , children_ (bucket_traits (buckets_.get (), bucketSize_))
121 , payload_ (PayloadTraits::empty_payload)
122 , parent_ (0)
123 {
124 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700125
126 inline
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700127 ~trie ()
128 {
129 payload_ = PayloadTraits::empty_payload; // necessary for smart pointers...
130 children_.clear_and_dispose (trie_delete_disposer ());
131 }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700132
133 void
134 clear ()
135 {
136 children_.clear_and_dispose (trie_delete_disposer ());
137 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700138
139 template<class Predicate>
140 void
141 clear_if (Predicate cond)
142 {
143 recursive_iterator trieNode (this);
144 recursive_iterator end (0);
145
146 while (trieNode != end)
147 {
148 if (cond (*trieNode))
149 {
150 trieNode = recursive_iterator (trieNode->erase ());
151 }
152 trieNode ++;
153 }
154 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700155
156 // actual entry
157 friend bool
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700158 operator== <> (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &a,
159 const trie<FullKey, Payload, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700160
161 friend std::size_t
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700162 hash_value <> (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700163
164 inline std::pair<iterator, bool>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700165 insert (const FullKey &key,
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700166 typename PayloadTraits::pointer_type payload)
167 {
168 trie *trieNode = this;
169
170 BOOST_FOREACH (const Key &subkey, key)
171 {
172 typename unordered_set::iterator item = trieNode->children_.find (subkey);
173 if (item == trieNode->children_.end ())
174 {
175 trie *newNode = new trie (subkey, initialBucketSize_, bucketIncrement_);
176 // std::cout << "new " << newNode << "\n";
177 newNode->parent_ = trieNode;
178
179 if (trieNode->children_.size () >= trieNode->bucketSize_)
180 {
181 trieNode->bucketSize_ += trieNode->bucketIncrement_;
182 buckets_array newBuckets (new bucket_type [trieNode->bucketSize_]);
183 trieNode->children_.rehash (bucket_traits (newBuckets.get (), trieNode->bucketSize_));
184 trieNode->buckets_.swap (newBuckets);
185 }
186
187 std::pair< typename unordered_set::iterator, bool > ret =
188 trieNode->children_.insert (*newNode);
189
190 trieNode = &(*ret.first);
191 }
192 else
193 trieNode = &(*item);
194 }
195
196 if (trieNode->payload_ == PayloadTraits::empty_payload)
197 {
198 trieNode->payload_ = payload;
199 return std::make_pair (trieNode, true);
200 }
201 else
202 return std::make_pair (trieNode, false);
203 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700204
205 /**
206 * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
207 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700208 inline iterator
209 erase ()
210 {
211 payload_ = PayloadTraits::empty_payload;
212 return prune ();
213 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700214
215 /**
216 * @brief Do exactly as erase, but without erasing the payload
217 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700218 inline iterator
219 prune ()
220 {
221 if (payload_ == PayloadTraits::empty_payload &&
222 children_.size () == 0)
223 {
224 if (parent_ == 0) return this;
225
226 trie *parent = parent_;
227 parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
228
229 return parent->prune ();
230 }
231 return this;
232 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700233
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700234 inline boost::tuple<const iterator, bool, const iterator>
235 find (const FullKey &key) const
236 {
237 return const_cast<trie*> (this)->find (key);
238 }
239
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700240 /**
241 * @brief Perform the longest prefix match
242 * @param key the key for which to perform the longest prefix match
243 *
244 * @return ->second is true if prefix in ->first is longer than key
245 */
246 inline boost::tuple<iterator, bool, iterator>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700247 find (const FullKey &key)
248 {
249 trie *trieNode = this;
250 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
251 bool reachLast = true;
252
253 BOOST_FOREACH (const Key &subkey, key)
254 {
255 typename unordered_set::iterator item = trieNode->children_.find (subkey);
256 if (item == trieNode->children_.end ())
257 {
258 reachLast = false;
259 break;
260 }
261 else
262 {
263 trieNode = &(*item);
264
265 if (trieNode->payload_ != PayloadTraits::empty_payload)
266 foundNode = trieNode;
267 }
268 }
269
270 return boost::make_tuple (foundNode, reachLast, trieNode);
271 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700272
273 /**
274 * @brief Find next payload of the sub-trie
275 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
276 */
277 inline iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700278 find ()
279 {
280 if (payload_ != PayloadTraits::empty_payload)
281 return this;
282
283 typedef trie<FullKey, Payload, PayloadTraits, PolicyHook> trie;
284 for (typename trie::unordered_set::iterator subnode = children_.begin ();
285 subnode != children_.end ();
286 subnode++ )
287 // BOOST_FOREACH (trie &subnode, children_)
288 {
289 iterator value = subnode->find ();
290 if (value != 0)
291 return value;
292 }
293
294 return 0;
295 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700296
297 /**
298 * @brief Find next payload of the sub-trie satisfying the predicate
299 * @param pred predicate
300 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
301 */
302 template<class Predicate>
303 inline iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700304 find_if (Predicate pred)
305 {
306 if (payload_ != PayloadTraits::empty_payload && pred (payload_))
307 return this;
308
309 typedef trie<FullKey, Payload, PayloadTraits, PolicyHook> trie;
310 for (typename trie::unordered_set::iterator subnode = children_.begin ();
311 subnode != children_.end ();
312 subnode++ )
313 // BOOST_FOREACH (const trie &subnode, children_)
314 {
315 iterator value = subnode->find ();
316 if (value != 0)
317 return value;
318 }
319
320 return 0;
321 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700322
323 iterator end ()
324 {
325 return 0;
326 }
327
328 const_iterator end () const
329 {
330 return 0;
331 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700332
333 typename PayloadTraits::const_pointer_type
334 payload () const
335 {
336 return payload_;
337 }
338
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700339 typename PayloadTraits::pointer_type
340 payload ()
341 {
342 return payload_;
343 }
344
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700345 void
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700346 set_payload (typename PayloadTraits::pointer_type payload)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700347 {
348 payload_ = payload;
349 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700350
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700351 inline void
352 PrintStat (std::ostream &os) const;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700353
354private:
355 //The disposer object function
356 struct trie_delete_disposer
357 {
358 void operator() (trie *delete_this)
359 {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700360 delete delete_this;
361 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700362 };
363
364 template<class D>
365 struct array_disposer
366 {
367 void operator() (D *array)
368 {
369 delete [] array;
370 }
371 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700372
373 friend
374 std::ostream&
375 operator<< < > (std::ostream &os, const trie &trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700376
377public:
378 PolicyHook policy_hook_;
379
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700380private:
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700381 boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700382
383 // necessary typedefs
384 typedef trie self_type;
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700385 typedef boost::intrusive::member_hook< trie,
386 boost::intrusive::unordered_set_member_hook< >,
387 &trie::unordered_set_member_hook_ > member_hook;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700388
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700389 typedef boost::intrusive::unordered_set< trie, member_hook > unordered_set;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700390 typedef typename unordered_set::bucket_type bucket_type;
391 typedef typename unordered_set::bucket_traits bucket_traits;
392
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700393 template<class T>
394 friend class trie_iterator;
395
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700396 ////////////////////////////////////////////////
397 // Actual data
398 ////////////////////////////////////////////////
399
400 Key key_; ///< name component
401
402 size_t initialBucketSize_;
403 size_t bucketIncrement_;
404
405 size_t bucketSize_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700406 typedef boost::interprocess::unique_ptr< bucket_type, array_disposer<bucket_type> > buckets_array;
407 buckets_array buckets_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700408 unordered_set children_;
409
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700410 typename PayloadTraits::pointer_type payload_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700411 trie *parent_; // to make cleaning effective
412};
413
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700414
415
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700416
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700417template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700418inline std::ostream&
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700419operator << (std::ostream &os, const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700420{
421 os << "# " << trie_node.key_ << ((trie_node.payload_ != 0)?"*":"") << std::endl;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700422 typedef trie<FullKey, Payload, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700423
424 for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin ();
425 subnode != trie_node.children_.end ();
426 subnode++ )
427 // BOOST_FOREACH (const trie &subnode, trie_node.children_)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700428 {
429 os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != 0)?"*":"") << "\"]\n";
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700430 os << "\"" << &(*subnode) << "\"" << " [label=\"" << subnode->key_ << ((subnode->payload_ != 0)?"*":"") << "\"]""\n";
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700431
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700432 os << "\"" << &trie_node << "\"" << " -> " << "\"" << &(*subnode) << "\"" << "\n";
433 os << *subnode;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700434 }
435
436 return os;
437}
438
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700439template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
440inline void
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700441trie<FullKey, Payload, PayloadTraits, PolicyHook>
442::PrintStat (std::ostream &os) const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700443{
444 os << "# " << key_ << ((payload_ != 0)?"*":"") << ": " << children_.size() << " children" << std::endl;
445 for (size_t bucket = 0, maxbucket = children_.bucket_count ();
446 bucket < maxbucket;
447 bucket++)
448 {
449 os << " " << children_.bucket_size (bucket);
450 }
451 os << "\n";
452
453 typedef trie<FullKey, Payload, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700454 for (typename trie::unordered_set::const_iterator subnode = children_.begin ();
455 subnode != children_.end ();
456 subnode++ )
457 // BOOST_FOREACH (const trie &subnode, children_)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700458 {
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700459 subnode->PrintStat (os);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700460 }
461}
462
463
464template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700465inline bool
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700466operator == (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &a,
467 const trie<FullKey, Payload, PayloadTraits, PolicyHook> &b)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700468{
469 return a.key_ == b.key_;
470}
471
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700472template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700473inline std::size_t
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700474hash_value (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700475{
476 return boost::hash_value (trie_node.key_);
477}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700478
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700479
480
481template<class Trie>
482class trie_iterator
483{
484public:
485 trie_iterator () : trie_ (0) {}
486 trie_iterator (typename Trie::iterator item) : trie_ (item) {}
487 trie_iterator (Trie &item) : trie_ (&item) {}
488
489 Trie & operator* () { return *trie_; }
490 const Trie & operator* () const { return *trie_; }
491 Trie * operator-> () { return trie_; }
492 const Trie * operator-> () const { return trie_; }
493 bool operator== (trie_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
494 bool operator== (trie_iterator<Trie> &other) { return (trie_ == other.trie_); }
495 bool operator!= (trie_iterator<const Trie> &other) const { return !(*this == other); }
496 bool operator!= (trie_iterator<Trie> &other) { return !(*this == other); }
497
498 trie_iterator<Trie> &
499 operator++ (int)
500 {
501 if (trie_->children_.size () > 0)
502 trie_ = &(*trie_->children_.begin ());
503 else
504 trie_ = goUp ();
505 return *this;
506 }
507
508 trie_iterator<Trie> &
509 operator++ ()
510 {
511 (*this)++;
512 return *this;
513 }
514
515private:
516 typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
517 typename Trie::unordered_set::const_iterator,
518 typename Trie::unordered_set::iterator>::type set_iterator;
519
520 Trie* goUp ()
521 {
522 if (trie_->parent_ != 0)
523 {
524 // typename Trie::unordered_set::iterator item =
525 set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
526 item++;
527 if (item != trie_->parent_->children_.end ())
528 {
529 return &(*item);
530 }
531 else
532 {
533 trie_ = trie_->parent_;
534 return goUp ();
535 }
536 }
537 else
538 return 0;
539 }
540private:
541 Trie *trie_;
542};
543
544
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700545} // ndnSIM
546
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700547#endif // TRIE_H_