blob: 9ca8a28da321c5db7f92640036c7b8c35d912499 [file] [log] [blame]
Alexander Afanasyev60a7b622014-12-20 17:04:07 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2011-2015 Regents of the University of California.
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -07004 *
Alexander Afanasyev60a7b622014-12-20 17:04:07 -08005 * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
6 * contributors.
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -07007 *
Alexander Afanasyev60a7b622014-12-20 17:04:07 -08008 * ndnSIM is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070011 *
Alexander Afanasyev60a7b622014-12-20 17:04:07 -080012 * ndnSIM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070015 *
Alexander Afanasyev60a7b622014-12-20 17:04:07 -080016 * You should have received a copy of the GNU General Public License along with
17 * ndnSIM, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 **/
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070019
Alexander Afanasyev9a989702012-06-29 17:44:00 -070020#ifndef TRIE_H_
21#define TRIE_H_
22
Spyridon Mastorakis53e922f2014-10-17 17:29:26 -070023#include "ns3/ndnSIM/model/ndn-common.hpp"
24
Alexander Afanasyev9a989702012-06-29 17:44:00 -070025#include "ns3/ptr.h"
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070026
27#include <boost/intrusive/unordered_set.hpp>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070028#include <boost/intrusive/list.hpp>
Alexander Afanasyev9a989702012-06-29 17:44:00 -070029#include <boost/intrusive/set.hpp>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070030#include <boost/functional/hash.hpp>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070031#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
Alexander Afanasyev07179012014-12-21 00:23:04 -080032#include <tuple>
Alexander Afanasyev78057c32012-07-06 15:18:46 -070033#include <boost/foreach.hpp>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -070034#include <boost/mpl/if.hpp>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070035
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070036namespace ns3 {
37namespace ndn {
38namespace ndnSIM {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070039
40/////////////////////////////////////////////////////
41// Allow customization for payload
42//
Alexander Afanasyev8566f452012-12-10 15:21:51 -080043template<typename Payload, typename BasePayload = Payload>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080044struct pointer_payload_traits {
45 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
Alexander Afanasyev0845c092012-07-13 17:45:33 -070048
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080049 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 Afanasyevbe55cf62014-12-20 17:51:09 -080052 typedef BasePayload*
53 base_type; // base type of the entry (when implementation details need to be hidden)
54 typedef const BasePayload*
55 const_base_type; // const base type of the entry (when implementation details need to be hidden)
Alexander Afanasyeveec66292013-02-06 16:23:21 -080056
Alexander Afanasyev78057c32012-07-06 15:18:46 -070057 static Payload* empty_payload;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070058};
59
Alexander Afanasyev8566f452012-12-10 15:21:51 -080060template<typename Payload, typename BasePayload>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080061Payload* pointer_payload_traits<Payload, BasePayload>::empty_payload = 0;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070062
Alexander Afanasyev8566f452012-12-10 15:21:51 -080063template<typename Payload, typename BasePayload = Payload>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080064struct smart_pointer_payload_traits {
65 typedef Payload payload_type;
66 typedef ns3::Ptr<Payload> storage_type;
67 typedef ns3::Ptr<Payload> insert_type;
Alexander Afanasyeveec66292013-02-06 16:23:21 -080068
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080069 typedef ns3::Ptr<Payload> return_type;
Alexander Afanasyev0845c092012-07-13 17:45:33 -070070 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 Afanasyevbe55cf62014-12-20 17:51:09 -080079ns3::Ptr<Payload> smart_pointer_payload_traits<Payload, BasePayload>::empty_payload = 0;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070080
Alexander Afanasyev8566f452012-12-10 15:21:51 -080081template<typename Payload, typename BasePayload = Payload>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080082struct non_pointer_traits {
83 typedef Payload payload_type;
84 typedef Payload storage_type;
85 typedef const Payload& insert_type; // nothing to insert
Alexander Afanasyev0845c092012-07-13 17:45:33 -070086
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080087 typedef Payload& return_type;
88 typedef const Payload& const_return_type;
Alexander Afanasyeveec66292013-02-06 16:23:21 -080089
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080090 typedef BasePayload& base_type;
Alexander Afanasyev62304f22012-12-10 18:06:21 -080091 typedef const BasePayload& const_base_type;
Alexander Afanasyeveec66292013-02-06 16:23:21 -080092
Alexander Afanasyev0845c092012-07-13 17:45:33 -070093 static Payload empty_payload;
94};
95
Alexander Afanasyev8566f452012-12-10 15:21:51 -080096template<typename Payload, typename BasePayload>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080097Payload non_pointer_traits<Payload, BasePayload>::empty_payload = Payload();
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070098
99////////////////////////////////////////////////////
100// forward declarations
101//
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800102template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800103class trie;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700104
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700105template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700106inline std::ostream&
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800107operator<<(std::ostream& os, const trie<FullKey, PayloadTraits, PolicyHook>& trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700108
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700109template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700110bool
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800111operator==(const trie<FullKey, PayloadTraits, PolicyHook>& a,
112 const trie<FullKey, PayloadTraits, PolicyHook>& b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700113
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800114template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700115std::size_t
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800116hash_value(const trie<FullKey, PayloadTraits, PolicyHook>& trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700117
118///////////////////////////////////////////////////
119// actual definition
120//
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700121template<class T, class NonConstT>
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700122class trie_iterator;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700123
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700124template<class T>
125class trie_point_iterator;
126
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800127template<typename FullKey, typename PayloadTraits, typename PolicyHook>
128class trie {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700129public:
Spyridon Mastorakis1f1cd5e2014-12-04 11:12:40 -0800130 typedef typename FullKey::value_type Key;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700131
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800132 typedef trie* iterator;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700133 typedef const trie* const_iterator;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700134
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700135 typedef trie_iterator<trie, trie> recursive_iterator;
136 typedef trie_iterator<const trie, trie> const_recursive_iterator;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700137
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700138 typedef trie_point_iterator<trie> point_iterator;
139 typedef trie_point_iterator<const trie> const_point_iterator;
140
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700141 typedef PayloadTraits payload_traits;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800142
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800143 inline trie(const Key& key, size_t bucketSize = 1, size_t bucketIncrement = 1)
144 : key_(key)
145 , initialBucketSize_(bucketSize)
146 , bucketIncrement_(bucketIncrement)
147 , bucketSize_(initialBucketSize_)
148 , buckets_(new bucket_type[bucketSize_]) // cannot use normal pointer, because lifetime of
149 // buckets should be larger than lifetime of the
150 // container
151 , children_(bucket_traits(buckets_.get(), bucketSize_))
152 , payload_(PayloadTraits::empty_payload)
153 , parent_(0)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700154 {
155 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700156
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800157 inline ~trie()
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700158 {
159 payload_ = PayloadTraits::empty_payload; // necessary for smart pointers...
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800160 children_.clear_and_dispose(trie_delete_disposer());
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700161 }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700162
163 void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800164 clear()
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700165 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800166 children_.clear_and_dispose(trie_delete_disposer());
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700167 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700168
169 template<class Predicate>
170 void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800171 clear_if(Predicate cond)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700172 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800173 recursive_iterator trieNode(this);
174 recursive_iterator end(0);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700175
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800176 while (trieNode != end) {
177 if (cond(*trieNode)) {
178 trieNode = recursive_iterator(trieNode->erase());
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700179 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800180 trieNode++;
181 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700182 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800183
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700184 // actual entry
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800185 friend bool operator==<>(const trie<FullKey, PayloadTraits, PolicyHook>& a,
186 const trie<FullKey, PayloadTraits, PolicyHook>& b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700187
188 friend std::size_t
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800189 hash_value<>(const trie<FullKey, PayloadTraits, PolicyHook>& trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700190
191 inline std::pair<iterator, bool>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800192 insert(const FullKey& key, typename PayloadTraits::insert_type payload)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700193 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800194 trie* trieNode = this;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800195
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800196 BOOST_FOREACH (const Key& subkey, key) {
197 typename unordered_set::iterator item = trieNode->children_.find(subkey);
198 if (item == trieNode->children_.end()) {
199 trie* newNode = new trie(subkey, initialBucketSize_, bucketIncrement_);
200 // std::cout << "new " << newNode << "\n";
201 newNode->parent_ = trieNode;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700202
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800203 if (trieNode->children_.size() >= trieNode->bucketSize_) {
204 trieNode->bucketSize_ += trieNode->bucketIncrement_;
205 trieNode->bucketIncrement_ *= 2; // increase bucketIncrement exponentially
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800206
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800207 buckets_array newBuckets(new bucket_type[trieNode->bucketSize_]);
208 trieNode->children_.rehash(bucket_traits(newBuckets.get(), trieNode->bucketSize_));
209 trieNode->buckets_.swap(newBuckets);
210 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800211
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800212 std::pair<typename unordered_set::iterator, bool> ret =
213 trieNode->children_.insert(*newNode);
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800214
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800215 trieNode = &(*ret.first);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700216 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800217 else
218 trieNode = &(*item);
219 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700220
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800221 if (trieNode->payload_ == PayloadTraits::empty_payload) {
222 trieNode->payload_ = payload;
223 return std::make_pair(trieNode, true);
224 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700225 else
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800226 return std::make_pair(trieNode, false);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700227 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700228
229 /**
230 * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
231 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700232 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800233 erase()
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700234 {
235 payload_ = PayloadTraits::empty_payload;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800236 return prune();
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700237 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700238
239 /**
240 * @brief Do exactly as erase, but without erasing the payload
241 */
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700242 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800243 prune()
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700244 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800245 if (payload_ == PayloadTraits::empty_payload && children_.size() == 0) {
246 if (parent_ == 0)
247 return this;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700248
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800249 trie* parent = parent_;
250 parent->children_
251 .erase_and_dispose(*this,
252 trie_delete_disposer()); // delete this; basically, committing a suicide
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700253
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800254 return parent->prune();
255 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700256 return this;
257 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700258
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700259 /**
260 * @brief Perform prune of the node, but without attempting to parent of the node
261 */
262 inline void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800263 prune_node()
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700264 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800265 if (payload_ == PayloadTraits::empty_payload && children_.size() == 0) {
266 if (parent_ == 0)
267 return;
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700268
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800269 trie* parent = parent_;
270 parent->children_
271 .erase_and_dispose(*this,
272 trie_delete_disposer()); // delete this; basically, committing a suicide
273 }
Alexander Afanasyev70426a02012-08-15 15:39:18 -0700274 }
275
Alexander Afanasyev07179012014-12-21 00:23:04 -0800276 // inline std::tuple<const iterator, bool, const iterator>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700277 // find (const FullKey &key) const
278 // {
279 // return const_cast<trie*> (this)->find (key);
280 // }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700281
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700282 /**
283 * @brief Perform the longest prefix match
284 * @param key the key for which to perform the longest prefix match
285 *
286 * @return ->second is true if prefix in ->first is longer than key
287 */
Alexander Afanasyev07179012014-12-21 00:23:04 -0800288 inline std::tuple<iterator, bool, iterator>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800289 find(const FullKey& key)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700290 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800291 trie* trieNode = this;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700292 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
293 bool reachLast = true;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800294
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800295 BOOST_FOREACH (const Key& subkey, key) {
296 typename unordered_set::iterator item = trieNode->children_.find(subkey);
297 if (item == trieNode->children_.end()) {
298 reachLast = false;
299 break;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700300 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800301 else {
302 trieNode = &(*item);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700303
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800304 if (trieNode->payload_ != PayloadTraits::empty_payload)
305 foundNode = trieNode;
306 }
307 }
308
Alexander Afanasyev07179012014-12-21 00:23:04 -0800309 return std::make_tuple(foundNode, reachLast, trieNode);
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800310 }
311
312 /**
313 * @brief Perform the longest prefix match satisfying preficate
314 * @param key the key for which to perform the longest prefix match
315 *
316 * @return ->second is true if prefix in ->first is longer than key
317 */
318 template<class Predicate>
Alexander Afanasyev07179012014-12-21 00:23:04 -0800319 inline std::tuple<iterator, bool, iterator>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800320 find_if(const FullKey& key, Predicate pred)
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800321 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800322 trie* trieNode = this;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800323 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
324 bool reachLast = true;
325
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800326 BOOST_FOREACH (const Key& subkey, key) {
327 typename unordered_set::iterator item = trieNode->children_.find(subkey);
328 if (item == trieNode->children_.end()) {
329 reachLast = false;
330 break;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800331 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800332 else {
333 trieNode = &(*item);
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800334
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800335 if (trieNode->payload_ != PayloadTraits::empty_payload && pred(trieNode->payload_)) {
336 foundNode = trieNode;
337 }
338 }
339 }
340
Alexander Afanasyev07179012014-12-21 00:23:04 -0800341 return std::make_tuple(foundNode, reachLast, trieNode);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700342 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700343
344 /**
345 * @brief Find next payload of the sub-trie
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800346 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration
347 * )
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700348 */
349 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800350 find()
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700351 {
352 if (payload_ != PayloadTraits::empty_payload)
353 return this;
354
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700355 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800356 for (typename trie::unordered_set::iterator subnode = children_.begin();
357 subnode != children_.end(); subnode++)
358 // BOOST_FOREACH (trie &subnode, children_)
359 {
360 iterator value = subnode->find();
361 if (value != 0)
362 return value;
363 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800364
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700365 return 0;
366 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700367
368 /**
369 * @brief Find next payload of the sub-trie satisfying the predicate
370 * @param pred predicate
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800371 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration
372 * )
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700373 */
374 template<class Predicate>
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700375 inline const iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800376 find_if(Predicate pred)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700377 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800378 if (payload_ != PayloadTraits::empty_payload && pred(payload_))
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700379 return this;
380
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700381 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800382 for (typename trie::unordered_set::iterator subnode = children_.begin();
383 subnode != children_.end(); subnode++)
384 // BOOST_FOREACH (const trie &subnode, children_)
385 {
386 iterator value = subnode->find_if(pred);
387 if (value != 0)
388 return value;
389 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800390
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700391 return 0;
392 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700393
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700394 /**
395 * @brief Find next payload of the sub-trie satisfying the predicate
396 * @param pred predicate
397 *
398 * This version check predicate only for the next level children
399 *
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800400 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration
401 *)
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700402 */
403 template<class Predicate>
404 inline const iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800405 find_if_next_level(Predicate pred)
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700406 {
407 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800408 for (typename trie::unordered_set::iterator subnode = children_.begin();
409 subnode != children_.end(); subnode++) {
410 if (pred(subnode->key())) {
411 return subnode->find();
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700412 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800413 }
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700414
415 return 0;
416 }
417
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800418 iterator
419 end()
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700420 {
421 return 0;
422 }
423
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800424 const_iterator
425 end() const
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700426 {
427 return 0;
428 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700429
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700430 typename PayloadTraits::const_return_type
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800431 payload() const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700432 {
433 return payload_;
434 }
435
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700436 typename PayloadTraits::return_type
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800437 payload()
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700438 {
439 return payload_;
440 }
441
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700442 void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800443 set_payload(typename PayloadTraits::insert_type payload)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700444 {
445 payload_ = payload;
446 }
Alexander Afanasyev0560eec2012-07-16 15:44:31 -0700447
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800448 Key
449 key() const
Alexander Afanasyev0560eec2012-07-16 15:44:31 -0700450 {
451 return key_;
452 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800453
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700454 inline void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800455 PrintStat(std::ostream& os) const;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800456
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700457private:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800458 // The disposer object function
459 struct trie_delete_disposer {
460 void
461 operator()(trie* delete_this)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700462 {
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700463 delete delete_this;
464 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700465 };
466
467 template<class D>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800468 struct array_disposer {
469 void
470 operator()(D* array)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700471 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800472 delete[] array;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700473 }
474 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700475
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800476 friend std::ostream& operator<<<>(std::ostream& os, const trie& trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700477
478public:
479 PolicyHook policy_hook_;
480
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700481private:
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700482 boost::intrusive::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700483
484 // necessary typedefs
485 typedef trie self_type;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800486 typedef boost::intrusive::member_hook<trie, boost::intrusive::unordered_set_member_hook<>,
487 &trie::unordered_set_member_hook_> member_hook;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700488
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800489 typedef boost::intrusive::unordered_set<trie, member_hook> unordered_set;
490 typedef typename unordered_set::bucket_type bucket_type;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700491 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 Afanasyevbe55cf62014-12-20 17:51:09 -0800509 typedef boost::interprocess::unique_ptr<bucket_type, array_disposer<bucket_type>> buckets_array;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700510 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 Afanasyevbe55cf62014-12-20 17:51:09 -0800514 trie* parent_; // to make cleaning effective
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700515};
516
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700517template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700518inline std::ostream&
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800519operator<<(std::ostream& os, const trie<FullKey, PayloadTraits, PolicyHook>& trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700520{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800521 os << "# " << trie_node.key_ << ((trie_node.payload_ != PayloadTraits::empty_payload) ? "*" : "")
522 << std::endl;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700523 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700524
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800525 for (typename trie::unordered_set::const_iterator subnode = trie_node.children_.begin();
526 subnode != trie_node.children_.end(); subnode++)
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700527 // BOOST_FOREACH (const trie &subnode, trie_node.children_)
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800528 {
529 os << "\"" << &trie_node << "\""
530 << " [label=\"" << trie_node.key_
531 << ((trie_node.payload_ != PayloadTraits::empty_payload) ? "*" : "") << "\"]\n";
532 os << "\"" << &(*subnode) << "\""
533 << " [label=\"" << subnode->key_
534 << ((subnode->payload_ != PayloadTraits::empty_payload) ? "*" : "") << "\"]"
535 "\n";
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800536
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800537 os << "\"" << &trie_node << "\""
538 << " -> "
539 << "\"" << &(*subnode) << "\""
540 << "\n";
541 os << *subnode;
542 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700543
544 return os;
545}
546
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700547template<typename FullKey, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700548inline void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800549trie<FullKey, PayloadTraits, PolicyHook>::PrintStat(std::ostream& os) const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700550{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800551 os << "# " << key_ << ((payload_ != PayloadTraits::empty_payload) ? "*" : "") << ": "
552 << children_.size() << " children" << std::endl;
553 for (size_t bucket = 0, maxbucket = children_.bucket_count(); bucket < maxbucket; bucket++) {
554 os << " " << children_.bucket_size(bucket);
555 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700556 os << "\n";
557
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700558 typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800559 for (typename trie::unordered_set::const_iterator subnode = children_.begin();
560 subnode != children_.end(); subnode++)
Alexander Afanasyev051d3782012-07-03 10:10:15 -0700561 // BOOST_FOREACH (const trie &subnode, children_)
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800562 {
563 subnode->PrintStat(os);
564 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700565}
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 Afanasyevbe55cf62014-12-20 17:51:09 -0800569operator==(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 Afanasyevbe55cf62014-12-20 17:51:09 -0800577hash_value(const trie<FullKey, PayloadTraits, PolicyHook>& trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700578{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800579 return boost::hash_value(trie_node.key_);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700580}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700581
Alexander Afanasyev1cb4aad2012-08-09 14:58:16 -0700582template<class Trie, class NonConstTrie> // hack for boost < 1.47
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800583class trie_iterator {
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700584public:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800585 trie_iterator()
586 : trie_(0)
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700587 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800588 }
589 trie_iterator(typename Trie::iterator item)
590 : trie_(item)
591 {
592 }
593 trie_iterator(Trie& item)
594 : trie_(&item)
595 {
596 }
597
598 Trie& operator*()
599 {
600 return *trie_;
601 }
602 const Trie& operator*() const
603 {
604 return *trie_;
605 }
606 Trie* operator->()
607 {
608 return trie_;
609 }
610 const Trie* operator->() const
611 {
612 return trie_;
613 }
614 bool
615 operator==(trie_iterator<const Trie, NonConstTrie>& other) const
616 {
617 return (trie_ == other.trie_);
618 }
619 bool
620 operator==(trie_iterator<Trie, NonConstTrie>& other)
621 {
622 return (trie_ == other.trie_);
623 }
624 bool
625 operator!=(trie_iterator<const Trie, NonConstTrie>& other) const
626 {
627 return !(*this == other);
628 }
629 bool
630 operator!=(trie_iterator<Trie, NonConstTrie>& other)
631 {
632 return !(*this == other);
633 }
634
635 trie_iterator<Trie, NonConstTrie>&
636 operator++(int)
637 {
638 if (trie_->children_.size() > 0)
639 trie_ = &(*trie_->children_.begin());
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700640 else
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800641 trie_ = goUp();
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700642 return *this;
643 }
644
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800645 trie_iterator<Trie, NonConstTrie>&
646 operator++()
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700647 {
648 (*this)++;
649 return *this;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800650 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700651
652private:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800653 typedef typename boost::mpl::if_<boost::is_same<Trie, NonConstTrie>,
654 typename Trie::unordered_set::iterator,
655 typename Trie::unordered_set::const_iterator>::type set_iterator;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800656
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800657 Trie*
658 goUp()
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700659 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800660 if (trie_->parent_ != 0) {
661 // typename Trie::unordered_set::iterator item =
662 set_iterator item = const_cast<NonConstTrie*>(trie_)
663 ->parent_->children_.iterator_to(const_cast<NonConstTrie&>(*trie_));
664 item++;
665 if (item != trie_->parent_->children_.end()) {
666 return &(*item);
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700667 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800668 else {
669 trie_ = trie_->parent_;
670 return goUp();
671 }
672 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700673 else
674 return 0;
675 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800676
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700677private:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800678 Trie* trie_;
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700679};
680
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700681template<class Trie>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800682class trie_point_iterator {
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800683private:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800684 typedef typename boost::mpl::if_<boost::is_same<Trie, const Trie>,
685 typename Trie::unordered_set::const_iterator,
686 typename Trie::unordered_set::iterator>::type set_iterator;
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700687
688public:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800689 trie_point_iterator()
690 : trie_(0)
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700691 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800692 }
693 trie_point_iterator(typename Trie::iterator item)
694 : trie_(item)
695 {
696 }
697 trie_point_iterator(Trie& item)
698 {
699 if (item.children_.size() != 0)
700 trie_ = &*item.children_.begin();
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700701 else
702 trie_ = 0;
703 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800704
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800705 Trie& operator*()
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700706 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800707 return *trie_;
708 }
709 const Trie& operator*() const
710 {
711 return *trie_;
712 }
713 Trie* operator->()
714 {
715 return trie_;
716 }
717 const Trie* operator->() const
718 {
719 return trie_;
720 }
721 bool
722 operator==(trie_point_iterator<const Trie>& other) const
723 {
724 return (trie_ == other.trie_);
725 }
726 bool
727 operator==(trie_point_iterator<Trie>& other)
728 {
729 return (trie_ == other.trie_);
730 }
731 bool
732 operator!=(trie_point_iterator<const Trie>& other) const
733 {
734 return !(*this == other);
735 }
736 bool
737 operator!=(trie_point_iterator<Trie>& other)
738 {
739 return !(*this == other);
740 }
741
742 trie_point_iterator<Trie>&
743 operator++(int)
744 {
745 if (trie_->parent_ != 0) {
746 set_iterator item = trie_->parent_->children_.iterator_to(*trie_);
747 item++;
748 if (item == trie_->parent_->children_.end())
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700749 trie_ = 0;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800750 else
751 trie_ = &*item;
752 }
753 else {
754 trie_ = 0;
755 }
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700756 return *this;
757 }
758
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800759 trie_point_iterator<Trie>&
760 operator++()
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700761 {
762 (*this)++;
763 return *this;
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800764 }
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700765
766private:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800767 Trie* trie_;
Alexander Afanasyev0845c092012-07-13 17:45:33 -0700768};
769
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700770} // ndnSIM
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700771} // ndn
Alexander Afanasyeve77db792012-08-09 11:10:58 -0700772} // ns3
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700773
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700774#endif // TRIE_H_