All pastes #606724 Raw Edit

Something

public text v1 · immutable
·published 2007-07-07 01:33 UTC
rendered paste body
#if !defined(DICT_H)
#define DICT_H

#ifndef NULL
#include <cstdio>
#endif

#ifndef _strcmpi
#include <cstring>
#endif

template <class DataType> class Dict;
typedef void (*delete_t)(void*);

template <class DataType>
class DictNode {
	friend class Dict<DataType>;
private:
	DataType Data;
	DictNode *LeftNode, *RightNode;
	DictNode *PrevNode, *NextNode;

public:
	const char *Key;

	DictNode(const char *NodeKey, DataType NodeData) : Key(NodeKey), Data(NodeData) {
		NextNode = PrevNode = NULL;
		LeftNode = RightNode = NULL;
	}

	~DictNode(void) {
		Key = NULL;
		Data = NULL;
	}
};

template <class DataType>
class Dict {
private:
	unsigned long DictSize;
	bool FreeKey, FreeData;
	delete_t DeleteKey, DeleteData;
	DictNode<DataType> *RootNode, *FirstNode, *LastNode;

	static DictNode<DataType> *SplayTree(DictNode<DataType> *Node, const char *Key) {
		DictNode<DataType> Stack(NULL, NULL);
		DictNode<DataType> *Left, *Right, *Up;

		if (!Node) return NULL;
		Left = Right = &Stack;

		int res;
		for (;;) {
		if (!(res = _strcmpi(Key, Node->Key)))
			break;
		if (res < 0) {
			if (!Node->LeftNode) break;
			res = _strcmpi(Key, Node->LeftNode->Key);
			if (res < 0) {
				Up = Node->LeftNode;
				Node->LeftNode = Up->RightNode;
				Up->RightNode = Node;
				Node = Up;
				if (!Node->LeftNode) break;
			}
			Right->LeftNode = Node;
			Right = Node;
			Node = Node->LeftNode;
		} else {
			if (!Node->RightNode) break;
			if ((res = _strcmpi(Key, Node->RightNode->Key)) > 0) {
				Up = Node->RightNode;
				Node->RightNode = Up->LeftNode;
				Up->LeftNode = Node;
				Node = Up;
				if (!Node->RightNode) break;
			}
			Left->RightNode = Node;
			Left = Node;
			Node = Node->RightNode;
		}
		}
		Left->RightNode = Node->LeftNode;
		Right->LeftNode = Node->RightNode;
		Node->LeftNode = Stack.RightNode;
		Node->RightNode = Stack.LeftNode;
		return Node;
	}

	inline void DeleteNode(DictNode<DataType> *Node) {
		if (Node->Key && FreeKey) {
			if (DeleteKey) {
				DeleteKey((void*)Node->Key);
			} else {
				delete[] Node->Key;
			}
		}
		if (Node->Data && FreeData) {
			if (DeleteData) {
				DeleteData((void*)Node->Data);
			} else {
				delete[] Node->Data;
			}
		}
		delete Node;
	}

public:
	Dict(bool FreeKeys, bool FreeDatas) : DictSize(0), FreeKey(FreeKeys), FreeData(FreeDatas) {
		DeleteKey = DeleteData = NULL;
		FirstNode = LastNode = RootNode = NULL;
	}

	~Dict(void) {
		DictDelete();
	}

	inline void SetDeleteKey(delete_t DeleteKeyF) {
		DeleteKey = DeleteKeyF;
	}

	inline void SetDeleteData(delete_t DeleteDataF) {
		DeleteData = DeleteDataF;
	}

	inline unsigned long Size(void) {
		return DictSize;
	}

	inline const char *ForEach(int (*comparator)(const char *, DataType, void *), void *Extra) {
		DictNode<DataType> *Node = FirstNode;

		while (Node) {
			if (comparator(Node->Key, Node->Data, Extra))
				return Node->Key;
			Node = Node->NextNode;
		}
		return NULL;
	}

	inline DataType ForEachData(int (*comparator)(const char *, DataType, void *), void *Extra) {
		DictNode<DataType> *Node = FirstNode;
	
		while (Node) {
			if (comparator(Node->Key, Node->Data, Extra))
				return Node->Data;
			Node = Node->NextNode;
		}
		return NULL;
	}

	void InsertNode(const char *Key, DataType Data) {
		DictNode<DataType> *NewNode = new DictNode<DataType>(Key, Data);

		if (!Key) {
			delete NewNode;
			return;
		}
		if (RootNode) {
		RootNode = SplayTree(RootNode, Key);
		int res = _strcmpi(Key, RootNode->Key);
		if (res < 0) {
			NewNode->LeftNode = RootNode->LeftNode;
			NewNode->RightNode = RootNode;
			RootNode->LeftNode = NULL;
			if (RootNode->PrevNode) {
				RootNode->PrevNode->NextNode = NewNode;
			} else {
				FirstNode = NewNode;
			}
			NewNode->PrevNode = RootNode->PrevNode;
			NewNode->NextNode = RootNode;
			RootNode->PrevNode = NewNode;
			RootNode = NewNode;
		} else if (res > 0) {
			NewNode->RightNode = RootNode->RightNode;
			NewNode->LeftNode = RootNode;
			RootNode->RightNode = NULL;
			if (RootNode->NextNode) {
				RootNode->NextNode->PrevNode = NewNode;
			} else {
				LastNode = NewNode;
			}
			NewNode->NextNode = RootNode->NextNode;
			NewNode->PrevNode = RootNode;
			RootNode->NextNode = NewNode;
			RootNode = NewNode;
		} else {
			if (FreeData) {
				if (DeleteData) {
					DeleteData((void*)RootNode->Data);
				} else {
					delete[] RootNode->Data;
				}
			}
			if (FreeKey) {
				if (DeleteKey) {
					DeleteKey((void*)RootNode->Key);
				} else {
					delete[] RootNode->Key;
				}
			}
			delete NewNode;
			RootNode->Data = Data;
			RootNode->Key = Key;
			DictSize--;
		}
		} else {
			NewNode->LeftNode = NewNode->RightNode = NULL;
			NewNode->NextNode = NewNode->PrevNode = NULL;
			RootNode = FirstNode = LastNode = NewNode;
		}
		DictSize++;
	}

	bool RemoveNode(const char *Key) {
		DictNode<DataType> *NewRoot, *OldRoot;

		if (!RootNode) return false;
		RootNode = SplayTree(RootNode, Key);
		if (_strcmpi(Key, RootNode->Key))
			return false;

		if (!RootNode->LeftNode) {
			NewRoot = RootNode->RightNode;
		} else {
			NewRoot = SplayTree(RootNode->LeftNode, Key);
			NewRoot->RightNode = RootNode->RightNode;
		}
		if (RootNode->PrevNode) RootNode->PrevNode->NextNode = RootNode->NextNode;
		if (RootNode == FirstNode) FirstNode = FirstNode->NextNode;
		if (RootNode->NextNode) RootNode->NextNode->PrevNode = RootNode->PrevNode;
		if (RootNode == LastNode) LastNode = LastNode->PrevNode;
		OldRoot = RootNode;
		RootNode = NewRoot;
		DeleteNode(OldRoot);
		DictSize--;
		return true;
	}

	inline DataType FindNode(const char *Key) {
		if (!Key || !RootNode) return NULL;
		RootNode = SplayTree(RootNode, Key);
		return (_strcmpi(Key, RootNode->Key)) ? NULL : RootNode->Data;
	}

	void DictDelete(void) {
		DictNode<DataType> *Node, *Next;
		if (!DictSize) return;
		for (Node = FirstNode; Node; Node = Next) {
			Next = Node->NextNode;
			DeleteNode(Node);
		}
		DictSize = 0;
	}
};

#endif /* !defined(DICT_H) */