blob: 50288af020e75d17059c876a3acaf6242f076fbc [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,
Alexander Afanasyev9a989702012-06-29 17:44:00 -070074 typename PayloadTraits,
75 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070076class trie;
77
Alexander Afanasyev30f60e32012-07-10 14:21:16 -070078template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070079inline std::ostream&
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070080operator << (std::ostream &os,
Alexander Afanasyev30f60e32012-07-10 14:21:16 -070081 const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070082
Alexander Afanasyev30f60e32012-07-10 14:21:16 -070083template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070084bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -070085operator== (const trie<FullKey, PayloadTraits, PolicyHook> &a,
86 const trie<FullKey, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070087
Alexander Afanasyev30f60e32012-07-10 14:21:16 -070088template<typename FullKey, typename PayloadTraits, typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070089std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -070090hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070091
92///////////////////////////////////////////////////
93// actual definition
94//
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -070095template<class T>
96class trie_iterator;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070097
98template<typename FullKey,
Alexander Afanasyev30f60e32012-07-10 14:21:16 -070099 typename PayloadTraits,
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700100 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700101class trie
102{
103public:
104 typedef typename FullKey::partial_type Key;
105
106 typedef trie* iterator;
107 typedef const trie* const_iterator;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700108
109 typedef trie_iterator<trie> recursive_iterator;
110 typedef trie_iterator<const trie> const_recursive_iterator;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700111
112 typedef PayloadTraits payload_traits;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700113
114 inline
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700115 trie (const Key &key, size_t bucketSize = 10, size_t bucketIncrement = 10)
116 : key_ (key)
117 , initialBucketSize_ (bucketSize)
118 , bucketIncrement_ (bucketIncrement)
119 , bucketSize_ (initialBucketSize_)
120 , buckets_ (new bucket_type [bucketSize_]) //cannot use normal pointer, because lifetime of buckets should be larger than lifetime of the container
121 , children_ (bucket_traits (buckets_.get (), bucketSize_))
122 , payload_ (PayloadTraits::empty_payload)
123 , parent_ (0)
124 {
125 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700126
127 inline
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700128 ~trie ()
129 {
130 payload_ = PayloadTraits::empty_payload; // necessary for smart pointers...
131 children_.clear_and_dispose (trie_delete_disposer ());
132 }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700133
134 void
135 clear ()
136 {
137 children_.clear_and_dispose (trie_delete_disposer ());
138 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700139
140 template<class Predicate>
141 void
142 clear_if (Predicate cond)
143 {
144 recursive_iterator trieNode (this);
145 recursive_iterator end (0);
146
147 while (trieNode != end)
148 {
149 if (cond (*trieNode))
150 {
151 trieNode = recursive_iterator (trieNode->erase ());
152 }
153 trieNode ++;
154 }
155 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700156
157 // actual entry
158 friend bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700159 operator== <> (const trie<FullKey, PayloadTraits, PolicyHook> &a,
160 const trie<FullKey, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700161
162 friend std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700163 hash_value <> (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700164
165 inline std::pair<iterator, bool>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700166 insert (const FullKey &key,
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700167 typename PayloadTraits::pointer_type payload)
168 {
169 trie *trieNode = this;
170
171 BOOST_FOREACH (const Key &subkey, key)
172 {
173 typename unordered_set::iterator item = trieNode->children_.find (subkey);
174 if (item == trieNode->children_.end ())
175 {
176 trie *newNode = new trie (subkey, initialBucketSize_, bucketIncrement_);
177 // std::cout << "new " << newNode << "\n";
178 newNode->parent_ = trieNode;
179
180 if (trieNode->children_.size () >= trieNode->bucketSize_)
181 {
182 trieNode->bucketSize_ += trieNode->bucketIncrement_;
183 buckets_array newBuckets (new bucket_type [trieNode->bucketSize_]);
184 trieNode->children_.rehash (bucket_traits (newBuckets.get (), trieNode->bucketSize_));
185 trieNode->buckets_.swap (newBuckets);
186 }
187
188 std::pair< typename unordered_set::iterator, bool > ret =
189 trieNode->children_.insert (*newNode);
190
191 trieNode = &(*ret.first);
192 }
193 else
194 trieNode = &(*item);
195 }
196
197 if (trieNode->payload_ == PayloadTraits::empty_payload)
198 {
199 trieNode->payload_ = payload;
200 return std::make_pair (trieNode, true);
201 }
202 else
203 return std::make_pair (trieNode, false);
204 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700205
206 /**
207 * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
208 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700209 inline iterator
210 erase ()
211 {
212 payload_ = PayloadTraits::empty_payload;
213 return prune ();
214 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700215
216 /**
217 * @brief Do exactly as erase, but without erasing the payload
218 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700219 inline iterator
220 prune ()
221 {
222 if (payload_ == PayloadTraits::empty_payload &&
223 children_.size () == 0)
224 {
225 if (parent_ == 0) return this;
226
227 trie *parent = parent_;
228 parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
229
230 return parent->prune ();
231 }
232 return this;
233 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700234
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700235 // inline boost::tuple<const iterator, bool, const iterator>
236 // find (const FullKey &key) const
237 // {
238 // return const_cast<trie*> (this)->find (key);
239 // }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700240
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700241 /**
242 * @brief Perform the longest prefix match
243 * @param key the key for which to perform the longest prefix match
244 *
245 * @return ->second is true if prefix in ->first is longer than key
246 */
247 inline boost::tuple<iterator, bool, iterator>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700248 find (const FullKey &key)
249 {
250 trie *trieNode = this;
251 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
252 bool reachLast = true;
253
254 BOOST_FOREACH (const Key &subkey, key)
255 {
256 typename unordered_set::iterator item = trieNode->children_.find (subkey);
257 if (item == trieNode->children_.end ())
258 {
259 reachLast = false;
260 break;
261 }
262 else
263 {
264 trieNode = &(*item);
265
266 if (trieNode->payload_ != PayloadTraits::empty_payload)
267 foundNode = trieNode;
268 }
269 }
270
271 return boost::make_tuple (foundNode, reachLast, trieNode);
272 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700273
274 /**
275 * @brief Find next payload of the sub-trie
276 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
277 */
278 inline iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700279 find ()
280 {
281 if (payload_ != PayloadTraits::empty_payload)
282 return this;
283
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700284 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700285 for (typename trie::unordered_set::iterator subnode = children_.begin ();
286 subnode != children_.end ();
287 subnode++ )
288 // BOOST_FOREACH (trie &subnode, children_)
289 {
290 iterator value = subnode->find ();
291 if (value != 0)
292 return value;
293 }
294
295 return 0;
296 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700297
298 /**
299 * @brief Find next payload of the sub-trie satisfying the predicate
300 * @param pred predicate
301 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
302 */
303 template<class Predicate>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700304 inline const iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700305 find_if (Predicate pred)
306 {
307 if (payload_ != PayloadTraits::empty_payload && pred (payload_))
308 return this;
309
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700310 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700311 for (typename trie::unordered_set::iterator subnode = children_.begin ();
312 subnode != children_.end ();
313 subnode++ )
314 // BOOST_FOREACH (const trie &subnode, children_)
315 {
316 iterator value = subnode->find ();
317 if (value != 0)
318 return value;
319 }
320
321 return 0;
322 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700323
324 iterator end ()
325 {
326 return 0;
327 }
328
329 const_iterator end () const
330 {
331 return 0;
332 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700333
334 typename PayloadTraits::const_pointer_type
335 payload () const
336 {
337 return payload_;
338 }
339
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700340 typename PayloadTraits::pointer_type
341 payload ()
342 {
343 return payload_;
344 }
345
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700346 void
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700347 set_payload (typename PayloadTraits::pointer_type payload)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700348 {
349 payload_ = payload;
350 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700351
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700352 inline void
353 PrintStat (std::ostream &os) const;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700354
355private:
356 //The disposer object function
357 struct trie_delete_disposer
358 {
359 void operator() (trie *delete_this)
360 {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700361 delete delete_this;
362 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700363 };
364
365 template<class D>
366 struct array_disposer
367 {
368 void operator() (D *array)
369 {
370 delete [] array;
371 }
372 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700373
374 friend
375 std::ostream&
376 operator<< < > (std::ostream &os, const trie &trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700377
378public:
379 PolicyHook policy_hook_;
380
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700381private:
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700382 boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700383
384 // necessary typedefs
385 typedef trie self_type;
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700386 typedef boost::intrusive::member_hook< trie,
387 boost::intrusive::unordered_set_member_hook< >,
388 &trie::unordered_set_member_hook_ > member_hook;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700389
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700390 typedef boost::intrusive::unordered_set< trie, member_hook > unordered_set;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700391 typedef typename unordered_set::bucket_type bucket_type;
392 typedef typename unordered_set::bucket_traits bucket_traits;
393
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700394 template<class T>
395 friend class trie_iterator;
396
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700397 ////////////////////////////////////////////////
398 // Actual data
399 ////////////////////////////////////////////////
400
401 Key key_; ///< name component
402
403 size_t initialBucketSize_;
404 size_t bucketIncrement_;
405
406 size_t bucketSize_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700407 typedef boost::interprocess::unique_ptr< bucket_type, array_disposer<bucket_type> > buckets_array;
408 buckets_array buckets_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700409 unordered_set children_;
410
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700411 typename PayloadTraits::pointer_type payload_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700412 trie *parent_; // to make cleaning effective
413};
414
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700415
416
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700417
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700418template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700419inline std::ostream&
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700420operator << (std::ostream &os, const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700421{
422 os << "# " << trie_node.key_ << ((trie_node.payload_ != 0)?"*":"") << std::endl;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700423 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700424
425 for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin ();
426 subnode != trie_node.children_.end ();
427 subnode++ )
428 // BOOST_FOREACH (const trie &subnode, trie_node.children_)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700429 {
430 os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != 0)?"*":"") << "\"]\n";
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700431 os << "\"" << &(*subnode) << "\"" << " [label=\"" << subnode->key_ << ((subnode->payload_ != 0)?"*":"") << "\"]""\n";
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700432
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700433 os << "\"" << &trie_node << "\"" << " -> " << "\"" << &(*subnode) << "\"" << "\n";
434 os << *subnode;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700435 }
436
437 return os;
438}
439
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700440template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700441inline void
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700442trie<FullKey, PayloadTraits, PolicyHook>
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700443::PrintStat (std::ostream &os) const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700444{
445 os << "# " << key_ << ((payload_ != 0)?"*":"") << ": " << children_.size() << " children" << std::endl;
446 for (size_t bucket = 0, maxbucket = children_.bucket_count ();
447 bucket < maxbucket;
448 bucket++)
449 {
450 os << " " << children_.bucket_size (bucket);
451 }
452 os << "\n";
453
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700454 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700455 for (typename trie::unordered_set::const_iterator subnode = children_.begin ();
456 subnode != children_.end ();
457 subnode++ )
458 // BOOST_FOREACH (const trie &subnode, children_)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700459 {
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700460 subnode->PrintStat (os);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700461 }
462}
463
464
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700465template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700466inline bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700467operator == (const trie<FullKey, PayloadTraits, PolicyHook> &a,
468 const trie<FullKey, PayloadTraits, PolicyHook> &b)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700469{
470 return a.key_ == b.key_;
471}
472
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700473template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700474inline std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700475hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700476{
477 return boost::hash_value (trie_node.key_);
478}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700479
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700480
481
482template<class Trie>
483class trie_iterator
484{
485public:
486 trie_iterator () : trie_ (0) {}
487 trie_iterator (typename Trie::iterator item) : trie_ (item) {}
488 trie_iterator (Trie &item) : trie_ (&item) {}
489
490 Trie & operator* () { return *trie_; }
491 const Trie & operator* () const { return *trie_; }
492 Trie * operator-> () { return trie_; }
493 const Trie * operator-> () const { return trie_; }
494 bool operator== (trie_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
495 bool operator== (trie_iterator<Trie> &other) { return (trie_ == other.trie_); }
496 bool operator!= (trie_iterator<const Trie> &other) const { return !(*this == other); }
497 bool operator!= (trie_iterator<Trie> &other) { return !(*this == other); }
498
499 trie_iterator<Trie> &
500 operator++ (int)
501 {
502 if (trie_->children_.size () > 0)
503 trie_ = &(*trie_->children_.begin ());
504 else
505 trie_ = goUp ();
506 return *this;
507 }
508
509 trie_iterator<Trie> &
510 operator++ ()
511 {
512 (*this)++;
513 return *this;
514 }
515
516private:
517 typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
518 typename Trie::unordered_set::const_iterator,
519 typename Trie::unordered_set::iterator>::type set_iterator;
520
521 Trie* goUp ()
522 {
523 if (trie_->parent_ != 0)
524 {
525 // typename Trie::unordered_set::iterator item =
526 set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
527 item++;
528 if (item != trie_->parent_->children_.end ())
529 {
530 return &(*item);
531 }
532 else
533 {
534 trie_ = trie_->parent_;
535 return goUp ();
536 }
537 }
538 else
539 return 0;
540 }
541private:
542 Trie *trie_;
543};
544
545
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700546} // ndnSIM
547
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700548#endif // TRIE_H_