#ifndef _PROTO_TREE
#define _PROTO_TREE
#include "protoList.h"
#include <string.h>
#ifndef _WIN32_WCE
#include <sys/types.h>
#else
#include <types.h>
#endif
class ProtoTree : public ProtoIterable
{
public:
ProtoTree();
virtual ~ProtoTree();
bool IsEmpty() const
{return (NULL == root);}
void Empty();
void Destroy();
class Item;
bool Insert(Item& item);
void Remove(Item& item);
ProtoTree::Item* Find(const char* key, unsigned int keysize) const;
ProtoTree::Item* FindString(const char* keyString) const
{return Find(keyString, (unsigned int)(8*strlen(keyString)));}
ProtoTree::Item* FindClosestMatch(const char* key, unsigned int keysize) const;
ProtoTree::Item* FindPrefix(const char* key, unsigned int keysize) const;
ProtoTree::Item* GetRoot() const {return root;}
ProtoTree::Item* GetFirstItem() const;
ProtoTree::Item* GetLastItem() const;
ProtoTree::Item* RemoveRoot();
class Iterator;
class ItemPool;
enum Endian {ENDIAN_BIG, ENDIAN_LITTLE};
static ProtoTree::Endian GetNativeEndian()
{
#if BYTE_ORDER == LITTLE_ENDIAN
return ProtoTree::ENDIAN_LITTLE;
#else
return ProtoTree::ENDIAN_BIG;
#endif }
class Item : public ProtoIterable::Item
{
friend class ProtoTree;
friend class Iterator;
friend class ItemPool;
public:
Item();
virtual ~Item();
virtual const char* GetKey() const = 0;
virtual unsigned int GetKeysize() const = 0;
#ifdef WIN32
virtual Endian GetEndian() const
{return ENDIAN_BIG;} #else
virtual ProtoTree::Endian GetEndian() const
{return ENDIAN_BIG;} #endif
unsigned int GetDepth() const;
const char* GetKeyText() const
{
static char text[256];
unsigned int tlen = GetKeysize() >> 3;
if (tlen > 255) tlen = 255;
#ifdef WIN32
strncpy_s(text, 256, GetKey(), tlen);
#else
strncpy(text, GetKey(), tlen);
#endif text[tlen] = '\0';
return text;
}
protected:
Item* GetParent() const {return parent;}
Item* GetLeft() const {return left;}
Item* GetRight() const {return right;}
unsigned int GetBit() {return bit;}
bool IsEqual(const char* theKey, unsigned int theKeysize) const;
bool PrefixIsEqual(const char* prefix, unsigned int prefixSize) const;
void SetPoolNext(Item* poolNext) {right = poolNext;}
Item* GetPoolNext() const {return right;}
unsigned int bit;
Item* parent;
Item* left;
Item* right;
};
class ItemPool
{
public:
ItemPool();
virtual ~ItemPool();
void Destroy();
bool IsEmpty() const
{return (NULL == head);}
Item* Get();
void Put(Item& item);
private:
Item* head;
};
class Iterator : public ProtoIterable::Iterator
{
public:
Iterator(ProtoTree& tree,
bool reverse = false,
Item* cursor = NULL);
virtual ~Iterator();
void Reset(bool reverse = false,
const char* prefix = NULL,
unsigned int prefixSize = 0);
void SetCursor(Item& item);
Item* GetPrevItem();
Item* PeekPrevItem();
Item* GetNextItem();
Item* PeekNextItem();
void Update(ProtoIterable::Item* theItem, Action theAction);
bool reversed; unsigned int prefix_size; Item* prefix_item; Item* prev;
Item* next;
Item* curr_hop;
}; friend class Iterator;
class SimpleIterator : public ProtoIterable::Iterator
{
public:
SimpleIterator(ProtoTree& theTree);
virtual ~SimpleIterator();
void Reset();
Item* GetNextItem();
private:
void Update(ProtoIterable::Item* theItem, Action theAction);
Item* next;
};
static bool Bit(const char* key, unsigned int keysize, unsigned int index, Endian keyEndian);
static bool ItemIsEqual(const Item& item, const char* key, unsigned int keysize);
static bool ItemsAreEqual(const Item& item1, const Item& item2);
protected:
ProtoTree::Item* FindPredecessor(ProtoTree::Item& item) const;
ProtoTree::Item* FindPrefixSubtree(const char* prefix,
unsigned int prefixLen) const;
static bool KeysAreEqual(const char* key1,
const char* key2,
unsigned int keysize,
Endian keyEndian);
static bool PrefixIsEqual(const char* key,
unsigned int keysize,
const char* prefix,
unsigned int prefixSize,
Endian keyEndian);
Item* root;
};
template <class ITEM_TYPE>
class ProtoTreeTemplate : public ProtoTree
{
public:
ProtoTreeTemplate() {}
virtual ~ProtoTreeTemplate() {}
bool Insert(ITEM_TYPE& item)
{return ProtoTree::Insert(item);}
void Remove(ITEM_TYPE& item)
{ProtoTree::Remove(item);}
ITEM_TYPE* Find(const char* key, unsigned int keysize) const
{return (static_cast<ITEM_TYPE*>(ProtoTree::Find(key, keysize)));}
ITEM_TYPE* FindString(const char* keyString) const
{return (static_cast<ITEM_TYPE*>(ProtoTree::FindString(keyString)));}
ITEM_TYPE* FindClosestMatch(const char* key, unsigned int keysize) const
{return (static_cast<ITEM_TYPE*>(ProtoTree::FindClosestMatch(key, keysize)));}
ITEM_TYPE* FindPrefix(const char* key, unsigned int keysize) const
{return (static_cast<ITEM_TYPE*>(ProtoTree::FindPrefix(key, keysize)));}
void Destroy()
{ProtoTree::Destroy();}
class Iterator : public ProtoTree::Iterator
{
public:
Iterator(ProtoTreeTemplate& theTree,
bool reverse = false,
Item* cursor = NULL)
: ProtoTree::Iterator(theTree, reverse, cursor) {}
virtual ~Iterator() {}
ITEM_TYPE* GetPrevItem()
{return static_cast<ITEM_TYPE*>(ProtoTree::Iterator::GetPrevItem());}
ITEM_TYPE* PeekPrevItem()
{return static_cast<ITEM_TYPE*>(ProtoTree::Iterator::PeekPrevItem());}
ITEM_TYPE* GetNextItem()
{return static_cast<ITEM_TYPE*>(ProtoTree::Iterator::GetNextItem());}
ITEM_TYPE* PeekNextItem()
{return static_cast<ITEM_TYPE*>(ProtoTree::Iterator::PeekNextItem());}
};
class SimpleIterator : public ProtoTree::SimpleIterator
{
public:
SimpleIterator(ProtoTreeTemplate& theTree)
: ProtoTree::SimpleIterator(theTree) {}
virtual ~SimpleIterator() {}
ITEM_TYPE* GetNextItem()
{return static_cast<ITEM_TYPE*>(ProtoTree::SimpleIterator::GetNextItem());}
};
class ItemPool : public ProtoTree::ItemPool
{
public:
ItemPool() {}
virtual ~ItemPool() {}
void Put(ITEM_TYPE& item)
{ProtoTree::ItemPool::Put(item);}
ITEM_TYPE* Get()
{return static_cast<ITEM_TYPE*>(ProtoTree::ItemPool::Get());}
};
};
class ProtoSortedTree
{
public:
ProtoSortedTree(bool uniqueItemsOnly = false);
virtual ~ProtoSortedTree();
bool IsEmpty() const
{return item_tree.IsEmpty();}
class Iterator;
class ItemPool;
class Item : public ProtoTree::Item, public ProtoList::Item
{
friend class ProtoSortedTree;
friend class Iterator;
friend class ItemPool;
public:
Item();
virtual ~Item();
virtual const char* GetKey() const = 0;
virtual unsigned int GetKeysize() const = 0;
virtual ProtoTree::Endian GetEndian() const
#ifdef WIN32
{return ProtoTree::Item::GetEndian();}
#else
{return ProtoTree::Item::GetEndian();}
#endif
virtual bool UseSignBit() const
{return false;}
virtual bool UseComplement2() const
{return true;}
private:
bool IsInTree() const
{return (NULL != left);}
};
bool Insert(Item& item);
Item* GetHead() const
{return item_list.GetHead();}
Item* RemoveHead()
{
Item* item = GetHead();
if (NULL != item) Remove(*item);
return item;
}
Item* GetTail() const
{return item_list.GetTail();}
Item* GetRoot() const
{return static_cast<Item*>(item_tree.GetRoot());}
Item* Find(const char* key, unsigned int keysize) const
{return item_tree.Find(key, keysize);}
Item* FindString(const char* keyString) const
{return Find(keyString, (unsigned int)(8*strlen(keyString)));}
Item* FindPrefix(const char* key, unsigned int keysize) const
{return item_tree.FindPrefix(key, keysize);}
void Remove(Item& item);
void Empty();
void Destroy();
void Prepend(Item& item);
void Append(Item& item);
protected:
class List : public ProtoListTemplate<Item> {};
public:
class Iterator
{
public:
Iterator(ProtoSortedTree& tree,
bool reverse = false,
const char* keyMin = NULL,
unsigned int keysize = 0);
virtual ~Iterator();
bool HasEmptyTree() const
{return tree.IsEmpty();}
Item* GetNextItem()
{return list_iterator.GetNextItem();}
Item* GetPrevItem()
{return list_iterator.GetPrevItem();}
Item* PeekNextItem()
{return list_iterator.PeekNextItem();}
Item* PeekPrevItem()
{return list_iterator.PeekPrevItem();}
void Reset(bool reverse = false, const char* keyMin = NULL, unsigned int keysize = 0);
void SetCursor(Item* item)
{list_iterator.SetCursor(item);}
Item* GetCursor()
{return list_iterator.PeekNextItem();}
void Reverse()
{list_iterator.Reverse();}
bool IsReversed() const
{return list_iterator.IsReversed();}
private:
class TempItem : public Item
{
public:
TempItem(const char* theKey, unsigned int theKeysize, ProtoTree::Endian keyEndian);
virtual ~TempItem();
const char* GetKey() const {return key;}
unsigned int GetKeysize() const {return keysize;}
ProtoTree::Endian GetEndian() const {return key_endian;}
private:
const char* key;
unsigned int keysize;
ProtoTree::Endian key_endian;
};
ProtoSortedTree& tree;
List::Iterator list_iterator;
}; friend class Iterator;
class ItemPool : public List::ItemPool {};
void EmptyToPool(ItemPool& itemPool);
protected:
class Tree : public ProtoTreeTemplate<Item> {};
bool unique_items_only; Item* positive_min; Tree item_tree;
List item_list;
};
template <class ITEM_TYPE>
class ProtoSortedTreeTemplate : public ProtoSortedTree
{
public:
ProtoSortedTreeTemplate() {}
virtual ~ProtoSortedTreeTemplate() {}
ITEM_TYPE* Find(const char* key, unsigned int keysize) const
{return (static_cast<ITEM_TYPE*>(ProtoSortedTree::Find(key, keysize)));}
ITEM_TYPE* FindPrefix(const char* key, unsigned int keysize) const
{return (static_cast<ITEM_TYPE*>(ProtoSortedTree::FindPrefix(key, keysize)));}
ITEM_TYPE* GetHead() const
{return (static_cast<ITEM_TYPE*>(ProtoSortedTree::GetHead()));}
ITEM_TYPE* GetTail() const
{return (static_cast<ITEM_TYPE*>(ProtoSortedTree::GetTail()));}
ITEM_TYPE* RemoveHead()
{return (static_cast<ITEM_TYPE*>(ProtoSortedTree::RemoveHead()));}
class Iterator : public ProtoSortedTree::Iterator
{
public:
Iterator(ProtoSortedTreeTemplate& theTree,
bool reverse = false,
const char* keyMin = NULL,
unsigned int keysize = 0)
: ProtoSortedTree::Iterator(theTree, reverse, keyMin, keysize) {}
virtual ~Iterator() {}
ITEM_TYPE* GetPrevItem()
{return static_cast<ITEM_TYPE*>(ProtoSortedTree::Iterator::GetPrevItem());}
ITEM_TYPE* PeekPrevItem()
{return static_cast<ITEM_TYPE*>(ProtoSortedTree::Iterator::PeekPrevItem());}
ITEM_TYPE* GetNextItem()
{return static_cast<ITEM_TYPE*>(ProtoSortedTree::Iterator::GetNextItem());}
ITEM_TYPE* PeekNextItem()
{return static_cast<ITEM_TYPE*>(ProtoSortedTree::Iterator::PeekNextItem());}
};
class ItemPool : public ProtoSortedTree::ItemPool
{
public:
ItemPool() {}
virtual ~ItemPool() {}
void Put(ITEM_TYPE& item)
{ProtoSortedTree::ItemPool::Put(item);}
ITEM_TYPE* Get()
{return static_cast<ITEM_TYPE*>(ProtoSortedTree::ItemPool::Get());}
};
};
#endif