#if !defined(DICT_H) #define DICT_H #ifndef NULL #include #endif #ifndef _strcmpi #include #endif template class Dict; typedef void (*delete_t)(void*); template class DictNode { friend class Dict; 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 Dict { private: unsigned long DictSize; bool FreeKey, FreeData; delete_t DeleteKey, DeleteData; DictNode *RootNode, *FirstNode, *LastNode; static DictNode *SplayTree(DictNode *Node, const char *Key) { DictNode Stack(NULL, NULL); DictNode *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 *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 *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 *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 *NewNode = new DictNode(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 *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 *Node, *Next; if (!DictSize) return; for (Node = FirstNode; Node; Node = Next) { Next = Node->NextNode; DeleteNode(Node); } DictSize = 0; } }; #endif /* !defined(DICT_H) */