blob: e45ee70a2a18a71601dc0bea05d2e7d61f9dd8d7 [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
21#include "ns3/core-module.h"
22#include "ns3/ndnSIM-module.h"
23
24#include <boost/intrusive/unordered_set.hpp>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070025#include <boost/intrusive/list.hpp>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070026#include <boost/functional/hash.hpp>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070027#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
28#include <boost/tuple/tuple.hpp>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070029
30namespace bi = boost::intrusive;
31
32/////////////////////////////////////////////////////
33// Allow customization for payload
34//
35template<typename Payload>
36struct pointer_payload_traits
37{
38 typedef Payload* pointer_type;
39 typedef const Payload* const_pointer_type;
40
41 static const Payload* empty_payload;
42};
43
44template<typename Payload>
45const Payload*
46pointer_payload_traits<Payload>::empty_payload = 0;
47
48template<typename Payload>
49struct smart_pointer_payload_traits
50{
51 typedef ns3::Ptr<Payload> pointer_type;
52 typedef ns3::Ptr<const Payload> const_pointer_type;
53
54 static const ns3::Ptr<const Payload> empty_payload;
55};
56
57template<typename Payload>
58const ns3::Ptr<const Payload>
59smart_pointer_payload_traits<Payload>::empty_payload = 0;
60
61
62////////////////////////////////////////////////////
63// forward declarations
64//
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070065template<typename FullKey,
66 typename Payload,
67 typename PayloadTraits = pointer_payload_traits<Payload>,
68 typename PolicyHook = bi::list_member_hook<> >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070069class trie;
70
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070071template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070072inline std::ostream&
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070073operator << (std::ostream &os,
74 const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070075
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070076template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070077bool
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070078operator== (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &a,
79 const trie<FullKey, Payload, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070080
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070081template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070082std::size_t
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070083hash_value (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070084
85///////////////////////////////////////////////////
86// actual definition
87//
88
89
90template<typename FullKey,
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070091 typename Payload, typename PayloadTraits,
92 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070093class trie
94{
95public:
96 typedef typename FullKey::partial_type Key;
97
98 typedef trie* iterator;
99 typedef const trie* const_iterator;
100
101 inline
102 trie (const Key &key, size_t bucketSize = 10, size_t bucketIncrement = 10);
103
104 inline
105 ~trie ();
106
107 // actual entry
108 friend bool
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700109 operator== <> (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &a,
110 const trie<FullKey, Payload, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700111
112 friend std::size_t
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700113 hash_value <> (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700114
115 inline std::pair<iterator, bool>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700116 insert (const FullKey &key,
117 typename PayloadTraits::const_pointer_type payload);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700118
119 /**
120 * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
121 */
122 inline void
123 erase ();
124
125 /**
126 * @brief Do exactly as erase, but without erasing the payload
127 */
128 inline void
129 prune ();
130
131 /**
132 * @brief Perform the longest prefix match
133 * @param key the key for which to perform the longest prefix match
134 *
135 * @return ->second is true if prefix in ->first is longer than key
136 */
137 inline boost::tuple<iterator, bool, iterator>
138 find (const FullKey &key);
139
140 /**
141 * @brief Find next payload of the sub-trie
142 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
143 */
144 inline iterator
145 find ();
146
147 /**
148 * @brief Find next payload of the sub-trie satisfying the predicate
149 * @param pred predicate
150 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
151 */
152 template<class Predicate>
153 inline iterator
154 find_if (Predicate pred);
155
156 iterator end ()
157 {
158 return 0;
159 }
160
161 const_iterator end () const
162 {
163 return 0;
164 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700165
166 typename PayloadTraits::const_pointer_type
167 payload () const
168 {
169 return payload_;
170 }
171
172 void
173 set_payload (typename PayloadTraits::const_pointer_type payload)
174 {
175 payload_ = payload;
176 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700177
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700178 inline void
179 PrintStat (std::ostream &os) const;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700180
181private:
182 //The disposer object function
183 struct trie_delete_disposer
184 {
185 void operator() (trie *delete_this)
186 {
187 // std::cout << "Deleting " << delete_this << "\n";
188 delete delete_this;
189 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700190 };
191
192 template<class D>
193 struct array_disposer
194 {
195 void operator() (D *array)
196 {
197 delete [] array;
198 }
199 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700200
201 friend
202 std::ostream&
203 operator<< < > (std::ostream &os, const trie &trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700204
205public:
206 PolicyHook policy_hook_;
207
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700208private:
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700209 bi::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700210
211 // necessary typedefs
212 typedef trie self_type;
213 typedef bi::member_hook< trie,
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700214 bi::unordered_set_member_hook< >, &trie::unordered_set_member_hook_ > member_hook;
215 typedef bi::unordered_set< trie, member_hook > unordered_set;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700216 typedef typename unordered_set::bucket_type bucket_type;
217 typedef typename unordered_set::bucket_traits bucket_traits;
218
219 ////////////////////////////////////////////////
220 // Actual data
221 ////////////////////////////////////////////////
222
223 Key key_; ///< name component
224
225 size_t initialBucketSize_;
226 size_t bucketIncrement_;
227
228 size_t bucketSize_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700229 typedef boost::interprocess::unique_ptr< bucket_type, array_disposer<bucket_type> > buckets_array;
230 buckets_array buckets_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700231 unordered_set children_;
232
233 typename PayloadTraits::const_pointer_type payload_;
234 trie *parent_; // to make cleaning effective
235};
236
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700237template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
238trie<FullKey, Payload, PayloadTraits, PolicyHook>
239::trie (const trie::Key &key, size_t bucketSize, size_t bucketIncrement)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700240 : key_ (key)
241 , initialBucketSize_ (bucketSize)
242 , bucketIncrement_ (bucketIncrement)
243 , bucketSize_ (initialBucketSize_)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700244 , buckets_ (new bucket_type [bucketSize_]) //cannot use normal pointer, because lifetime of buckets should be larger than lifetime of the container
245 , children_ (bucket_traits (buckets_.get (), bucketSize_))
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700246 , payload_ (PayloadTraits::empty_payload)
247 , parent_ (0)
248{
249}
250
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700251template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
252trie<FullKey, Payload, PayloadTraits, PolicyHook>
253::~trie ()
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700254{
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700255 payload_ = PayloadTraits::empty_payload; // necessary for smart pointers...
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700256 children_.clear_and_dispose (trie_delete_disposer ());
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700257}
258
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700259template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700260inline
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700261std::pair<typename trie<FullKey, Payload, PayloadTraits, PolicyHook>::iterator, bool>
262trie<FullKey, Payload, PayloadTraits, PolicyHook>
263::insert (const FullKey &key, typename PayloadTraits::const_pointer_type payload)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700264{
265 trie *trieNode = this;
266
267 BOOST_FOREACH (const Key &subkey, key)
268 {
269 typename unordered_set::iterator item = trieNode->children_.find (subkey);
270 if (item == trieNode->children_.end ())
271 {
272 trie *newNode = new trie (subkey, initialBucketSize_, bucketIncrement_);
273 // std::cout << "new " << newNode << "\n";
274 newNode->parent_ = trieNode;
275
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700276 if (trieNode->children_.size () >= trieNode->bucketSize_)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700277 {
278 trieNode->bucketSize_ += trieNode->bucketIncrement_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700279 buckets_array newBuckets (new bucket_type [trieNode->bucketSize_]);
280 trieNode->children_.rehash (bucket_traits (newBuckets.get (), trieNode->bucketSize_));
281 trieNode->buckets_.swap (newBuckets);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700282 }
283
284 std::pair< typename unordered_set::iterator, bool > ret =
285 trieNode->children_.insert (*newNode);
286
287 trieNode = &(*ret.first);
288 }
289 else
290 trieNode = &(*item);
291 }
292
293 if (trieNode->payload_ == 0)
294 {
295 trieNode->payload_ = payload;
296 return std::make_pair (trieNode, true);
297 }
298 else
299 return std::make_pair (trieNode, false);
300}
301
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700302template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700303inline
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700304boost::tuple<typename trie<FullKey, Payload, PayloadTraits, PolicyHook>::iterator,
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700305 bool,
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700306 typename trie<FullKey, Payload, PayloadTraits, PolicyHook>::iterator>
307trie<FullKey, Payload, PayloadTraits, PolicyHook>
308::find (const FullKey &key)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700309{
310 trie *trieNode = this;
311 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
312 bool reachLast = true;
313
314 BOOST_FOREACH (const Key &subkey, key)
315 {
316 typename unordered_set::iterator item = trieNode->children_.find (subkey);
317 if (item == trieNode->children_.end ())
318 {
319 reachLast = false;
320 break;
321 }
322 else
323 {
324 trieNode = &(*item);
325
326 if (trieNode->payload_ != PayloadTraits::empty_payload)
327 foundNode = trieNode;
328 }
329 }
330
331 return boost::make_tuple (foundNode, reachLast, trieNode);
332}
333
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700334template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
335inline typename trie<FullKey, Payload, PayloadTraits, PolicyHook>::iterator
336trie<FullKey, Payload, PayloadTraits, PolicyHook>
337::find ()
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700338{
339 if (payload_ != PayloadTraits::empty_payload)
340 return this;
341
342 typedef trie<FullKey, Payload, PayloadTraits> trie;
343 BOOST_FOREACH (const trie &subnode, children_)
344 {
345 iterator value = subnode.find ();
346 if (value != 0)
347 return value;
348 }
349
350 return 0;
351}
352
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700353template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700354template<class Predicate>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700355inline typename trie<FullKey, Payload, PayloadTraits, PolicyHook>::iterator
356trie<FullKey, Payload, PayloadTraits, PolicyHook>
357::find_if (Predicate pred)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700358{
359 if (payload_ != PayloadTraits::empty_payload && pred (payload_))
360 return this;
361
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700362 typedef trie<FullKey, Payload, PayloadTraits, PolicyHook> trie;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700363 BOOST_FOREACH (const trie &subnode, children_)
364 {
365 iterator value = subnode.find ();
366 if (value != 0)
367 return value;
368 }
369
370 return 0;
371}
372
373
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700374template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700375inline void
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700376trie<FullKey, Payload, PayloadTraits, PolicyHook>::erase ()
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700377{
378 payload_ = PayloadTraits::empty_payload;
379 prune ();
380}
381
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700382template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700383inline void
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700384trie<FullKey, Payload, PayloadTraits, PolicyHook>::prune ()
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700385{
386 if (payload_ == 0 && children_.size () == 0)
387 {
388 if (parent_ == 0) return;
389
390 trie *parent = parent_;
391 parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
392
393 parent->prune ();
394 }
395}
396
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700397template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700398inline std::ostream&
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700399operator << (std::ostream &os, const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700400{
401 os << "# " << trie_node.key_ << ((trie_node.payload_ != 0)?"*":"") << std::endl;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700402 typedef trie<FullKey, Payload, PayloadTraits, PolicyHook> trie;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700403 BOOST_FOREACH (const trie &subnode, trie_node.children_)
404 {
405 os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != 0)?"*":"") << "\"]\n";
406 os << "\"" << &subnode << "\"" << " [label=\"" << subnode.key_ << ((subnode.payload_ != 0)?"*":"") << "\"]""\n";
407
408 os << "\"" << &trie_node << "\"" << " -> " << "\"" << &subnode << "\"" << "\n";
409 os << subnode;
410 }
411
412 return os;
413}
414
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700415template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
416inline void
417trie<FullKey, Payload, PayloadTraits, PolicyHook>::PrintStat (std::ostream &os) const
418{
419 os << "# " << key_ << ((payload_ != 0)?"*":"") << ": " << children_.size() << " children" << std::endl;
420 for (size_t bucket = 0, maxbucket = children_.bucket_count ();
421 bucket < maxbucket;
422 bucket++)
423 {
424 os << " " << children_.bucket_size (bucket);
425 }
426 os << "\n";
427
428 typedef trie<FullKey, Payload, PayloadTraits, PolicyHook> trie;
429 BOOST_FOREACH (const trie &subnode, children_)
430 {
431 subnode.PrintStat (os);
432 }
433}
434
435
436template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700437inline bool
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700438operator == (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &a,
439 const trie<FullKey, Payload, PayloadTraits, PolicyHook> &b)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700440{
441 return a.key_ == b.key_;
442}
443
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700444template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700445inline std::size_t
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700446hash_value (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700447{
448 return boost::hash_value (trie_node.key_);
449}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700450
451
452
453template<typename FullKey,
454 typename Payload, typename PayloadTraits
455 >
456struct lru_policy_traits
457{
458 typedef trie< FullKey, Payload, PayloadTraits, bi::list_member_hook<> > parent_trie;
459 typedef typename bi::list< parent_trie,
460 bi::member_hook< parent_trie,
461 bi::list_member_hook<>,
462 &parent_trie::policy_hook_ > > policy_container;
463
464 class policy : public policy_container
465 {
466 public:
467 policy ()
468 : max_size_ (100)
469 {
470 }
471
472 inline void
473 update (typename parent_trie::iterator item)
474 {
475 // do relocation
476 policy_container::splice (policy_container::end (),
477 *this,
478 policy_container::s_iterator_to (*item));
479 }
480
481 inline void
482 insert (typename parent_trie::iterator item)
483 {
484 if (policy_container::size () >= max_size_)
485 {
486 typename parent_trie::iterator oldItem = &(*policy_container::begin ());
487 policy_container::pop_front ();
488 oldItem->erase ();
489 }
490
491 policy_container::push_back (*item);
492 }
493
494 inline void
495 lookup (typename parent_trie::iterator item)
496 {
497 // do relocation
498 policy_container::splice (policy_container::end (),
499 *this,
500 policy_container::s_iterator_to (*item));
501 }
502
503 inline void
504 erase (typename parent_trie::iterator item)
505 {
506 policy_container::erase (policy_container::s_iterator_to (*item));
507 }
508
509 inline void
510 set_max_size (size_t max_size)
511 {
512 max_size_ = max_size;
513 }
514
515 private:
516 size_t max_size_;
517 };
518};
519
520
521
522template<typename FullKey,
523 typename Payload, typename PayloadTraits = pointer_payload_traits<Payload>,
524 typename policy_traits = lru_policy_traits<FullKey, Payload, PayloadTraits>
525 >
526class indexed_trie
527{
528public:
529 typedef trie< FullKey, Payload, PayloadTraits > parent_trie;
530 typedef typename parent_trie::iterator iterator;
531
532 inline
533 indexed_trie (size_t bucketSize = 10, size_t bucketIncrement = 10)
534 : trie_ ("", bucketSize, bucketIncrement)
535 {
536 }
537
538 inline std::pair< iterator, bool >
539 insert (const FullKey &key, typename PayloadTraits::const_pointer_type payload)
540 {
541 std::pair<iterator, bool> item =
542 trie_.insert (key, payload);
543
544 if (item.second) // real insert
545 {
546 policy_.insert (s_iterator_to (item.first));
547 }
548 else
549 {
550 item.first->set_payload (payload);
551 // policy_traits::update (*item.first);
552 }
553
554 return item;
555 }
556
557 inline void
558 erase (iterator node)
559 {
560 if (node == end ()) return;
561
562 policy_.erase (s_iterator_to (node));
563 node->erase (); // will do cleanup here
564 }
565
566 /**
567 * @brief Perform the longest prefix match
568 * @param key the key for which to perform the longest prefix match
569 *
570 * For subsequent direct searches, policy_.lookup () should be called manually
571 *
572 * @return ->second is true if prefix in ->first is longer than key
573 * ->third is always last node searched
574 */
575 inline boost::tuple< iterator, bool, iterator >
576 find (const FullKey &key)
577 {
578 boost::tuple< iterator, bool, iterator > item = trie_.find (key);
579 if (item.template get<0> () != trie_.end ())
580 {
581 policy_.lookup (s_iterator_to (item.template get<0> ()));
582 }
583 return boost::make_tuple (s_iterator_to (item.template get<0> ()),
584 item.template get<1> (),
585 s_iterator_to (item.template get<2> ()));
586 }
587
588 iterator end ()
589 {
590 return 0;
591 }
592
593 const parent_trie &
594 getTrie () const { return trie_; }
595
596 const typename policy_traits::policy &
597 getPolicy () const { return policy_; }
598
599 typename policy_traits::policy &
600 getPolicy () { return policy_; }
601
602 static inline iterator
603 s_iterator_to (typename parent_trie::iterator item)
604 {
605 if (item == 0)
606 return 0;
607 else
608 return &(*item);
609 }
610
611private:
612 parent_trie trie_;
613 typename policy_traits::policy policy_;
614};
615