Fimbulwinter Project  Pre-Alpha
An Ragnarok Online Emulator
Common/datastruct.hpp
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 }
 All Classes Functions