blob: b890631f698cd970e72f51cf068e78efc022de33 [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 Afanasyev2b4c9472012-08-09 15:00:38 -070035namespace ns3 {
36namespace ndn {
37namespace ndnSIM {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070038
39/////////////////////////////////////////////////////
40// Allow customization for payload
41//
Alexander Afanasyev8566f452012-12-10 15:21:51 -080042template<typename Payload, typename BasePayload = Payload>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070043struct pointer_payload_traits
44{
Alexander Afanasyev0845c092012-07-13 17:45:33 -070045 typedef Payload payload_type; // general type of the payload
46 typedef Payload* storage_type; // how the payload is actually stored
47 typedef Payload* insert_type; // what parameter is inserted
48
49 typedef Payload* return_type; // what is returned on access
50 typedef const Payload* const_return_type; // what is returned on const access
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070051
Alexander Afanasyev62304f22012-12-10 18:06:21 -080052 typedef BasePayload* base_type; // base type of the entry (when implementation details need to be hidden)
53 typedef const BasePayload* const_base_type; // const base type of the entry (when implementation details need to be hidden)
Alexander Afanasyev8566f452012-12-10 15:21:51 -080054
Alexander Afanasyev78057c32012-07-06 15:18:46 -070055 static Payload* empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070056};
57
Alexander Afanasyev8566f452012-12-10 15:21:51 -080058template<typename Payload, typename BasePayload>
Alexander Afanasyev78057c32012-07-06 15:18:46 -070059Payload*
Alexander Afanasyev8566f452012-12-10 15:21:51 -080060pointer_payload_traits<Payload, BasePayload>::empty_payload = 0;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070061
Alexander Afanasyev8566f452012-12-10 15:21:51 -080062template<typename Payload, typename BasePayload = Payload>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070063struct smart_pointer_payload_traits
64{
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070065 typedef Payload payload_type;
Alexander Afanasyev0845c092012-07-13 17:45:33 -070066 typedef ns3::Ptr<Payload> storage_type;
67 typedef ns3::Ptr<Payload> insert_type;
68
69 typedef ns3::Ptr<Payload> return_type;
70 typedef ns3::Ptr<const Payload> const_return_type;
Alexander Afanasyev8566f452012-12-10 15:21:51 -080071
72 typedef ns3::Ptr<BasePayload> base_type;
73 typedef ns3::Ptr<const BasePayload> const_base_type;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070074
Alexander Afanasyev78057c32012-07-06 15:18:46 -070075 static ns3::Ptr<Payload> empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070076};
77
Alexander Afanasyev8566f452012-12-10 15:21:51 -080078template<typename Payload, typename BasePayload>
Alexander Afanasyev78057c32012-07-06 15:18:46 -070079ns3::Ptr<Payload>
Alexander Afanasyev8566f452012-12-10 15:21:51 -080080smart_pointer_payload_traits<Payload, BasePayload>::empty_payload = 0;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070081
Alexander Afanasyev8566f452012-12-10 15:21:51 -080082template<typename Payload, typename BasePayload = Payload>
Alexander Afanasyev0845c092012-07-13 17:45:33 -070083struct non_pointer_traits
84{
85 typedef Payload payload_type;
86 typedef Payload storage_type;
87 typedef const Payload & insert_type; // nothing to insert
88
89 typedef Payload& return_type;
90 typedef const Payload & const_return_type;
91
Alexander Afanasyev62304f22012-12-10 18:06:21 -080092 typedef BasePayload& base_type;
93 typedef const BasePayload& const_base_type;
Alexander Afanasyev8566f452012-12-10 15:21:51 -080094
Alexander Afanasyev0845c092012-07-13 17:45:33 -070095 static Payload empty_payload;
96};
97
Alexander Afanasyev8566f452012-12-10 15:21:51 -080098template<typename Payload, typename BasePayload>
Alexander Afanasyev0845c092012-07-13 17:45:33 -070099Payload
Alexander Afanasyev8566f452012-12-10 15:21:51 -0800100non_pointer_traits<Payload, BasePayload>::empty_payload = Payload ();
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700101
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700102
103////////////////////////////////////////////////////
104// forward declarations
105//
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700106template<typename FullKey,
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700107 typename PayloadTraits,
108 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700109class trie;
110
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700111template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700112inline std::ostream&
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700113operator << (std::ostream &os,
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700114 const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700115
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700116template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700117bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700118operator== (const trie<FullKey, PayloadTraits, PolicyHook> &a,
119 const trie<FullKey, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700120
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700121template<typename FullKey, typename PayloadTraits, typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700122std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700123hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700124
125///////////////////////////////////////////////////
126// actual definition
127//
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700128template<class T, class NonConstT>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700129class trie_iterator;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700130
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700131template<class T>
132class trie_point_iterator;
133
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700134template<typename FullKey,
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700135 typename PayloadTraits,
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700136 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700137class trie
138{
139public:
140 typedef typename FullKey::partial_type Key;
141
142 typedef trie* iterator;
143 typedef const trie* const_iterator;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700144
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700145 typedef trie_iterator<trie, trie> recursive_iterator;
146 typedef trie_iterator<const trie, trie> const_recursive_iterator;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700147
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700148 typedef trie_point_iterator<trie> point_iterator;
149 typedef trie_point_iterator<const trie> const_point_iterator;
150
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700151 typedef PayloadTraits payload_traits;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700152
153 inline
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700154 trie (const Key &key, size_t bucketSize = 10, size_t bucketIncrement = 10)
155 : key_ (key)
156 , initialBucketSize_ (bucketSize)
157 , bucketIncrement_ (bucketIncrement)
158 , bucketSize_ (initialBucketSize_)
159 , buckets_ (new bucket_type [bucketSize_]) //cannot use normal pointer, because lifetime of buckets should be larger than lifetime of the container
160 , children_ (bucket_traits (buckets_.get (), bucketSize_))
161 , payload_ (PayloadTraits::empty_payload)
162 , parent_ (0)
163 {
164 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700165
166 inline
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700167 ~trie ()
168 {
169 payload_ = PayloadTraits::empty_payload; // necessary for smart pointers...
170 children_.clear_and_dispose (trie_delete_disposer ());
171 }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700172
173 void
174 clear ()
175 {
176 children_.clear_and_dispose (trie_delete_disposer ());
177 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700178
179 template<class Predicate>
180 void
181 clear_if (Predicate cond)
182 {
183 recursive_iterator trieNode (this);
184 recursive_iterator end (0);
185
186 while (trieNode != end)
187 {
188 if (cond (*trieNode))
189 {
190 trieNode = recursive_iterator (trieNode->erase ());
191 }
192 trieNode ++;
193 }
194 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700195
196 // actual entry
197 friend bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700198 operator== <> (const trie<FullKey, PayloadTraits, PolicyHook> &a,
199 const trie<FullKey, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700200
201 friend std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700202 hash_value <> (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700203
204 inline std::pair<iterator, bool>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700205 insert (const FullKey &key,
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700206 typename PayloadTraits::insert_type payload)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700207 {
208 trie *trieNode = this;
209
210 BOOST_FOREACH (const Key &subkey, key)
211 {
212 typename unordered_set::iterator item = trieNode->children_.find (subkey);
213 if (item == trieNode->children_.end ())
214 {
215 trie *newNode = new trie (subkey, initialBucketSize_, bucketIncrement_);
216 // std::cout << "new " << newNode << "\n";
217 newNode->parent_ = trieNode;
218
219 if (trieNode->children_.size () >= trieNode->bucketSize_)
220 {
221 trieNode->bucketSize_ += trieNode->bucketIncrement_;
Alexander Afanasyev424d5842012-09-03 17:35:34 -0700222 trieNode->bucketIncrement_ *= 2; // increase bucketIncrement exponentially
223
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700224 buckets_array newBuckets (new bucket_type [trieNode->bucketSize_]);
225 trieNode->children_.rehash (bucket_traits (newBuckets.get (), trieNode->bucketSize_));
226 trieNode->buckets_.swap (newBuckets);
227 }
228
229 std::pair< typename unordered_set::iterator, bool > ret =
230 trieNode->children_.insert (*newNode);
231
232 trieNode = &(*ret.first);
233 }
234 else
235 trieNode = &(*item);
236 }
237
238 if (trieNode->payload_ == PayloadTraits::empty_payload)
239 {
240 trieNode->payload_ = payload;
241 return std::make_pair (trieNode, true);
242 }
243 else
244 return std::make_pair (trieNode, false);
245 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700246
247 /**
248 * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
249 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700250 inline iterator
251 erase ()
252 {
253 payload_ = PayloadTraits::empty_payload;
254 return prune ();
255 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700256
257 /**
258 * @brief Do exactly as erase, but without erasing the payload
259 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700260 inline iterator
261 prune ()
262 {
263 if (payload_ == PayloadTraits::empty_payload &&
264 children_.size () == 0)
265 {
266 if (parent_ == 0) return this;
267
268 trie *parent = parent_;
269 parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
270
271 return parent->prune ();
272 }
273 return this;
274 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700275
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700276 /**
277 * @brief Perform prune of the node, but without attempting to parent of the node
278 */
279 inline void
280 prune_node ()
281 {
282 if (payload_ == PayloadTraits::empty_payload &&
283 children_.size () == 0)
284 {
285 if (parent_ == 0) return;
286
287 trie *parent = parent_;
288 parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
289 }
290 }
291
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700292 // inline boost::tuple<const iterator, bool, const iterator>
293 // find (const FullKey &key) const
294 // {
295 // return const_cast<trie*> (this)->find (key);
296 // }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700297
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700298 /**
299 * @brief Perform the longest prefix match
300 * @param key the key for which to perform the longest prefix match
301 *
302 * @return ->second is true if prefix in ->first is longer than key
303 */
304 inline boost::tuple<iterator, bool, iterator>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700305 find (const FullKey &key)
306 {
307 trie *trieNode = this;
308 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
309 bool reachLast = true;
310
311 BOOST_FOREACH (const Key &subkey, key)
312 {
313 typename unordered_set::iterator item = trieNode->children_.find (subkey);
314 if (item == trieNode->children_.end ())
315 {
316 reachLast = false;
317 break;
318 }
319 else
320 {
321 trieNode = &(*item);
322
323 if (trieNode->payload_ != PayloadTraits::empty_payload)
324 foundNode = trieNode;
325 }
326 }
327
328 return boost::make_tuple (foundNode, reachLast, trieNode);
329 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700330
331 /**
332 * @brief Find next payload of the sub-trie
333 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
334 */
335 inline iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700336 find ()
337 {
338 if (payload_ != PayloadTraits::empty_payload)
339 return this;
340
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700341 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700342 for (typename trie::unordered_set::iterator subnode = children_.begin ();
343 subnode != children_.end ();
344 subnode++ )
345 // BOOST_FOREACH (trie &subnode, children_)
346 {
347 iterator value = subnode->find ();
348 if (value != 0)
349 return value;
350 }
351
352 return 0;
353 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700354
355 /**
356 * @brief Find next payload of the sub-trie satisfying the predicate
357 * @param pred predicate
358 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
359 */
360 template<class Predicate>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700361 inline const iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700362 find_if (Predicate pred)
363 {
364 if (payload_ != PayloadTraits::empty_payload && pred (payload_))
365 return this;
366
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700367 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700368 for (typename trie::unordered_set::iterator subnode = children_.begin ();
369 subnode != children_.end ();
370 subnode++ )
371 // BOOST_FOREACH (const trie &subnode, children_)
372 {
373 iterator value = subnode->find ();
374 if (value != 0)
375 return value;
376 }
377
378 return 0;
379 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700380
381 iterator end ()
382 {
383 return 0;
384 }
385
386 const_iterator end () const
387 {
388 return 0;
389 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700390
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700391 typename PayloadTraits::const_return_type
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700392 payload () const
393 {
394 return payload_;
395 }
396
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700397 typename PayloadTraits::return_type
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700398 payload ()
399 {
400 return payload_;
401 }
402
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700403 void
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700404 set_payload (typename PayloadTraits::insert_type payload)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700405 {
406 payload_ = payload;
407 }
Alexander Afanasyev0560eec2012-07-16 15:44:31 -0700408
409 Key key () const
410 {
411 return key_;
412 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700413
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700414 inline void
415 PrintStat (std::ostream &os) const;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700416
417private:
418 //The disposer object function
419 struct trie_delete_disposer
420 {
421 void operator() (trie *delete_this)
422 {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700423 delete delete_this;
424 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700425 };
426
427 template<class D>
428 struct array_disposer
429 {
430 void operator() (D *array)
431 {
432 delete [] array;
433 }
434 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700435
436 friend
437 std::ostream&
438 operator<< < > (std::ostream &os, const trie &trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700439
440public:
441 PolicyHook policy_hook_;
442
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700443private:
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700444 boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700445
446 // necessary typedefs
447 typedef trie self_type;
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700448 typedef boost::intrusive::member_hook< trie,
449 boost::intrusive::unordered_set_member_hook< >,
450 &trie::unordered_set_member_hook_ > member_hook;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700451
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700452 typedef boost::intrusive::unordered_set< trie, member_hook > unordered_set;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700453 typedef typename unordered_set::bucket_type bucket_type;
454 typedef typename unordered_set::bucket_traits bucket_traits;
455
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700456 template<class T, class NonConstT>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700457 friend class trie_iterator;
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700458
459 template<class T>
460 friend class trie_point_iterator;
461
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700462 ////////////////////////////////////////////////
463 // Actual data
464 ////////////////////////////////////////////////
465
466 Key key_; ///< name component
467
468 size_t initialBucketSize_;
469 size_t bucketIncrement_;
470
471 size_t bucketSize_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700472 typedef boost::interprocess::unique_ptr< bucket_type, array_disposer<bucket_type> > buckets_array;
473 buckets_array buckets_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700474 unordered_set children_;
475
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700476 typename PayloadTraits::storage_type payload_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700477 trie *parent_; // to make cleaning effective
478};
479
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700480
481
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700482
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700483template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700484inline std::ostream&
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700485operator << (std::ostream &os, const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700486{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700487 os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << std::endl;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700488 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700489
490 for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin ();
491 subnode != trie_node.children_.end ();
492 subnode++ )
493 // BOOST_FOREACH (const trie &subnode, trie_node.children_)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700494 {
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700495 os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]\n";
496 os << "\"" << &(*subnode) << "\"" << " [label=\"" << subnode->key_ << ((subnode->payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]""\n";
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700497
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700498 os << "\"" << &trie_node << "\"" << " -> " << "\"" << &(*subnode) << "\"" << "\n";
499 os << *subnode;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700500 }
501
502 return os;
503}
504
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700505template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700506inline void
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700507trie<FullKey, PayloadTraits, PolicyHook>
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700508::PrintStat (std::ostream &os) const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700509{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700510 os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload)?"*":"") << ": " << children_.size() << " children" << std::endl;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700511 for (size_t bucket = 0, maxbucket = children_.bucket_count ();
512 bucket < maxbucket;
513 bucket++)
514 {
515 os << " " << children_.bucket_size (bucket);
516 }
517 os << "\n";
518
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700519 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700520 for (typename trie::unordered_set::const_iterator subnode = children_.begin ();
521 subnode != children_.end ();
522 subnode++ )
523 // BOOST_FOREACH (const trie &subnode, children_)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700524 {
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700525 subnode->PrintStat (os);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700526 }
527}
528
529
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700530template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700531inline bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700532operator == (const trie<FullKey, PayloadTraits, PolicyHook> &a,
533 const trie<FullKey, PayloadTraits, PolicyHook> &b)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700534{
535 return a.key_ == b.key_;
536}
537
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700538template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700539inline std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700540hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700541{
542 return boost::hash_value (trie_node.key_);
543}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700544
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700545
546
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700547template<class Trie, class NonConstTrie> // hack for boost < 1.47
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700548class trie_iterator
549{
550public:
551 trie_iterator () : trie_ (0) {}
552 trie_iterator (typename Trie::iterator item) : trie_ (item) {}
553 trie_iterator (Trie &item) : trie_ (&item) {}
554
555 Trie & operator* () { return *trie_; }
556 const Trie & operator* () const { return *trie_; }
557 Trie * operator-> () { return trie_; }
558 const Trie * operator-> () const { return trie_; }
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700559 bool operator== (trie_iterator<const Trie, NonConstTrie> &other) const { return (trie_ == other.trie_); }
560 bool operator== (trie_iterator<Trie, NonConstTrie> &other) { return (trie_ == other.trie_); }
561 bool operator!= (trie_iterator<const Trie, NonConstTrie> &other) const { return !(*this == other); }
562 bool operator!= (trie_iterator<Trie, NonConstTrie> &other) { return !(*this == other); }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700563
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700564 trie_iterator<Trie,NonConstTrie> &
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700565 operator++ (int)
566 {
567 if (trie_->children_.size () > 0)
568 trie_ = &(*trie_->children_.begin ());
569 else
570 trie_ = goUp ();
571 return *this;
572 }
573
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700574 trie_iterator<Trie,NonConstTrie> &
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700575 operator++ ()
576 {
577 (*this)++;
578 return *this;
579 }
580
581private:
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700582 typedef typename boost::mpl::if_< boost::is_same<Trie, NonConstTrie>,
583 typename Trie::unordered_set::iterator,
584 typename Trie::unordered_set::const_iterator>::type set_iterator;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700585
586 Trie* goUp ()
587 {
588 if (trie_->parent_ != 0)
589 {
590 // typename Trie::unordered_set::iterator item =
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700591 set_iterator item = const_cast<NonConstTrie*>(trie_)->parent_->children_.iterator_to (const_cast<NonConstTrie&> (*trie_));
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700592 item++;
593 if (item != trie_->parent_->children_.end ())
594 {
595 return &(*item);
596 }
597 else
598 {
599 trie_ = trie_->parent_;
600 return goUp ();
601 }
602 }
603 else
604 return 0;
605 }
606private:
607 Trie *trie_;
608};
609
610
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700611template<class Trie>
612class trie_point_iterator
613{
614private:
615 typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
616 typename Trie::unordered_set::const_iterator,
617 typename Trie::unordered_set::iterator>::type set_iterator;
618
619public:
620 trie_point_iterator () : trie_ (0) {}
621 trie_point_iterator (typename Trie::iterator item) : trie_ (item) {}
622 trie_point_iterator (Trie &item)
623 {
624 if (item.children_.size () != 0)
625 trie_ = &*item.children_.begin ();
626 else
627 trie_ = 0;
628 }
629
630 Trie & operator* () { return *trie_; }
631 const Trie & operator* () const { return *trie_; }
632 Trie * operator-> () { return trie_; }
633 const Trie * operator-> () const { return trie_; }
634 bool operator== (trie_point_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
635 bool operator== (trie_point_iterator<Trie> &other) { return (trie_ == other.trie_); }
636 bool operator!= (trie_point_iterator<const Trie> &other) const { return !(*this == other); }
637 bool operator!= (trie_point_iterator<Trie> &other) { return !(*this == other); }
638
639 trie_point_iterator<Trie> &
640 operator++ (int)
641 {
642 if (trie_->parent_ != 0)
643 {
644 set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
645 item ++;
646 if (item == trie_->parent_->children_.end ())
647 trie_ = 0;
648 else
649 trie_ = &*item;
650 }
651 else
652 {
653 trie_ = 0;
654 }
655 return *this;
656 }
657
658 trie_point_iterator<Trie> &
659 operator++ ()
660 {
661 (*this)++;
662 return *this;
663 }
664
665private:
666 Trie *trie_;
667};
668
669
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700670} // ndnSIM
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700671} // ndn
Alexander Afanasyeve77db792012-08-09 11:10:58 -0700672} // ns3
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700673
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700674#endif // TRIE_H_