20#ifndef KERNEL_UTILITIES_RADIX_TREE_H
21#define KERNEL_UTILITIES_RADIX_TREE_H
23#include "pedigree/kernel/Log.h"
24#include "pedigree/kernel/compiler.h"
25#include "pedigree/kernel/processor/types.h"
26#include "pedigree/kernel/utilities/Cord.h"
27#include "pedigree/kernel/utilities/Iterator.h"
28#include "pedigree/kernel/utilities/ObjectPool.h"
29#include "pedigree/kernel/utilities/Result.h"
30#include "pedigree/kernel/utilities/String.h"
31#include "pedigree/kernel/utilities/Vector.h"
32#include "pedigree/kernel/utilities/utility.h"
59 Node(
bool bCaseSensitive)
64 m_bCaseSensitive(bCaseSensitive),
71 void returnAllChildren();
87 Node* findChild(
const char* cpKey)
const;
90 void addChild(Node* pNode);
93 void replaceChild(Node* pNodeOld, Node* pNodeNew);
96 void removeChild(Node* pChild);
101 MatchType matchKey(
const char* cpKey,
size_t& offset)
const;
104 Node* getFirstChild()
const;
111 void setKey(
const char* cpKey);
113 void setKey(
const char* cpKey,
size_t lengthHint);
116 inline const char* getKey()
const {
119 const String& getKeyStr()
const {
122 inline void setValue(
const T& pV) {
126 inline void removeValue() {
130 inline const T& getValue()
const {
133 inline void setParent(Node* pP) {
136 inline Node* getParent()
const {
139 inline bool hasValue()
const {
143 void dump(
void (*emit_line)(
const char* s))
const;
172 Node* doNext()
const;
176 Node* getNextSibling()
const;
222 template <
typename U = T>
223 typename pedigree_std::enable_if<pedigree_std::is_same<U, T>::value &&
224 !pedigree_std::is_same<U, void*>::value,
228 if (lookup(key, value)) {
229 return LookupType::withValue(value);
231 return LookupType::withError(
true);
243 remove(iterNode->getKeyStr());
254 return Iterator(m_pRoot->hasValue() ? m_pRoot : m_pRoot->next());
262 return ConstIterator(m_pRoot->hasValue() ? m_pRoot : m_pRoot->next());
276 void dump(
void (*emit_line)(
const char* s))
const;
283 Node* p = m_NodePool.allocate(m_bCaseSensitive);
291 p->returnAllChildren();
297 m_NodePool.deallocate(p);
317 : m_nItems(0), m_pRoot(0), m_bCaseSensitive(bCaseSensitive), m_NodePool() {}
327 : m_nItems(0), m_pRoot(0), m_bCaseSensitive(x.m_bCaseSensitive), m_NodePool() {
341 m_pRoot = cloneNode(x.m_pRoot, 0);
342 m_nItems = x.m_nItems;
357 m_pRoot = getNewNode();
362 if (!m_pRoot->hasValue())
364 m_pRoot->setValue(value);
368 Node* pNode = m_pRoot;
370 const char* cpKey =
static_cast<const char*
>(key);
371 const char* cpKeyOrig = cpKey;
372 size_t cpKeyLength = key.length();
375 size_t partialOffset = 0;
376 switch (pNode->
matchKey(cpKey, partialOffset)) {
377 case Node::ExactMatch: {
378 if (!pNode->hasValue()) {
382 pNode->setValue(value);
385 case Node::NoMatch: {
386 FATAL(
"RadixTree: algorithmic error!");
389 case Node::PartialMatch: {
394 size_t i = partialOffset;
396 Node* pInter = getNewNode();
399 pInter->
m_Key.assign(cpKey, partialOffset);
405 size_t len = pNode->
m_Key.length();
411 if (cpKey[partialOffset] != 0) {
412 Node* pChild = getNewNode();
413 pChild->setKey(&cpKey[partialOffset],
414 (cpKeyLength - partialOffset - (cpKey - cpKeyOrig)));
415 pChild->setValue(value);
416 pChild->setParent(pInter);
419 pInter->setValue(value);
422 pInter->setParent(pNode->getParent());
424 pNode->setParent(pInter);
429 case Node::OverMatch: {
430 cpKey += pNode->
m_Key.length();
439 pChild = getNewNode();
440 pChild->setKey(cpKey, cpKeyLength - (cpKey - cpKeyOrig));
441 pChild->setValue(value);
442 pChild->setParent(pNode);
462 if (m_pRoot->hasValue()) {
463 value = m_pRoot->getValue();
469 Node* pNode = m_pRoot;
471 const char* cpKey =
static_cast<const char*
>(key);
475 switch (pNode->
matchKey(cpKey, offset)) {
476 case Node::ExactMatch:
477 if (!pNode->hasValue()) {
483 value = pNode->getValue();
486 case Node::PartialMatch:
488 case Node::OverMatch: {
489 cpKey += pNode->
m_Key.length();
509 m_pRoot = getNewNode();
513 Node* pNode = m_pRoot;
515 const char* cpKey =
static_cast<const char*
>(key);
519 if (!cpKey || (*cpKey == 0)) {
520 if (m_pRoot->hasValue()) {
521 m_pRoot->removeValue();
529 switch (pNode->
matchKey(cpKey, offset)) {
530 case Node::ExactMatch: {
531 if (!pNode->hasValue())
537 pNode->removeValue();
555 pParent = pNode->getParent();
562 if (pNode == m_pRoot)
572 pParent = pNode->getParent();
587 pParent = pNode->getParent();
594 pChild->setParent(pParent);
603 case Node::PartialMatch:
606 case Node::OverMatch: {
607 cpKey += pNode->
m_Key.length();
627 Node* n = getNewNode();
628 n->setKey(pNode->
m_Key);
629 if (pNode->hasValue())
630 n->setValue(pNode->
value);
631 n->setParent(pParent);
644 m_pRoot = getNewNode();
646 m_pRoot->returnAllChildren();
649 m_pRoot->removeValue();
650 m_pRoot->setParent(0);
657 m_pRoot->dump(emit_line);
674 for (
auto it : m_Children) {
675 it->returnAllChildren();
684 for (
auto it : m_Children) {
686 if (it->matchKey(cpKey, offset) != NoMatch) {
696 m_Children.pushBack(pNode);
701 for (
auto it = m_Children.begin(); it != m_Children.end(); ++it) {
702 if (*it == pNodeOld) {
712 it != m_Children.end();) {
713 if ((*it) == pChild) {
714 it = m_Children.erase(it);
722 size_t& offset)
const {
725 if (!m_Key.length()) {
729 const char* myKey = getKey();
739 int r = StringCompareCase(cpKey, myKey,
m_bCaseSensitive, m_Key.length() + 1, &i);
744 }
else if (m_Key[i] == 0) {
760 m_Key.assign(cpKey, lengthHint);
770 return *(m_Children.begin());
775 String tmp = pedigree_std::move(m_Key);
783 Node const* pNode =
this;
784 while ((pNode ==
this) || (pNode && !pNode->hasValue())) {
800 return const_cast<Node*
>(pNode);
810 it != m_pParent->m_Children.end(); ++it) {
822 for (
auto it : m_Children) {
828 s.Format(
" \"Node<%p: %s>\" -> \"Node<%p: %s>\";",
static_cast<const void*
>(it), it->getKey(),
829 static_cast<const void*
>(
this),
static_cast<const char*
>(m_Key));
830 emit_line(
static_cast<const char*
>(s));
An iterator applicable for many data structures.
const bool m_bCaseSensitive
RadixTree * m_pParentTree
@ NoMatch
Key didn't match node key at all.
@ PartialMatch
A subset of key matched the node key.
@ ExactMatch
Key matched node key exactly.
A key/value dictionary for string keys.
Iterator::Const ConstIterator
ConstIterator end() const
const bool m_bCaseSensitive
ObjectPool< Node > m_NodePool
::Iterator< T, Node > Iterator
Iterator erase(Iterator iter)
pedigree_std::enable_if< pedigree_std::is_same< U, T >::value &&!pedigree_std::is_same< U, void * >::value, LookupType >::type lookup(const String &key) const
ConstIterator begin() const
A vector / dynamic array.
void addChild(Node *pNode)
RadixTree(bool bCaseSensitive)
void remove(const String &key)
RadixTree & operator=(const RadixTree &x)
MUST_USE_RESULT bool lookup(const String &key, T &value) const
Node * cloneNode(Node *node, Node *parent)
void insert(const String &key, const T &value)
void removeChild(Node *pChild)
void replaceChild(Node *pNodeOld, Node *pNodeNew)
Node * findChild(const char *cpKey) const
void prependKey(const String &cpKey)
RadixTree(const RadixTree< T > &x)
Node * getFirstChild() const
Node * getNextSibling() const
MatchType matchKey(const char *cpKey, size_t &offset) const
void dump(void(*emit_line)(const char *s)) const