blob: 62411d6017d52a9eabf2e7a8e7b844f32f063097 [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 Afanasyeveec66292013-02-06 16:23:21 -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;
Alexander Afanasyeveec66292013-02-06 16:23:21 -080068
Alexander Afanasyev0845c092012-07-13 17:45:33 -070069 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 Afanasyeveec66292013-02-06 16:23:21 -080074
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;
Alexander Afanasyeveec66292013-02-06 16:23:21 -080091
Alexander Afanasyev62304f22012-12-10 18:06:21 -080092 typedef BasePayload& base_type;
93 typedef const BasePayload& const_base_type;
Alexander Afanasyeveec66292013-02-06 16:23:21 -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 Afanasyeveec66292013-02-06 16:23:21 -080099Payload
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 Afanasyeveec66292013-02-06 16:23:21 -0800109class trie;
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 -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 Afanasyeveec66292013-02-06 16:23:21 -0800152
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700153 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 Afanasyeveec66292013-02-06 16:23:21 -0800195
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700196 // 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;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800209
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700210 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
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800223
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 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800228
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700229 std::pair< typename unordered_set::iterator, bool > ret =
230 trieNode->children_.insert (*newNode);
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800231
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700232 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;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800310
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700311 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);
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800322
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700323 if (trieNode->payload_ != PayloadTraits::empty_payload)
324 foundNode = trieNode;
325 }
326 }
327
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800328 return boost::make_tuple (foundNode, reachLast, trieNode);
329 }
330
331 /**
332 * @brief Perform the longest prefix match satisfying preficate
333 * @param key the key for which to perform the longest prefix match
334 *
335 * @return ->second is true if prefix in ->first is longer than key
336 */
337 template<class Predicate>
338 inline boost::tuple<iterator, bool, iterator>
339 find_if (const FullKey &key, Predicate pred)
340 {
341 trie *trieNode = this;
342 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
343 bool reachLast = true;
344
345 BOOST_FOREACH (const Key &subkey, key)
346 {
347 typename unordered_set::iterator item = trieNode->children_.find (subkey);
348 if (item == trieNode->children_.end ())
349 {
350 reachLast = false;
351 break;
352 }
353 else
354 {
355 trieNode = &(*item);
356
357 if (trieNode->payload_ != PayloadTraits::empty_payload &&
358 pred (trieNode->payload_))
359 {
360 foundNode = trieNode;
361 }
362 }
363 }
364
365 return boost::make_tuple (foundNode, reachLast, trieNode);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700366 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700367
368 /**
369 * @brief Find next payload of the sub-trie
370 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
371 */
372 inline iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700373 find ()
374 {
375 if (payload_ != PayloadTraits::empty_payload)
376 return this;
377
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700378 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700379 for (typename trie::unordered_set::iterator subnode = children_.begin ();
380 subnode != children_.end ();
381 subnode++ )
382 // BOOST_FOREACH (trie &subnode, children_)
383 {
384 iterator value = subnode->find ();
385 if (value != 0)
386 return value;
387 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800388
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700389 return 0;
390 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700391
392 /**
393 * @brief Find next payload of the sub-trie satisfying the predicate
394 * @param pred predicate
395 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
396 */
397 template<class Predicate>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700398 inline const iterator
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700399 find_if (Predicate pred)
400 {
401 if (payload_ != PayloadTraits::empty_payload && pred (payload_))
402 return this;
403
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700404 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700405 for (typename trie::unordered_set::iterator subnode = children_.begin ();
406 subnode != children_.end ();
407 subnode++ )
408 // BOOST_FOREACH (const trie &subnode, children_)
409 {
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800410 iterator value = subnode->find_if (pred);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700411 if (value != 0)
412 return value;
413 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800414
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700415 return 0;
416 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700417
418 iterator end ()
419 {
420 return 0;
421 }
422
423 const_iterator end () const
424 {
425 return 0;
426 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700427
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700428 typename PayloadTraits::const_return_type
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700429 payload () const
430 {
431 return payload_;
432 }
433
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700434 typename PayloadTraits::return_type
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700435 payload ()
436 {
437 return payload_;
438 }
439
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700440 void
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700441 set_payload (typename PayloadTraits::insert_type payload)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700442 {
443 payload_ = payload;
444 }
Alexander Afanasyev0560eec2012-07-16 15:44:31 -0700445
446 Key key () const
447 {
448 return key_;
449 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800450
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700451 inline void
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800452 PrintStat (std::ostream &os) const;
453
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700454private:
455 //The disposer object function
456 struct trie_delete_disposer
457 {
458 void operator() (trie *delete_this)
459 {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700460 delete delete_this;
461 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700462 };
463
464 template<class D>
465 struct array_disposer
466 {
467 void operator() (D *array)
468 {
469 delete [] array;
470 }
471 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700472
473 friend
474 std::ostream&
475 operator<< < > (std::ostream &os, const trie &trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700476
477public:
478 PolicyHook policy_hook_;
479
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700480private:
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700481 boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700482
483 // necessary typedefs
484 typedef trie self_type;
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700485 typedef boost::intrusive::member_hook< trie,
486 boost::intrusive::unordered_set_member_hook< >,
487 &trie::unordered_set_member_hook_ > member_hook;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700488
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700489 typedef boost::intrusive::unordered_set< trie, member_hook > unordered_set;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700490 typedef typename unordered_set::bucket_type bucket_type;
491 typedef typename unordered_set::bucket_traits bucket_traits;
492
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700493 template<class T, class NonConstT>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700494 friend class trie_iterator;
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700495
496 template<class T>
497 friend class trie_point_iterator;
498
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700499 ////////////////////////////////////////////////
500 // Actual data
501 ////////////////////////////////////////////////
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800502
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700503 Key key_; ///< name component
504
505 size_t initialBucketSize_;
506 size_t bucketIncrement_;
507
508 size_t bucketSize_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700509 typedef boost::interprocess::unique_ptr< bucket_type, array_disposer<bucket_type> > buckets_array;
510 buckets_array buckets_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700511 unordered_set children_;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800512
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700513 typename PayloadTraits::storage_type payload_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700514 trie *parent_; // to make cleaning effective
515};
516
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700517
518
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700519
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700520template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700521inline std::ostream&
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700522operator << (std::ostream &os, const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700523{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700524 os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << std::endl;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700525 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700526
527 for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin ();
528 subnode != trie_node.children_.end ();
529 subnode++ )
530 // BOOST_FOREACH (const trie &subnode, trie_node.children_)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700531 {
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700532 os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]\n";
533 os << "\"" << &(*subnode) << "\"" << " [label=\"" << subnode->key_ << ((subnode->payload_ != PayloadTraits::empty_payload)?"*":"") << "\"]""\n";
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800534
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700535 os << "\"" << &trie_node << "\"" << " -> " << "\"" << &(*subnode) << "\"" << "\n";
536 os << *subnode;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700537 }
538
539 return os;
540}
541
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700542template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700543inline void
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700544trie<FullKey, PayloadTraits, PolicyHook>
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700545::PrintStat (std::ostream &os) const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700546{
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700547 os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload)?"*":"") << ": " << children_.size() << " children" << std::endl;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700548 for (size_t bucket = 0, maxbucket = children_.bucket_count ();
549 bucket < maxbucket;
550 bucket++)
551 {
552 os << " " << children_.bucket_size (bucket);
553 }
554 os << "\n";
555
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700556 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700557 for (typename trie::unordered_set::const_iterator subnode = children_.begin ();
558 subnode != children_.end ();
559 subnode++ )
560 // BOOST_FOREACH (const trie &subnode, children_)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700561 {
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700562 subnode->PrintStat (os);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700563 }
564}
565
566
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700567template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700568inline bool
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700569operator == (const trie<FullKey, PayloadTraits, PolicyHook> &a,
570 const trie<FullKey, PayloadTraits, PolicyHook> &b)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700571{
572 return a.key_ == b.key_;
573}
574
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700575template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700576inline std::size_t
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700577hash_value (const trie<FullKey, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700578{
579 return boost::hash_value (trie_node.key_);
580}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700581
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700582
583
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700584template<class Trie, class NonConstTrie> // hack for boost < 1.47
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700585class trie_iterator
586{
587public:
588 trie_iterator () : trie_ (0) {}
589 trie_iterator (typename Trie::iterator item) : trie_ (item) {}
590 trie_iterator (Trie &item) : trie_ (&item) {}
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800591
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700592 Trie & operator* () { return *trie_; }
593 const Trie & operator* () const { return *trie_; }
594 Trie * operator-> () { return trie_; }
595 const Trie * operator-> () const { return trie_; }
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700596 bool operator== (trie_iterator<const Trie, NonConstTrie> &other) const { return (trie_ == other.trie_); }
597 bool operator== (trie_iterator<Trie, NonConstTrie> &other) { return (trie_ == other.trie_); }
598 bool operator!= (trie_iterator<const Trie, NonConstTrie> &other) const { return !(*this == other); }
599 bool operator!= (trie_iterator<Trie, NonConstTrie> &other) { return !(*this == other); }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800600
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700601 trie_iterator<Trie,NonConstTrie> &
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700602 operator++ (int)
603 {
604 if (trie_->children_.size () > 0)
605 trie_ = &(*trie_->children_.begin ());
606 else
607 trie_ = goUp ();
608 return *this;
609 }
610
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700611 trie_iterator<Trie,NonConstTrie> &
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700612 operator++ ()
613 {
614 (*this)++;
615 return *this;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800616 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700617
618private:
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700619 typedef typename boost::mpl::if_< boost::is_same<Trie, NonConstTrie>,
620 typename Trie::unordered_set::iterator,
621 typename Trie::unordered_set::const_iterator>::type set_iterator;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800622
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700623 Trie* goUp ()
624 {
625 if (trie_->parent_ != 0)
626 {
627 // typename Trie::unordered_set::iterator item =
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700628 set_iterator item = const_cast<NonConstTrie*>(trie_)->parent_->children_.iterator_to (const_cast<NonConstTrie&> (*trie_));
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700629 item++;
630 if (item != trie_->parent_->children_.end ())
631 {
632 return &(*item);
633 }
634 else
635 {
636 trie_ = trie_->parent_;
637 return goUp ();
638 }
639 }
640 else
641 return 0;
642 }
643private:
644 Trie *trie_;
645};
646
647
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700648template<class Trie>
649class trie_point_iterator
650{
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800651private:
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700652 typedef typename boost::mpl::if_< boost::is_same<Trie, const Trie>,
653 typename Trie::unordered_set::const_iterator,
654 typename Trie::unordered_set::iterator>::type set_iterator;
655
656public:
657 trie_point_iterator () : trie_ (0) {}
658 trie_point_iterator (typename Trie::iterator item) : trie_ (item) {}
659 trie_point_iterator (Trie &item)
660 {
661 if (item.children_.size () != 0)
662 trie_ = &*item.children_.begin ();
663 else
664 trie_ = 0;
665 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800666
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700667 Trie & operator* () { return *trie_; }
668 const Trie & operator* () const { return *trie_; }
669 Trie * operator-> () { return trie_; }
670 const Trie * operator-> () const { return trie_; }
671 bool operator== (trie_point_iterator<const Trie> &other) const { return (trie_ == other.trie_); }
672 bool operator== (trie_point_iterator<Trie> &other) { return (trie_ == other.trie_); }
673 bool operator!= (trie_point_iterator<const Trie> &other) const { return !(*this == other); }
674 bool operator!= (trie_point_iterator<Trie> &other) { return !(*this == other); }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800675
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700676 trie_point_iterator<Trie> &
677 operator++ (int)
678 {
679 if (trie_->parent_ != 0)
680 {
681 set_iterator item = trie_->parent_->children_.iterator_to (*trie_);
682 item ++;
683 if (item == trie_->parent_->children_.end ())
684 trie_ = 0;
685 else
686 trie_ = &*item;
687 }
688 else
689 {
690 trie_ = 0;
691 }
692 return *this;
693 }
694
695 trie_point_iterator<Trie> &
696 operator++ ()
697 {
698 (*this)++;
699 return *this;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800700 }
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700701
702private:
703 Trie *trie_;
704};
705
706
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700707} // ndnSIM
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700708} // ndn
Alexander Afanasyeve77db792012-08-09 11:10:58 -0700709} // ns3
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700710
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700711#endif // TRIE_H_