29#ifndef __BASE_TRIE_HH__
30#define __BASE_TRIE_HH__
53template <
class Key,
class Value>
57 static_assert(std::is_integral_v<Key>,
"Key has to be an integral type");
73 std::unique_ptr<Node>
kids[2];
127 static const unsigned MaxBits =
sizeof(Key) * 8;
163 const Key msb = 1ULL << (
MaxBits - 1);
164 return orig | (orig >> 1) | msb;
182 if (node->
kids[0] && node->
kids[0]->matches(key))
183 node = node->
kids[0].get();
184 else if (node->
kids[1] && node->
kids[1]->matches(key))
185 node = node->
kids[1].get();
211 Key new_mask = ~(Key)0;
220 while (
goesAfter(&node, node->
kids[0].get(), key, new_mask) ||
225 Key cur_mask = node->
mask;
227 if (cur_mask == new_mask) {
228 assert(!node->
value);
233 for (
unsigned int i = 0;
i < 2;
i++) {
234 auto& kid = node->
kids[
i];
237 auto new_node = std::make_unique<Node>(key, new_mask,
val);
238 new_node->parent = node;
239 kid = std::move(new_node);
248 last_mask = cur_mask;
250 done = ((key & cur_mask) != (kid->key & cur_mask)) ||
251 last_mask == new_mask;
253 cur_mask = last_mask;
256 if (cur_mask == node->
mask)
260 auto new_node = std::make_unique<Node>(key, cur_mask,
nullptr);
261 new_node->parent = node;
262 kid->
parent = new_node.get();
263 new_node->
kids[0] = std::move(kid);
264 kid = std::move(new_node);
267 if (cur_mask == new_mask) {
273 new_node = std::make_unique<Node>(key, new_mask,
val);
274 new_node->parent = kid.get();
275 kid->kids[1] = std::move(new_node);
276 return kid->kids[1].get();
279 panic(
"Reached the end of the Trie insert function!\n");
318 panic(
"Trie: Can't remove root node.\n");
324 node->
kids[0]->parent = parent;
326 if (parent->
kids[0].get() == node)
327 parent->
kids[0] = std::move(node->
kids[0]);
328 else if (parent->
kids[1].get() == node)
329 parent->
kids[1] = std::move(node->
kids[0]);
331 panic(
"Trie: Inconsistent parent/kid relationship.\n");
333 if (parent->
kids[1] && !parent->
kids[0]) {
334 parent->
kids[0] = std::move(parent->
kids[1]);
335 parent->
kids[1] =
nullptr;
378 dump(
const char *title, std::ostream &
os=std::cout)
380 ccprintf(
os,
"**************************************************\n");
381 ccprintf(
os,
"*** Start of Trie: %s\n", title);
382 ccprintf(
os,
"*** (parent, me, key, mask, value pointer)\n");
383 ccprintf(
os,
"**************************************************\n");
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
A trie is a tree-based data structure used for data retrieval.
Handle lookupHandle(Key key)
Method which looks up the Handle corresponding to a particular key.
void dump(const char *title, std::ostream &os=std::cout)
A debugging method which prints the contents of this trie.
bool goesAfter(Node **parent, Node *kid, Key key, Key new_mask)
A utility method which checks whether the key being looked up lies beyond the Node being examined.
Key extendMask(Key orig)
A utility method which extends a mask value one more bit towards the lsb.
static const unsigned MaxBits
Value * remove(Handle handle)
Method to delete a value from the trie.
Handle insert(Key key, unsigned width, Value *val)
Method which inserts a key/value pair into the trie.
Value * lookup(Key key)
Method which looks up the Value corresponding to a particular key.
void clear()
A method which removes all key/value pairs from the trie.
Value * remove(Key key)
Method to lookup a value from the trie and then delete it.
#define panic(...)
This implements a cprintf based panic() function.
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
void ccprintf(cp::Print &print)
std::unique_ptr< Node > kids[2]
Node(Key _key, Key _mask, Value *_val)
void dump(std::ostream &os, int level)