blob: a9772854d330d162aea9a8b7d53fac4cdc0cfe8b [file] [log] [blame]
Alexander Afanasyev9a989702012-06-29 17:44:00 -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#ifndef TRIE_WITH_POLICY_H_
22#define TRIE_WITH_POLICY_H_
23
24#include "trie.h"
25#include "lru-policy.h"
26
27template<typename FullKey,
28 typename Payload,
29 typename PayloadTraits,
30 typename PolicyTraits
31 >
32class trie_with_policy
33{
34public:
35 typedef trie< FullKey, Payload, PayloadTraits, typename PolicyTraits::policy_hook_type > parent_trie;
36 typedef typename parent_trie::iterator iterator;
37
38 inline
39 trie_with_policy (size_t bucketSize = 10, size_t bucketIncrement = 10)
40 : trie_ ("", bucketSize, bucketIncrement)
41 {
42 }
43
44 inline std::pair< iterator, bool >
45 insert (const FullKey &key, typename PayloadTraits::const_pointer_type payload)
46 {
47 std::pair<iterator, bool> item =
48 trie_.insert (key, payload);
49
50 if (item.second) // real insert
51 {
52 policy_.insert (s_iterator_to (item.first));
53 }
54 else
55 {
56 item.first->set_payload (payload);
57 policy_.update (s_iterator_to (item.first));
58 }
59
60 return item;
61 }
62
63 inline void
64 erase (iterator node)
65 {
66 if (node == end ()) return;
67
68 policy_.erase (s_iterator_to (node));
69 node->erase (); // will do cleanup here
70 }
71
72 /**
73 * @brief Find a node that has the longest common prefix with key (FIB/PIT lookup)
74 */
75 inline iterator
76 longest_prefix_match (const FullKey &key)
77 {
78 boost::tuple< iterator, bool, iterator > item = trie_.find (key);
79 if (item.template get<0> () != trie_.end ())
80 {
81 policy_.lookup (s_iterator_to (item.template get<0> ()));
82 }
83 return item.template get<0> ();
84 }
85
86 /**
87 * @brief Find a node that has prefix at least as the key (cache lookup)
88 */
89 inline iterator
90 deepest_prefix_match (const FullKey &key)
91 {
92 iterator foundItem, lastItem;
93 bool reachLast;
94 boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
95
96 // guard in case we don't have anything in the trie
97 if (lastItem == trie_.end ())
98 return trie_.end ();
99
100 if (reachLast)
101 {
102 if (foundItem == trie_.end ())
103 {
104 foundItem = lastItem->find (); // should be something
105 }
106 policy_.lookup (s_iterator_to (foundItem));
107 return foundItem;
108 }
109 else
110 { // couldn't find a node that has prefix at least as key
111 return trie_.end ();
112 }
113 }
114
115 /**
116 * @brief Find a node that has prefix at least as the key
117 */
118 template<class Predicate>
119 inline iterator
120 deepest_prefix_match (const FullKey &key, Predicate pred)
121 {
122 iterator foundItem, lastItem;
123 bool reachLast;
124 boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
125
126 // guard in case we don't have anything in the trie
127 if (lastItem == trie_.end ())
128 return trie_.end ();
129
130 if (reachLast)
131 {
132 foundItem = lastItem->find_if (pred); // may or may not find something
133 if (foundItem == trie_.end ())
134 {
135 return trie_.end ();
136 }
137 policy_.lookup (s_iterator_to (foundItem));
138 return foundItem;
139 }
140 else
141 { // couldn't find a node that has prefix at least as key
142 return trie_.end ();
143 }
144 }
145
146 // /**
147 // * @brief Perform the longest prefix match
148 // * @param key the key for which to perform the longest prefix match
149 // *
150 // * @return ->second is true if prefix in ->first is longer than key
151 // * ->third is always last node searched
152 // */
153 // inline boost::tuple< iterator, bool, iterator >
154 // find (const FullKey &key)
155 // {
156 // boost::tuple< iterator, bool, iterator > item = trie_.find (key);
157 // if (item.template get<0> () != trie_.end ())
158 // {
159 // policy_.lookup (s_iterator_to (item.template get<0> ()));
160 // }
161 // return boost::make_tuple (s_iterator_to (item.template get<0> ()),
162 // item.template get<1> (),
163 // s_iterator_to (item.template get<2> ()));
164 // }
165
166 // /**
167 // * @brief Find next payload of the sub-trie
168 // * @param start Start for the search (root for the sub-trie)
169 // * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
170 // */
171 // inline iterator
172 // find (iterator start)
173 // {
174 // iterator item = start->find ();
175 // if (item != trie_.end ())
176 // {
177 // policy_.lookup (s_iterator_to (item));
178 // }
179 // return item;
180 // }
181
182 // /**
183 // * @brief Find next payload of the sub-trie satisfying the predicate
184 // * @param start Start for the search (root for the sub-trie)
185 // * @param pred predicate
186 // * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
187 // */
188 // template<class Predicate>
189 // inline iterator
190 // find_if (iterator start, Predicate pred)
191 // {
192 // iterator item = start->find (pred);
193 // if (item != trie_.end ())
194 // {
195 // policy_.lookup (s_iterator_to (item));
196 // }
197 // return item;
198 // }
199
200 iterator end ()
201 {
202 return 0;
203 }
204
205 const parent_trie &
206 getTrie () const { return trie_; }
207
208 const typename PolicyTraits::policy &
209 getPolicy () const { return policy_; }
210
211 typename PolicyTraits::policy &
212 getPolicy () { return policy_; }
213
214 static inline iterator
215 s_iterator_to (typename parent_trie::iterator item)
216 {
217 if (item == 0)
218 return 0;
219 else
220 return &(*item);
221 }
222
223private:
224 parent_trie trie_;
225 typename PolicyTraits::policy policy_;
226};
227
228
229#endif // TRIE_WITH_POLICY_H_
230