|
Fimbulwinter Project
Pre-Alpha
An Ragnarok Online Emulator
|
00001 /*==================================================================* 00002 * ___ _ _ _ _ _ * 00003 * / __(_)_ __ ___ | |__ _ _| |_ _(_)_ __ | |_ ___ _ __ * 00004 * / _\ | | '_ ` _ \| '_ \| | | | \ \ /\ / / | '_ \| __/ _ \ '__| * 00005 * / / | | | | | | | |_) | |_| | |\ V V /| | | | | || __/ | * 00006 * \/ |_|_| |_| |_|_.__/ \__,_|_| \_/\_/ |_|_| |_|\__\___|_| * 00007 * * 00008 * ------------------------------------------------------------------* 00009 * Emulator * 00010 * ------------------------------------------------------------------* 00011 * Licenced under GNU GPL v3 * 00012 * ------------------------------------------------------------------* 00013 * Database Classes * 00014 * ================================================================= */ 00015 00016 #pragma once 00017 00018 #include <cstdlib> 00019 #include <cassert> 00020 #include <cmath> 00021 #include <list> 00022 00023 using std::list; 00024 00025 template <class S, class T> class PatriciaTrie; 00026 00027 template <class S, class T> 00028 class PatriciaTrieNode { 00029 00030 private: 00031 00032 friend class PatriciaTrie<S,T>; 00033 int bit_index; 00034 S key; 00035 T data; 00036 PatriciaTrieNode<S,T>* left; 00037 PatriciaTrieNode<S,T>* right; 00038 00039 public: 00040 00041 // Constructors & destructor 00042 PatriciaTrieNode (); 00043 PatriciaTrieNode (S, T, int, PatriciaTrieNode<S,T>*, PatriciaTrieNode<S,T>*); 00044 virtual ~PatriciaTrieNode (); 00045 00046 // Name: Initialize 00047 // Args: key, data, left, right 00048 // Return: void 00049 // Purpose: Initialize this node with the given data. 00050 void Initialize (S, T, int, PatriciaTrieNode<S,T>*, PatriciaTrieNode<S,T>*); 00051 00052 // Name: GetData/SetData 00053 // Args: data : T 00054 // Return: T | bool 00055 // Purpose: Accessors for the data field. 00056 T GetData (); 00057 bool SetData (T); 00058 00059 // Name: GetKey 00060 // Args: none 00061 // Return: S 00062 // Purpose: Getter for the key field. 00063 S GetKey (); 00064 00065 // Name: GetLeft/GetRight 00066 // Args: none 00067 // Return: PatriciaTrieNode* 00068 // Purpose: Getters for the left/right fields. 00069 PatriciaTrieNode<S,T>* GetLeft (); 00070 PatriciaTrieNode<S,T>* GetRight (); 00071 00072 }; 00073 00074 template <class S, class T> 00075 class PatriciaTrie { 00076 00077 private: 00078 00079 void recursive_remove (PatriciaTrieNode<S,T>*); 00080 int bit_get (S, int); 00081 int bit_first_different (S, S); 00082 bool key_compare (S, S); 00083 void key_copy (PatriciaTrieNode<S,T>*, PatriciaTrieNode<S,T>*); 00084 PatriciaTrieNode<S,T>* find_bitindex_node (PatriciaTrieNode<S,T>* root, int bitindex); 00085 PatriciaTrieNode<S,T>* head; 00086 00087 public: 00088 00089 // Constructor and destructor 00090 PatriciaTrie (); 00091 virtual ~PatriciaTrie (); 00092 00093 // Name: Insert(key, data) 00094 // Args: key : S, data : T 00095 // Return: PatriciaTrieNode* 00096 // Purpose: Insert a new key+data pair in the Patricia structure, and 00097 // return the new node. 00098 virtual PatriciaTrieNode<S,T>* Insert (S, T); 00099 00100 // Name: Exists(key) 00101 // Args: key : S 00102 // Return: bool 00103 // Purpose: Test if a node with the given key exists. 00104 virtual bool Exists (S); 00105 00106 // Name: Lookup(key) 00107 // Args: key : S 00108 // Return: T 00109 // Purpose: Search for the given key, and return the data associated 00110 // with it. 00111 virtual T Lookup (S); 00112 00113 // Name: LookupNode(key) 00114 // Args: key : S 00115 // Return: T 00116 // Purpose: Search for the given key, and return the node that 00117 // contains it (or NULL). 00118 virtual PatriciaTrieNode<S,T>* LookupNode (S); 00119 00120 // Name: Delete(key) 00121 // Args: key : S 00122 // Return: bool 00123 // Purpose: Remove the node containing the given key. Return 00124 // true if the operation succeeded, false otherwise. 00125 virtual bool Delete (S); 00126 00127 // Name: NODE_LIST 00128 // Purpose a list of patricia nodes 00129 typedef typename list<PatriciaTrieNode<S,T>*> NODE_LIST; 00130 typedef typename NODE_LIST::iterator NODE_LIST_ITERATOR; 00131 00132 // Name: GetNodeList 00133 // Args: PatriciaTrieNode<S,T>* 00134 // Return: NODE_LIST 00135 // Purpose: Get all the nodes from the tree 00136 virtual NODE_LIST GetNodeList (PatriciaTrieNode<S,T>* root = NULL); 00137 00138 // Name: LookupGroup 00139 // Args: S 00140 // Return: PatriciaTrieNode<S,T>* 00141 // Purpose: Get the node that has the longest prefix with the given key 00142 // this is the potential father node if we would insert the given node 00143 virtual PatriciaTrieNode<S,T>* LookupGroup (S); 00144 00145 // Name: Copy 00146 // Return: PatriciaTrie<S,T>* 00147 // Purpose: Copy the complete trie 00148 virtual PatriciaTrie<S,T>* Copy (PatriciaTrieNode<S,T>* root = NULL); 00149 00150 }; 00151 00152 template <class S, class T> 00153 PatriciaTrieNode<S,T>::PatriciaTrieNode() { 00154 Initialize(S(), T(), -1, this, this); 00155 } 00156 00157 template <class S, class T> 00158 PatriciaTrieNode<S,T>::PatriciaTrieNode(S k, 00159 T d, 00160 int bi, 00161 PatriciaTrieNode<S,T>* l, 00162 PatriciaTrieNode<S,T>* r) { 00163 Initialize(k, d, bi, l, r); 00164 } 00165 00166 template <class S, class T> 00167 void PatriciaTrieNode<S,T>::Initialize( S k, 00168 T d, 00169 int bi, 00170 PatriciaTrieNode<S,T>* l, 00171 PatriciaTrieNode<S,T>* r) { 00172 00173 key = k; 00174 data = d; 00175 left = l; 00176 right = r; 00177 bit_index = bi; 00178 } 00179 00180 template <class S, class T> 00181 PatriciaTrieNode<S,T>::~PatriciaTrieNode() { 00182 } 00183 00184 template <class S, class T> 00185 T PatriciaTrieNode<S,T>::GetData() { 00186 return data; 00187 } 00188 00189 template <class S, class T> 00190 bool PatriciaTrieNode<S,T>::SetData(T d) { 00191 data = d; 00192 return true; 00193 } 00194 00195 template <class S, class T> 00196 S PatriciaTrieNode<S,T>::GetKey() { 00197 return key; 00198 } 00199 00200 template <class S, class T> 00201 PatriciaTrieNode<S,T>* PatriciaTrieNode<S,T>::GetLeft() { 00202 return left; 00203 } 00204 00205 template <class S, class T> 00206 PatriciaTrieNode<S,T>* PatriciaTrieNode<S,T>::GetRight() { 00207 return right; 00208 } 00209 00210 template <class S, class T> 00211 PatriciaTrie<S,T>::PatriciaTrie() { 00212 // Create the head of the structure. The head is never moved 00213 // around in the trie (i.e. it always stays at the top of the structure). 00214 // This prevents further complications having to do with node removal. 00215 head = new PatriciaTrieNode<S,T> (); 00216 head->key = S (); 00217 } 00218 00219 template <class S, class T> 00220 PatriciaTrie<S,T>::~PatriciaTrie() { 00221 recursive_remove (head); 00222 } 00223 00224 template <class S, class T> 00225 PatriciaTrieNode<S,T>* PatriciaTrie<S,T>::Insert(S k, T d) { 00226 00227 PatriciaTrieNode<S,T> *p, *t, *x; 00228 00229 // Start at the root 00230 p = head; 00231 t = (PatriciaTrieNode<S,T>*)(p->right); 00232 00233 // Navigate down the tree and look for the key 00234 while (p->bit_index < t->bit_index) { 00235 p = t; 00236 t = (PatriciaTrieNode<S,T>*)(bit_get(k, t->bit_index) ? t->right : t->left); 00237 } 00238 00239 // Is the key already in the tree? 00240 if (key_compare(k, t->key)) 00241 return NULL; // Already in the tree! 00242 00243 // Find the first bit that does not match. 00244 int i = bit_first_different(k, t->key); 00245 00246 // Find the appropriate place in the tree where 00247 // the node has to be inserted 00248 p = head; 00249 x = (PatriciaTrieNode<S,T>*)(p->right); 00250 while ( ( p->bit_index < x->bit_index ) && 00251 ( x->bit_index < i) ) { 00252 p = x; 00253 x = (PatriciaTrieNode<S,T>*)(bit_get(k, x->bit_index) ? x->right : x->left); 00254 } 00255 00256 // Allocate a new node and initialize it. 00257 t = new PatriciaTrieNode<S,T>(); 00258 t->Initialize(k, d, i, (bit_get(k, i) ? x : t), (bit_get(k, i) ? t : x)); 00259 00260 // Rewire 00261 if (bit_get(k, p->bit_index)) 00262 p->right = t; 00263 else 00264 p->left = t; 00265 00266 // Return the newly created node 00267 return t; 00268 } 00269 00270 template <class S, class T> 00271 bool PatriciaTrie<S,T>::Exists(S k) { 00272 00273 // Lookup the node 00274 PatriciaTrieNode<S,T>* node = LookupNode(k); 00275 return (node != NULL); 00276 } 00277 00278 template <class S, class T> 00279 T PatriciaTrie<S,T>::Lookup(S k) { 00280 00281 // Lookup the node 00282 PatriciaTrieNode<S,T>* node = LookupNode(k); 00283 00284 // Failed? 00285 if (!node) 00286 return T (); 00287 00288 // Return the data stored in this node 00289 return node->data; 00290 } 00291 00292 template <class S, class T> 00293 PatriciaTrieNode<S,T>* PatriciaTrie<S,T>::LookupNode(S k) { 00294 00295 PatriciaTrieNode<S,T>* p; 00296 PatriciaTrieNode<S,T>* x; 00297 00298 // Start at the root. 00299 p = head; 00300 x = (PatriciaTrieNode<S,T>*)(head->right); 00301 00302 // Go down the Patricia structure until an upward 00303 // link is encountered. 00304 while (p->bit_index < x->bit_index) { 00305 p = x; 00306 x = (PatriciaTrieNode<S,T>*)(bit_get(k, x->bit_index) ? x->right : x->left); 00307 } 00308 00309 // Perform a comparison, and return NULL if 00310 // the key is not found at this location in the structure. 00311 if (!key_compare(k, x->key)) 00312 return NULL; 00313 00314 // Return the node 00315 return x; 00316 } 00317 00318 template <class S, class T> 00319 bool PatriciaTrie<S,T>::Delete(S k) { 00320 00321 PatriciaTrieNode<S,T> *p, *t, *x, *pp, *lp; 00322 int bp, bl, br; 00323 S key; 00324 00325 // Start at the root 00326 p = head; 00327 t = (PatriciaTrieNode<S,T>*)(p->right); 00328 00329 // Navigate down the tree and look for the key 00330 while (p->bit_index < t->bit_index) { 00331 pp = p; 00332 p = t; 00333 t = (PatriciaTrieNode<S,T>*)(bit_get(k, t->bit_index) ? t->right : t->left); 00334 } 00335 00336 // Is the key in the tree? If not, get out! 00337 if (!key_compare(k, t->key)) 00338 return false; // The key could not be found! 00339 00340 // Copy p's key to t 00341 if (t != p) 00342 key_copy(p, t); 00343 00344 // Is p a leaf? 00345 bp = p->bit_index; 00346 bl = ((PatriciaTrieNode<S,T>*)(p->left))->bit_index; 00347 br = ((PatriciaTrieNode<S,T>*)(p->right))->bit_index; 00348 00349 if ((bl > bp) || (br > bp)) { 00350 00351 // There is at least one downward edge. 00352 00353 if (p != t) { 00354 00355 // Look for a new (intermediate) key 00356 key = S(p->key); 00357 00358 lp = p; 00359 x = (PatriciaTrieNode<S,T>*)(bit_get(key, p->bit_index) ? p->right : p->left); 00360 00361 while (lp->bit_index < x->bit_index) { 00362 lp = x; 00363 x = (PatriciaTrieNode<S,T>*)(bit_get(key, x->bit_index) ? x->right : x->left); 00364 } 00365 00366 // If the intermediate key was not found, we have a problem.. 00367 if (!key_compare(key, x->key)) { 00368 return false; // The key could not be found! 00369 } 00370 00371 // Rewire the leaf (lp) to point to t 00372 if (bit_get(key, lp->bit_index)) 00373 lp->right = t; 00374 else 00375 lp->left = t; 00376 00377 } 00378 00379 // Rewire the parent to point to the real child of p 00380 if (pp != p) { 00381 PatriciaTrieNode<S,T>* ch = (PatriciaTrieNode<S,T>*)(bit_get(k, p->bit_index) ? p->left : p->right); 00382 if (bit_get(k, pp->bit_index)) 00383 pp->right = ch; 00384 else 00385 pp->left = ch; 00386 00387 } 00388 00389 } else { 00390 00391 // Both edges (left, right) are pointing upwards or to the node (self-edges). 00392 00393 // Rewire the parent 00394 if (pp != p) { 00395 PatriciaTrieNode<S,T>* blx = (PatriciaTrieNode<S,T>*)(p->left); 00396 PatriciaTrieNode<S,T>* brx = (PatriciaTrieNode<S,T>*)(p->right); 00397 00398 PatriciaTrieNode<S,T>* item = (((blx == brx) && (blx == p)) ? pp : ((blx==p)?brx:blx)); 00399 00400 if (bit_get(k, pp->bit_index)) 00401 pp->right = item; 00402 else 00403 pp->left = item; 00404 00405 } 00406 00407 } 00408 00409 // Deallocate p (no longer needed) 00410 delete p; 00411 00412 // Success! 00413 return true; 00414 } 00415 00416 template <class S, class T> 00417 void PatriciaTrie<S,T>::recursive_remove(PatriciaTrieNode<S,T>* root) { 00418 00419 if (root == NULL) return; 00420 00421 PatriciaTrieNode<S,T>* l = (PatriciaTrieNode<S,T>*)root->left; 00422 PatriciaTrieNode<S,T>* r = (PatriciaTrieNode<S,T>*)root->right; 00423 00424 // Remove the left branch 00425 if ( (l->bit_index >= root->bit_index) && (l != root) && (l != head) ) 00426 recursive_remove(l); 00427 00428 // Remove the right branch 00429 if ( (r->bit_index >= root->bit_index) && (r != root) && (r != head) ) 00430 recursive_remove(r); 00431 00432 // Remove the root 00433 delete root; 00434 } 00435 00436 template <class S, class T> 00437 int PatriciaTrie<S,T>::bit_get(S bit_stream, int n) { 00438 00439 if (n < 0) return 2; // "pseudo-bit" with a value of 2. 00440 00441 // get the value of the n-th bit from the bit_stream 00442 // return 0 or 1 00443 00444 unsigned int byteno = n / 8; 00445 unsigned int bitno = 8 - 1 - (n % 8); 00446 unsigned char bitmask = 0x01 << bitno; 00447 unsigned char* pnt = (unsigned char*) &bit_stream; 00448 00449 pnt += byteno; 00450 int ret = ((*pnt) & bitmask) >> bitno; 00451 00452 assert (ret == 0 || ret == 1); 00453 return ret; 00454 } 00455 00456 template <class S, class T> 00457 bool PatriciaTrie<S,T>::key_compare(S k1, S k2) { 00458 return (k1 == k2); 00459 } 00460 00461 template <class S, class T> 00462 int PatriciaTrie<S,T>::bit_first_different(S k1, S k2) { 00463 00464 int n = 0; 00465 int d = 0; 00466 00467 unsigned char* pnt_k1 = (unsigned char*)&k1; 00468 unsigned char* pnt_k2 = (unsigned char*)&k2; 00469 00470 while (*pnt_k1 == *pnt_k2 && n < sizeof (S)){ 00471 pnt_k1++; 00472 pnt_k2++; 00473 n++; 00474 } 00475 00476 S* sobj1 = (S*) pnt_k1; 00477 S* sobj2 = (S*) pnt_k2; 00478 00479 while (bit_get(*sobj1, d) == bit_get(*sobj2, d)) 00480 d++; 00481 00482 return ((n << 3) + d); 00483 } 00484 00485 template <class S, class T> 00486 void PatriciaTrie<S,T>::key_copy(PatriciaTrieNode<S,T>* src, PatriciaTrieNode<S,T>* dest) { 00487 dest->key = src->key; 00488 dest->data = src->data; 00489 } 00490 00491 template <class S, class T> 00492 typename PatriciaTrie<S,T>::NODE_LIST PatriciaTrie<S,T>::GetNodeList (PatriciaTrieNode<S,T>* root) { 00493 00494 NODE_LIST retNodes; 00495 NODE_LIST newItemsLeft, newItemsRight; 00496 PatriciaTrieNode<S,T>* startNode = (root == NULL ? head : root); 00497 00498 // 00499 // insert the current node if it is not the root node 00500 // 00501 00502 if (startNode->bit_index >= 0) 00503 retNodes.insert (retNodes.end (), startNode); 00504 00505 // 00506 // walk down left wing 00507 // 00508 00509 if (startNode->left != NULL && startNode->left->bit_index > startNode->bit_index) 00510 newItemsLeft = GetNodeList (startNode->left); 00511 00512 retNodes.insert (retNodes.end(), newItemsLeft.begin(), newItemsLeft.end()); 00513 00514 // 00515 // walk down right wing 00516 // 00517 00518 if (startNode->right != NULL && startNode->right->bit_index > startNode->bit_index) 00519 newItemsRight = GetNodeList (startNode->right); 00520 00521 retNodes.insert (retNodes.end(), newItemsRight.begin(), newItemsRight.end()); 00522 00523 return retNodes; 00524 } 00525 00526 template <class S, class T> 00527 PatriciaTrieNode<S,T>* PatriciaTrie<S,T>::LookupGroup (S k) { 00528 00529 PatriciaTrieNode<S,T> *p, *t; 00530 00531 p = head; 00532 t = (PatriciaTrieNode<S,T>*)(p->right); 00533 00534 while (p->bit_index < t->bit_index) { 00535 p = t; 00536 t = (PatriciaTrieNode<S,T>*)(bit_get(k, t->bit_index) ? t->right : t->left); 00537 } 00538 00539 return t; 00540 } 00541 00542 template <class S, class T> 00543 PatriciaTrie<S,T>* PatriciaTrie<S,T>::Copy (PatriciaTrieNode<S,T>* root) { 00544 00545 PatriciaTrieNode<S,T>* newNode = new PatriciaTrieNode<S,T> (); 00546 bool recursiveHead = (root == NULL); 00547 if (root == NULL) root = head; 00548 00549 newNode->bit_index = root->bit_index; 00550 newNode->data = root->data; 00551 newNode->key = root->key; 00552 00553 // 00554 // create the subtrees and wire my children to it 00555 // or (if there are no subtrees) wire the children to myself 00556 // later we will wire the children correctly with some backedges 00557 // 00558 00559 if (root->left != NULL && root->left->bit_index > root->bit_index) { 00560 PatriciaTrie<S,T>* leftTrie = Copy (root->left); 00561 newNode->left = leftTrie->head; 00562 leftTrie->head = NULL; 00563 delete leftTrie; 00564 } else { 00565 newNode->left = newNode; 00566 } 00567 00568 if (root->right != NULL && root->right->bit_index > root->bit_index) { 00569 PatriciaTrie<S,T>* rightTrie = Copy (root->right); 00570 newNode->right = rightTrie->head; 00571 rightTrie->head = NULL; 00572 delete rightTrie; 00573 } else { 00574 newNode->right = newNode; 00575 } 00576 00577 PatriciaTrie<S,T>* newTrie = new PatriciaTrie<S,T> (); 00578 newTrie->head = newNode; 00579 00580 // 00581 // need to adapt the back edges 00582 // 00583 00584 if (recursiveHead) { 00585 00586 NODE_LIST origNodes = GetNodeList (); 00587 NODE_LIST newNodes = newTrie->GetNodeList (); 00588 00589 assert (origNodes.size() == newNodes.size()); 00590 00591 NODE_LIST_ITERATOR iorigBegin = origNodes.begin (); 00592 NODE_LIST_ITERATOR iorigEnd = origNodes.end (); 00593 NODE_LIST_ITERATOR inewBegin = newNodes.begin (); 00594 NODE_LIST_ITERATOR inewEnd = newNodes.end (); 00595 00596 for ( ; iorigBegin != iorigEnd && inewBegin != inewEnd; iorigBegin++, inewBegin++) { 00597 00598 PatriciaTrieNode<S,T>* origNode = *iorigBegin; 00599 PatriciaTrieNode<S,T>* newNode = *inewBegin; 00600 00601 // 00602 // make some checks that everything went fine 00603 // 00604 00605 assert (origNode != newNode && 00606 origNode->key == newNode->key && 00607 origNode->bit_index == newNode->bit_index && 00608 origNode->data == newNode->data ); 00609 00610 // 00611 // if the original node has backedges: 00612 // find the correct backedge node in the new trie 00613 // and wire the children correctly 00614 // 00615 00616 if (origNode->left->bit_index < origNode->bit_index) 00617 newNode->left = newTrie->find_bitindex_node (newTrie->head, origNode->left->bit_index); 00618 00619 if (origNode->right->bit_index < origNode->bit_index) 00620 newNode->right = newTrie->find_bitindex_node (newTrie->head, origNode->right->bit_index); 00621 00622 } // for ( ; iorigBegin != iorigEnd && inewBegin != inewEnd; iorigBegin++, inewBegin++) 00623 00624 } // if (recursiveHead) 00625 00626 return newTrie; 00627 } 00628 00629 template <class S, class T> 00630 PatriciaTrieNode<S,T>* PatriciaTrie<S,T>::find_bitindex_node (PatriciaTrieNode<S,T>* root, int bitindex) { 00631 00632 // 00633 // is the head-pseudo-node requested? 00634 // 00635 00636 if (bitindex == -1) 00637 return head; 00638 00639 // 00640 // check all the normal nodes 00641 // 00642 00643 NODE_LIST nodes = GetNodeList (root); 00644 00645 NODE_LIST_ITERATOR i = nodes.begin (); 00646 NODE_LIST_ITERATOR iend = nodes.end (); 00647 00648 for ( ; i != iend; i++) { 00649 PatriciaTrieNode<S,T>* node = *i; 00650 if (node->bit_index == bitindex) return node; 00651 } 00652 00653 return NULL; 00654 }
1.7.6.1