llptrskipmap.h

Go to the documentation of this file.
00001 
00032 #ifndef LL_LLPTRSKIPMAP_H
00033 #define LL_LLPTRSKIPMAP_H
00034 
00035 #include "llerror.h"
00036 #include "llrand.h"
00037 
00038 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH = 8> 
00039 class LLPtrSkipMapNode
00040 {
00041 public:
00042         LLPtrSkipMapNode()
00043         {
00044                 S32 i;
00045                 for (i = 0; i < BINARY_DEPTH; i++)
00046                 {
00047                         mForward[i] = NULL;
00048                 }
00049 
00050                 U8  *zero = (U8 *)&mIndex;
00051 
00052                 for (i = 0; i < (S32)sizeof(INDEX_T); i++)
00053                 {
00054                         *(zero + i) = 0;
00055                 }
00056 
00057                 zero = (U8 *)&mData;
00058 
00059                 for (i = 0; i < (S32)sizeof(DATA_T); i++)
00060                 {
00061                         *(zero + i) = 0;
00062                 }
00063         }
00064 
00065         LLPtrSkipMapNode(const INDEX_T &index)
00066         :       mIndex(index)
00067         {
00068 
00069                 S32 i;
00070                 for (i = 0; i < BINARY_DEPTH; i++)
00071                 {
00072                         mForward[i] = NULL;
00073                 }
00074 
00075                 U8 *zero = (U8 *)&mData;
00076 
00077                 for (i = 0; i < (S32)sizeof(DATA_T); i++)
00078                 {
00079                         *(zero + i) = 0;
00080                 }
00081         }
00082 
00083         LLPtrSkipMapNode(const INDEX_T &index, DATA_T datap)
00084         :       mIndex(index)
00085         {
00086 
00087                 S32 i;
00088                 for (i = 0; i < BINARY_DEPTH; i++)
00089                 {
00090                         mForward[i] = NULL;
00091                 }
00092 
00093                 mData = datap;
00094         }
00095 
00096         ~LLPtrSkipMapNode()
00097         {
00098         }
00099 
00100         // delete associated data and NULLs out pointer
00101         void deleteData()
00102         {
00103                 delete mData;
00104                 mData = 0;
00105         }
00106 
00107         // NULLs out pointer
00108         void removeData()
00109         {
00110                 mData = 0;
00111         }
00112 
00113         INDEX_T                                 mIndex;
00114         DATA_T                                  mData;
00115         LLPtrSkipMapNode                                *mForward[BINARY_DEPTH];
00116 
00117 private:
00118         // Disallow copying of LLPtrSkipMapNodes by not implementing these methods.
00119         LLPtrSkipMapNode(const LLPtrSkipMapNode &);
00120         LLPtrSkipMapNode &operator=(const LLPtrSkipMapNode &rhs);
00121 };
00122 
00123 //---------------------------------------------------------------------------
00124 
00125 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH = 8> 
00126 class LLPtrSkipMap
00127 {
00128 public:
00129         typedef BOOL (*compare)(const DATA_T& first, const DATA_T& second);
00130         typedef compare insert_func;
00131         typedef compare equals_func;
00132 
00133         void init();
00134 
00135         // basic constructor
00136         LLPtrSkipMap();
00137 
00138         // basic constructor including sorter
00139         LLPtrSkipMap(insert_func insert_first, equals_func equals);
00140 
00141         ~LLPtrSkipMap();
00142 
00143         void setInsertFirst(insert_func insert_first);
00144         void setEquals(equals_func equals);
00145 
00146         DATA_T &addData(const INDEX_T &index, DATA_T datap);
00147         DATA_T &addData(const INDEX_T &index);
00148         DATA_T &getData(const INDEX_T &index);
00149         DATA_T &operator[](const INDEX_T &index);
00150 
00151         // If index present, returns data.
00152         // If index not present, adds <index,NULL> and returns NULL.
00153         DATA_T &getData(const INDEX_T &index, BOOL &b_new_entry);
00154 
00155         // returns data entry before and after index
00156         BOOL getInterval(const INDEX_T &index, INDEX_T &index_before, INDEX_T &index_after,
00157                 DATA_T &data_before, DATA_T &data_after );
00158 
00159         // Returns TRUE if data present in map.
00160         BOOL checkData(const INDEX_T &index);
00161 
00162         // Returns TRUE if key is present in map. This is useful if you
00163         // are potentially storing NULL pointers in the map
00164         BOOL checkKey(const INDEX_T &index);
00165 
00166         // If there, returns the data.
00167         // If not, returns NULL.
00168         // Never adds entries to the map.
00169         DATA_T getIfThere(const INDEX_T &index);
00170 
00171         INDEX_T reverseLookup(const DATA_T datap);
00172 
00173         // returns number of items in the list
00174         S32 getLength(); // WARNING!  getLength is O(n), not O(1)!
00175 
00176         BOOL removeData(const INDEX_T &index);
00177         BOOL deleteData(const INDEX_T &index);
00178 
00179         // remove all nodes from the list but do not delete data
00180         void removeAllData();
00181         void deleteAllData();
00182 
00183         // place mCurrentp on first node
00184         void resetList();
00185 
00186         // return the data currently pointed to
00187         DATA_T  getCurrentDataWithoutIncrement();
00188 
00189         // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
00190         DATA_T  getCurrentData();
00191 
00192         // same as getCurrentData() but a more intuitive name for the operation
00193         DATA_T  getNextData();
00194 
00195         INDEX_T getNextKey();
00196 
00197         // return the key currently pointed to
00198         INDEX_T getCurrentKeyWithoutIncrement();
00199 
00200         // remove the Node at mCurentOperatingp
00201         // leave mCurrentp and mCurentOperatingp on the next entry
00202         void removeCurrentData();
00203 
00204         void deleteCurrentData();
00205 
00206         // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
00207         DATA_T  getFirstData();
00208 
00209         INDEX_T getFirstKey();
00210 
00211         static BOOL     defaultEquals(const INDEX_T &first, const INDEX_T &second)
00212         {
00213                 return first == second;
00214         }
00215 
00216 private:
00217         // don't generate implicit copy constructor or copy assignment
00218         LLPtrSkipMap(const LLPtrSkipMap &);
00219         LLPtrSkipMap &operator=(const LLPtrSkipMap &);
00220 
00221 private:
00222         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> mHead;
00223         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *mUpdate[BINARY_DEPTH];
00224         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *mCurrentp;
00225         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *mCurrentOperatingp;
00226         S32                                                     mLevel;
00227         BOOL                                            (*mInsertFirst)(const INDEX_T &first, const INDEX_T &second);
00228         BOOL                                            (*mEquals)(const INDEX_T &first, const INDEX_T &second);
00229         S32                                                     mNumberOfSteps;
00230 };
00231 
00233 //
00234 // LLPtrSkipMap implementation
00235 //
00236 //
00237 
00238 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00239 inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::LLPtrSkipMap()
00240         :       mInsertFirst(NULL),
00241                 mEquals(defaultEquals)
00242 {
00243         if (BINARY_DEPTH < 2)
00244         {
00245                 llerrs << "Trying to create skip list with too little depth, "
00246                         "must be 2 or greater" << llendl;
00247         }
00248         S32 i;
00249         for (i = 0; i < BINARY_DEPTH; i++)
00250         {
00251                 mUpdate[i] = NULL;
00252         }
00253         mLevel = 1;
00254         mCurrentp = *(mHead.mForward);
00255         mCurrentOperatingp = *(mHead.mForward);
00256 }
00257 
00258 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00259 inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::LLPtrSkipMap(insert_func insert_first, 
00260                                                                                                                                  equals_func equals) 
00261 :       mInsertFirst(insert_first),
00262         mEquals(equals)
00263 {
00264         if (BINARY_DEPTH < 2)
00265         {
00266                 llerrs << "Trying to create skip list with too little depth, "
00267                         "must be 2 or greater" << llendl;
00268         }
00269         mLevel = 1;
00270         S32 i;
00271         for (i = 0; i < BINARY_DEPTH; i++)
00272         {
00273                 mHead.mForward[i] = NULL;
00274                 mUpdate[i] = NULL;
00275         }
00276         mCurrentp = *(mHead.mForward);
00277         mCurrentOperatingp = *(mHead.mForward);
00278 }
00279 
00280 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00281 inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::~LLPtrSkipMap()
00282 {
00283         removeAllData();
00284 }
00285 
00286 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00287 inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::setInsertFirst(insert_func insert_first)
00288 {
00289         mInsertFirst = insert_first;
00290 }
00291 
00292 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00293 inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::setEquals(equals_func equals)
00294 {
00295         mEquals = equals;
00296 }
00297 
00298 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00299 inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::addData(const INDEX_T &index, DATA_T datap)
00300 {
00301         S32                     level;
00302         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
00303         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
00304 
00305         // find the pointer one in front of the one we want
00306         if (mInsertFirst)
00307         {
00308                 for (level = mLevel - 1; level >= 0; level--)
00309                 {
00310                         temp = *(current->mForward + level);
00311                         while (  (temp)
00312                                    &&(mInsertFirst(temp->mIndex, index)))
00313                         {
00314                                 current = temp;
00315                                 temp = *(current->mForward + level);
00316                         }
00317                         *(mUpdate + level) = current;
00318                 }
00319         }
00320         else
00321         {
00322                 for (level = mLevel - 1; level >= 0; level--)
00323                 {
00324                         temp = *(current->mForward + level);
00325                         while (  (temp)
00326                                    &&(temp->mIndex < index))
00327                         {
00328                                 current = temp;
00329                                 temp = *(current->mForward + level);
00330                         }
00331                         *(mUpdate + level) = current;
00332                 }
00333         }
00334         
00335         // we're now just in front of where we want to be . . . take one step forward
00336         current = *current->mForward;
00337 
00338         // replace the existing data if a node is already there
00339         if (  (current)
00340                 &&(mEquals(current->mIndex, index)))
00341         {
00342                 current->mData = datap;
00343                 return current->mData;
00344         }
00345 
00346         // now add the new node
00347         S32 newlevel;
00348         for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
00349         {
00350                 if (ll_frand() < 0.5f)
00351                 {
00352                         break;
00353                 }
00354         }
00355 
00356         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode 
00357                 = new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index, datap);
00358 
00359         if (newlevel > mLevel)
00360         {
00361                 mHead.mForward[mLevel] = NULL;
00362                 mUpdate[mLevel] = &mHead;
00363                 mLevel = newlevel;
00364         }
00365 
00366         for (level = 0; level < newlevel; level++)
00367         {
00368                 snode->mForward[level] = mUpdate[level]->mForward[level];
00369                 mUpdate[level]->mForward[level] = snode;
00370         }
00371         return snode->mData;
00372 }
00373 
00374 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00375 inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::addData(const INDEX_T &index)
00376 {
00377         S32                     level;
00378         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
00379         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
00380 
00381         // find the pointer one in front of the one we want
00382         if (mInsertFirst)
00383         {
00384                 for (level = mLevel - 1; level >= 0; level--)
00385                 {
00386                         temp = *(current->mForward + level);
00387                         while (  (temp)
00388                                    &&(mInsertFirst(temp->mIndex, index)))
00389                         {
00390                                 current = temp;
00391                                 temp = *(current->mForward + level);
00392                         }
00393                         *(mUpdate + level) = current;
00394                 }
00395         }
00396         else
00397         {
00398                 for (level = mLevel - 1; level >= 0; level--)
00399                 {
00400                         temp = *(current->mForward + level);
00401                         while (  (temp)
00402                                    &&(temp->mIndex < index))
00403                         {
00404                                 current = temp;
00405                                 temp = *(current->mForward + level);
00406                         }
00407                         *(mUpdate + level) = current;
00408                 }
00409         }
00410         
00411         // we're now just in front of where we want to be . . . take one step forward
00412         current = *current->mForward;
00413 
00414         // now add the new node
00415         S32 newlevel;
00416         for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
00417         {
00418                 if (ll_frand() < 0.5f)
00419                         break;
00420         }
00421 
00422         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode 
00423                 = new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index);
00424 
00425         if (newlevel > mLevel)
00426         {
00427                 mHead.mForward[mLevel] = NULL;
00428                 mUpdate[mLevel] = &mHead;
00429                 mLevel = newlevel;
00430         }
00431 
00432         for (level = 0; level < newlevel; level++)
00433         {
00434                 snode->mForward[level] = mUpdate[level]->mForward[level];
00435                 mUpdate[level]->mForward[level] = snode;
00436         }
00437         return snode->mData;
00438 }
00439 
00440 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00441 inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getData(const INDEX_T &index)
00442 {
00443         S32                     level;
00444         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
00445         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
00446 
00447         mNumberOfSteps = 0;
00448 
00449         // find the pointer one in front of the one we want
00450         if (mInsertFirst)
00451         {
00452                 for (level = mLevel - 1; level >= 0; level--)
00453                 {
00454                         temp = *(current->mForward + level);
00455                         while (  (temp)
00456                                    &&(mInsertFirst(temp->mIndex, index)))
00457                         {
00458                                 current = temp;
00459                                 temp = *(current->mForward + level);
00460                                 mNumberOfSteps++;
00461                         }
00462                         *(mUpdate + level) = current;
00463                 }
00464         }
00465         else
00466         {
00467                 for (level = mLevel - 1; level >= 0; level--)
00468                 {
00469                         temp = *(current->mForward + level);
00470                         while (  (temp)
00471                                    &&(temp->mIndex < index))
00472                         {
00473                                 current = temp;
00474                                 temp = *(current->mForward + level);
00475                                 mNumberOfSteps++;
00476                         }
00477                         *(mUpdate + level) = current;
00478                 }
00479         }
00480         
00481         // we're now just in front of where we want to be . . . take one step forward
00482         current = *current->mForward;
00483         mNumberOfSteps++;
00484 
00485         if (  (current)
00486                 &&(mEquals(current->mIndex, index)))
00487         {
00488                 
00489                 return current->mData;
00490         }
00491         
00492         // now add the new node
00493         S32 newlevel;
00494         for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
00495         {
00496                 if (ll_frand() < 0.5f)
00497                         break;
00498         }
00499 
00500         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode 
00501                 = new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index);
00502 
00503         if (newlevel > mLevel)
00504         {
00505                 mHead.mForward[mLevel] = NULL;
00506                 mUpdate[mLevel] = &mHead;
00507                 mLevel = newlevel;
00508         }
00509 
00510         for (level = 0; level < newlevel; level++)
00511         {
00512                 snode->mForward[level] = mUpdate[level]->mForward[level];
00513                 mUpdate[level]->mForward[level] = snode;
00514         }
00515         
00516         return snode->mData;
00517 }
00518 
00519 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00520 inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getInterval(const INDEX_T &index, 
00521                                                                                                                                          INDEX_T &index_before, 
00522                                                                                                                                          INDEX_T &index_after, 
00523                                                                                                                                          DATA_T &data_before, 
00524                                                                                                                                          DATA_T &data_after)
00525 {
00526         S32                     level;
00527         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
00528         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
00529 
00530         mNumberOfSteps = 0;
00531 
00532         // find the pointer one in front of the one we want
00533         if (mInsertFirst)
00534         {
00535                 for (level = mLevel - 1; level >= 0; level--)
00536                 {
00537                         temp = *(current->mForward + level);
00538                         while (  (temp)
00539                                    &&(mInsertFirst(temp->mIndex, index)))
00540                         {
00541                                 current = temp;
00542                                 temp = *(current->mForward + level);
00543                                 mNumberOfSteps++;
00544                         }
00545                         *(mUpdate + level) = current;
00546                 }
00547         }
00548         else
00549         {
00550                 for (level = mLevel - 1; level >= 0; level--)
00551                 {
00552                         temp = *(current->mForward + level);
00553                         while (  (temp)
00554                                    &&(temp->mIndex < index))
00555                         {
00556                                 current = temp;
00557                                 temp = *(current->mForward + level);
00558                                 mNumberOfSteps++;
00559                         }
00560                         *(mUpdate + level) = current;
00561                 }
00562         }
00563         
00564         BOOL both_found = TRUE;
00565 
00566         if (current != &mHead)
00567         {
00568                 index_before = current->mIndex;
00569                 data_before = current->mData;
00570         }
00571         else
00572         {
00573                 data_before = 0;
00574                 index_before = 0;
00575                 both_found = FALSE;
00576         }
00577 
00578         // we're now just in front of where we want to be . . . take one step forward
00579         mNumberOfSteps++;
00580         current = *current->mForward;
00581 
00582         if (current)
00583         {
00584                 data_after = current->mData;
00585                 index_after = current->mIndex;
00586         }
00587         else
00588         {
00589                 data_after = 0;
00590                 index_after = 0;
00591                 both_found = FALSE;
00592         }
00593 
00594         return both_found;
00595 }
00596 
00597 
00598 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00599 inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::operator[](const INDEX_T &index)
00600 {
00601         
00602         return getData(index);
00603 }
00604 
00605 // If index present, returns data.
00606 // If index not present, adds <index,NULL> and returns NULL.
00607 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00608 inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getData(const INDEX_T &index, BOOL &b_new_entry)
00609 {
00610         S32                     level;
00611         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
00612         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
00613 
00614         mNumberOfSteps = 0;
00615 
00616         // find the pointer one in front of the one we want
00617         if (mInsertFirst)
00618         {
00619                 for (level = mLevel - 1; level >= 0; level--)
00620                 {
00621                         temp = *(current->mForward + level);
00622                         while (  (temp)
00623                                    &&(mInsertFirst(temp->mIndex, index)))
00624                         {
00625                                 current = temp;
00626                                 temp = *(current->mForward + level);
00627                                 mNumberOfSteps++;
00628                         }
00629                         *(mUpdate + level) = current;
00630                 }
00631         }
00632         else
00633         {
00634                 for (level = mLevel - 1; level >= 0; level--)
00635                 {
00636                         temp = *(current->mForward + level);
00637                         while (  (temp)
00638                                    &&(temp->mIndex < index))
00639                         {
00640                                 current = temp;
00641                                 temp = *(current->mForward + level);
00642                                 mNumberOfSteps++;
00643                         }
00644                         *(mUpdate + level) = current;
00645                 }
00646         }
00647         
00648         // we're now just in front of where we want to be . . . take one step forward
00649         mNumberOfSteps++;
00650         current = *current->mForward;
00651 
00652         if (  (current)
00653                 &&(mEquals(current->mIndex, index)))
00654         {
00655                 
00656                 return current->mData;
00657         }
00658         b_new_entry = TRUE;
00659         addData(index);
00660         
00661         return current->mData;
00662 }
00663 
00664 // Returns TRUE if data present in map.
00665 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00666 inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::checkData(const INDEX_T &index)
00667 {
00668         S32                     level;
00669         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
00670         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
00671 
00672         // find the pointer one in front of the one we want
00673         if (mInsertFirst)
00674         {
00675                 for (level = mLevel - 1; level >= 0; level--)
00676                 {
00677                         temp = *(current->mForward + level);
00678                         while (  (temp)
00679                                    &&(mInsertFirst(temp->mIndex, index)))
00680                         {
00681                                 current = temp;
00682                                 temp = *(current->mForward + level);
00683                         }
00684                         *(mUpdate + level) = current;
00685                 }
00686         }
00687         else
00688         {
00689                 for (level = mLevel - 1; level >= 0; level--)
00690                 {
00691                         temp = *(current->mForward + level);
00692                         while (  (temp)
00693                                    &&(temp->mIndex < index))
00694                         {
00695                                 current = temp;
00696                                 temp = *(current->mForward + level);
00697                         }
00698                         *(mUpdate + level) = current;
00699                 }
00700         }
00701         
00702         // we're now just in front of where we want to be . . . take one step forward
00703         current = *current->mForward;
00704 
00705         if (current)
00706         {
00707                 // Gets rid of some compiler ambiguity for the LLPointer<> templated class.
00708                 if (current->mData)
00709                 {
00710                         return mEquals(current->mIndex, index);
00711                 }
00712         }
00713 
00714         return FALSE;
00715 }
00716 
00717 // Returns TRUE if key is present in map. This is useful if you
00718 // are potentially storing NULL pointers in the map
00719 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00720 inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::checkKey(const INDEX_T &index)
00721 {
00722         S32                     level;
00723         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
00724         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
00725 
00726         // find the pointer one in front of the one we want
00727         if (mInsertFirst)
00728         {
00729                 for (level = mLevel - 1; level >= 0; level--)
00730                 {
00731                         temp = *(current->mForward + level);
00732                         while (  (temp)
00733                                    &&(mInsertFirst(temp->mIndex, index)))
00734                         {
00735                                 current = temp;
00736                                 temp = *(current->mForward + level);
00737                         }
00738                         *(mUpdate + level) = current;
00739                 }
00740         }
00741         else
00742         {
00743                 for (level = mLevel - 1; level >= 0; level--)
00744                 {
00745                         temp = *(current->mForward + level);
00746                         while (  (temp)
00747                                    &&(temp->mIndex < index))
00748                         {
00749                                 current = temp;
00750                                 temp = *(current->mForward + level);
00751                         }
00752                         *(mUpdate + level) = current;
00753                 }
00754         }
00755         
00756         // we're now just in front of where we want to be . . . take one step forward
00757         current = *current->mForward;
00758 
00759         if (current)
00760         {
00761                 return mEquals(current->mIndex, index);
00762         }
00763 
00764         return FALSE;
00765 }
00766 
00767 // If there, returns the data.
00768 // If not, returns NULL.
00769 // Never adds entries to the map.
00770 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00771 inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getIfThere(const INDEX_T &index)
00772 {
00773         S32                     level;
00774         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
00775         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
00776 
00777         mNumberOfSteps = 0;
00778 
00779         // find the pointer one in front of the one we want
00780         if (mInsertFirst)
00781         {
00782                 for (level = mLevel - 1; level >= 0; level--)
00783                 {
00784                         temp = *(current->mForward + level);
00785                         while (  (temp)
00786                                    &&(mInsertFirst(temp->mIndex, index)))
00787                         {
00788                                 current = temp;
00789                                 temp = *(current->mForward + level);
00790                                 mNumberOfSteps++;
00791                         }
00792                         *(mUpdate + level) = current;
00793                 }
00794         }
00795         else
00796         {
00797                 for (level = mLevel - 1; level >= 0; level--)
00798                 {
00799                         temp = *(current->mForward + level);
00800                         while (  (temp)
00801                                    &&(temp->mIndex < index))
00802                         {
00803                                 current = temp;
00804                                 temp = *(current->mForward + level);
00805                                 mNumberOfSteps++;
00806                         }
00807                         *(mUpdate + level) = current;
00808                 }
00809         }
00810         
00811         // we're now just in front of where we want to be . . . take one step forward
00812         mNumberOfSteps++;
00813         current = *current->mForward;
00814 
00815         if (current)
00816         {
00817                 if (mEquals(current->mIndex, index))
00818                 {
00819                         return current->mData;
00820                 }
00821         }
00822 
00823         // Avoid Linux compiler warning on returning NULL.
00824         return (DATA_T)0;
00825 }
00826 
00827 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00828 inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::reverseLookup(const DATA_T datap)
00829 {
00830         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
00831 
00832         while (current)
00833         {
00834                 if (datap == current->mData)
00835                 {
00836                         
00837                         return current->mIndex;
00838                 }
00839                 current = *current->mForward;
00840         }
00841 
00842         // not found! return NULL
00843         return INDEX_T();
00844 }
00845 
00846 // returns number of items in the list
00847 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00848 inline S32 LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getLength()
00849 {
00850         U32     length = 0;
00851         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>* temp;
00852         for (temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0])
00853         {
00854                 length++;
00855         }
00856         
00857         return length;
00858 }
00859 
00860 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00861 inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeData(const INDEX_T &index)
00862 {
00863         S32                     level;
00864         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
00865         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
00866 
00867         // find the pointer one in front of the one we want
00868         if (mInsertFirst)
00869         {
00870                 for (level = mLevel - 1; level >= 0; level--)
00871                 {
00872                         temp = *(current->mForward + level);
00873                         while (  (temp)
00874                                    &&(mInsertFirst(temp->mIndex, index)))
00875                         {
00876                                 current = temp;
00877                                 temp = *(current->mForward + level);
00878                         }
00879                         *(mUpdate + level) = current;
00880                 }
00881         }
00882         else
00883         {
00884                 for (level = mLevel - 1; level >= 0; level--)
00885                 {
00886                         temp = *(current->mForward + level);
00887                         while (  (temp)
00888                                    &&(temp->mIndex < index))
00889                         {
00890                                 current = temp;
00891                                 temp = *(current->mForward + level);
00892                         }
00893                         *(mUpdate + level) = current;
00894                 }
00895         }
00896         
00897         // we're now just in front of where we want to be . . . take one step forward
00898         current = *current->mForward;
00899 
00900         if (!current)
00901         {
00902                 // empty list or beyond the end!
00903                 
00904                 return FALSE;
00905         }
00906 
00907         // is this the one we want?
00908         if (!mEquals(current->mIndex, index))
00909         {
00910                 // nope!
00911                 
00912                 return FALSE;
00913         }
00914         else
00915         {
00916                 // do we need to fix current or currentop?
00917                 if (current == mCurrentp)
00918                 {
00919                         mCurrentp = *current->mForward;
00920                 }
00921 
00922                 if (current == mCurrentOperatingp)
00923                 {
00924                         mCurrentOperatingp = *current->mForward;
00925                 }
00926                 // yes it is!  change pointers as required
00927                 for (level = 0; level < mLevel; level++)
00928                 {
00929                         if (*((*(mUpdate + level))->mForward + level) != current)
00930                         {
00931                                 // cool, we've fixed all the pointers!
00932                                 break;
00933                         }
00934                         *((*(mUpdate + level))->mForward + level) = *(current->mForward + level);
00935                 }
00936 
00937                 // clean up cuurent
00938                 current->removeData();
00939                 delete current;
00940 
00941                 // clean up mHead
00942                 while (  (mLevel > 1)
00943                            &&(!*(mHead.mForward + mLevel - 1)))
00944                 {
00945                         mLevel--;
00946                 }
00947         }
00948         
00949         return TRUE;
00950 }
00951 
00952 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
00953 inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteData(const INDEX_T &index)
00954 {
00955         S32                     level;
00956         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
00957         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
00958 
00959         // find the pointer one in front of the one we want
00960         if (mInsertFirst)
00961         {
00962                 for (level = mLevel - 1; level >= 0; level--)
00963                 {
00964                         temp = *(current->mForward + level);
00965                         while (  (temp)
00966                                    &&(mInsertFirst(temp->mIndex, index)))
00967                         {
00968                                 current = temp;
00969                                 temp = *(current->mForward + level);
00970                         }
00971                         *(mUpdate + level) = current;
00972                 }
00973         }
00974         else
00975         {
00976                 for (level = mLevel - 1; level >= 0; level--)
00977                 {
00978                         temp = *(current->mForward + level);
00979                         while (  (temp)
00980                                    &&(temp->mIndex < index))
00981                         {
00982                                 current = temp;
00983                                 temp = *(current->mForward + level);
00984                         }
00985                         *(mUpdate + level) = current;
00986                 }
00987         }
00988         
00989         // we're now just in front of where we want to be . . . take one step forward
00990         current = *current->mForward;
00991 
00992         if (!current)
00993         {
00994                 // empty list or beyond the end!
00995                 
00996                 return FALSE;
00997         }
00998 
00999         // is this the one we want?
01000         if (!mEquals(current->mIndex, index))
01001         {
01002                 // nope!
01003                 
01004                 return FALSE;
01005         }
01006         else
01007         {
01008                 // do we need to fix current or currentop?
01009                 if (current == mCurrentp)
01010                 {
01011                         mCurrentp = *current->mForward;
01012                 }
01013 
01014                 if (current == mCurrentOperatingp)
01015                 {
01016                         mCurrentOperatingp = *current->mForward;
01017                 }
01018                 // yes it is!  change pointers as required
01019                 for (level = 0; level < mLevel; level++)
01020                 {
01021                         if (*((*(mUpdate + level))->mForward + level) != current)
01022                         {
01023                                 // cool, we've fixed all the pointers!
01024                                 break;
01025                         }
01026                         *((*(mUpdate + level))->mForward + level) = *(current->mForward + level);
01027                 }
01028 
01029                 // clean up cuurent
01030                 current->deleteData();
01031                 delete current;
01032 
01033                 // clean up mHead
01034                 while (  (mLevel > 1)
01035                            &&(!*(mHead.mForward + mLevel - 1)))
01036                 {
01037                         mLevel--;
01038                 }
01039         }
01040         
01041         return TRUE;
01042 }
01043 
01044 // remove all nodes from the list but do not delete data
01045 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
01046 void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeAllData()
01047 {
01048         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
01049         // reset mCurrentp
01050         mCurrentp = *(mHead.mForward);
01051 
01052         while (mCurrentp)
01053         {
01054                 temp = mCurrentp->mForward[0];
01055                 mCurrentp->removeData();
01056                 delete mCurrentp;
01057                 mCurrentp = temp;
01058         }
01059 
01060         S32 i;
01061         for (i = 0; i < BINARY_DEPTH; i++)
01062         {
01063                 mHead.mForward[i] = NULL;
01064                 mUpdate[i] = NULL;
01065         }
01066 
01067         mCurrentp = *(mHead.mForward);
01068         mCurrentOperatingp = *(mHead.mForward);
01069 }
01070 
01071 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
01072 inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteAllData()
01073 {
01074         LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
01075         // reset mCurrentp
01076         mCurrentp = *(mHead.mForward);
01077 
01078         while (mCurrentp)
01079         {
01080                 temp = mCurrentp->mForward[0];
01081                 mCurrentp->deleteData();
01082                 delete mCurrentp;
01083                 mCurrentp = temp;
01084         }
01085 
01086         S32 i;
01087         for (i = 0; i < BINARY_DEPTH; i++)
01088         {
01089                 mHead.mForward[i] = NULL;
01090                 mUpdate[i] = NULL;
01091         }
01092 
01093         mCurrentp = *(mHead.mForward);
01094         mCurrentOperatingp = *(mHead.mForward);
01095 }
01096 
01097 // place mCurrentp on first node
01098 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
01099 inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::resetList()
01100 {
01101         mCurrentp = *(mHead.mForward);
01102         mCurrentOperatingp = *(mHead.mForward);
01103 }
01104 
01105 
01106 // return the data currently pointed to
01107 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
01108 inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentDataWithoutIncrement()
01109 {
01110         if (mCurrentOperatingp)
01111         {
01112                 return mCurrentOperatingp->mData;
01113         }
01114         else
01115         {
01116                 //return NULL;          // causes warning
01117                 return (DATA_T)0;                       // equivalent, but no warning
01118         }
01119 }
01120 
01121 // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
01122 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
01123 inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentData()
01124 {
01125         if (mCurrentp)
01126         {
01127                 mCurrentOperatingp = mCurrentp;
01128                 mCurrentp = mCurrentp->mForward[0];
01129                 return mCurrentOperatingp->mData;
01130         }
01131         else
01132         {
01133                 //return NULL;          // causes warning
01134                 return (DATA_T)0;                       // equivalent, but no warning
01135         }
01136 }
01137 
01138 // same as getCurrentData() but a more intuitive name for the operation
01139 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
01140 inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getNextData()
01141 {
01142         if (mCurrentp)
01143         {
01144                 mCurrentOperatingp = mCurrentp;
01145                 mCurrentp = mCurrentp->mForward[0];
01146                 return mCurrentOperatingp->mData;
01147         }
01148         else
01149         {
01150                 //return NULL;  // causes compile warning
01151                 return (DATA_T)0;               // equivalent, but removes warning
01152         }
01153 }
01154 
01155 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
01156 inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getNextKey()
01157 {
01158         if (mCurrentp)
01159         {
01160                 mCurrentOperatingp = mCurrentp;
01161                 mCurrentp = mCurrentp->mForward[0];
01162                 return mCurrentOperatingp->mIndex;
01163         }
01164         else
01165         {
01166                 return mHead.mIndex;
01167         }
01168 }
01169 
01170 // return the key currently pointed to
01171 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
01172 inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentKeyWithoutIncrement()
01173 {
01174         if (mCurrentOperatingp)
01175         {
01176                 return mCurrentOperatingp->mIndex;
01177         }
01178         else
01179         {
01180                 //return NULL;  // causes compile warning
01181                 return (INDEX_T)0;              // equivalent, but removes warning
01182         }
01183 }
01184 
01185 
01186 // remove the Node at mCurentOperatingp
01187 // leave mCurrentp and mCurentOperatingp on the next entry
01188 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
01189 inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeCurrentData()
01190 {
01191         if (mCurrentOperatingp)
01192         {
01193                 removeData(mCurrentOperatingp->mIndex);
01194         }
01195 }
01196 
01197 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
01198 inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteCurrentData()
01199 {
01200         if (mCurrentOperatingp)
01201         {
01202                 deleteData(mCurrentOperatingp->mIndex);
01203         }
01204 }
01205 
01206 // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
01207 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
01208 inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getFirstData()
01209 {
01210         mCurrentp = *(mHead.mForward);
01211         mCurrentOperatingp = *(mHead.mForward);
01212         if (mCurrentp)
01213         {
01214                 mCurrentOperatingp = mCurrentp;
01215                 mCurrentp = mCurrentp->mForward[0];
01216                 return mCurrentOperatingp->mData;
01217         }
01218         else
01219         {
01220                 //return NULL;  // causes compile warning
01221                 return (DATA_T)0;               // equivalent, but removes warning
01222         }
01223 }
01224 
01225 template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
01226 inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getFirstKey()
01227 {
01228         mCurrentp = *(mHead.mForward);
01229         mCurrentOperatingp = *(mHead.mForward);
01230         if (mCurrentp)
01231         {
01232                 mCurrentOperatingp = mCurrentp;
01233                 mCurrentp = mCurrentp->mForward[0];
01234                 return mCurrentOperatingp->mIndex;
01235         }
01236         else
01237         {
01238                 return mHead.mIndex;
01239         }
01240 }
01241 
01242 #endif

Generated on Thu Jul 1 06:09:03 2010 for Second Life Viewer by  doxygen 1.4.7