lllocalidhashmap.h

Go to the documentation of this file.
00001 
00032 #ifndef LL_LLLOCALIDHASHMAP_H
00033 #define LL_LLLOCALIDHASHMAP_H
00034 
00035 #include "stdtypes.h"
00036 #include "llerror.h"
00037 
00038 const S32 MAX_ITERS = 4;
00039 // LocalID hash map
00040 
00041 //
00042 // LLLocalIDHashNode
00043 //
00044 
00045 template <class DATA, int SIZE>
00046 class LLLocalIDHashNode
00047 {
00048 public:
00049         LLLocalIDHashNode();
00050 
00051 public:
00052         S32 mCount;
00053         U32     mKey[SIZE];
00054         DATA mData[SIZE];
00055         LLLocalIDHashNode<DATA, SIZE> *mNextNodep;
00056 };
00057 
00058 
00059 //
00060 // LLLocalIDHashNode implementation
00061 //
00062 template <class DATA, int SIZE>
00063 LLLocalIDHashNode<DATA, SIZE>::LLLocalIDHashNode()
00064 {
00065         mCount = 0;
00066         mNextNodep = NULL;
00067 }
00068 
00069 //
00070 // LLLocalIDHashMapIter
00071 //
00072 template <class DATA_TYPE, int SIZE>
00073 class LLLocalIDHashMap;
00074 
00075 template <class DATA_TYPE, int SIZE>
00076 class LLLocalIDHashMapIter
00077 {
00078 public:
00079         LLLocalIDHashMapIter(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp);
00080         ~LLLocalIDHashMapIter();
00081 
00082         void setMap(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp);
00083         inline void first();
00084         inline void next();
00085         inline DATA_TYPE& current(); // *NOTE: Deprecate? Phoenix 2005-04-15
00086         inline BOOL done() const;
00087         inline S32  currentBin() const;
00088         inline void setBin(S32 bin);
00089 
00090         DATA_TYPE& operator*() const
00091         {
00092                 return mCurHashNodep->mData[mCurHashNodeKey];
00093         }
00094         DATA_TYPE* operator->() const
00095         {
00096                 return &(operator*());
00097         }
00098 
00099         LLLocalIDHashMap<DATA_TYPE, SIZE> *mHashMapp;
00100         LLLocalIDHashNode<DATA_TYPE, SIZE> *mCurHashNodep;
00101 
00102         S32 mCurHashMapNodeNum;
00103         S32 mCurHashNodeKey;
00104 
00105         DATA_TYPE mNull;
00106 
00107         S32 mIterID;
00108 };
00109 
00110 
00111 
00112 template <class DATA_TYPE, int SIZE>
00113 class LLLocalIDHashMap
00114 {
00115 public:
00116         friend class LLLocalIDHashMapIter<DATA_TYPE, SIZE>;
00117 
00118         LLLocalIDHashMap(); // DO NOT use this unless you explicitly setNull, or the data type constructs a "null"
00119                                                 // object by default
00120         // basic constructor including sorter
00121         LLLocalIDHashMap(const DATA_TYPE &null_data);
00122         // Hack, this should really be a const ref, but I'm not doing it that way because the sim
00123         // usually uses pointers.
00124         ~LLLocalIDHashMap();
00125 
00126         inline DATA_TYPE &get(const U32 local_id);
00127         inline BOOL check(const U32 local_id) const;
00128         inline DATA_TYPE &set(const U32 local_id, const DATA_TYPE data);
00129         inline BOOL remove(const U32 local_id);
00130         void removeAll();
00131 
00132         void setNull(const DATA_TYPE data) { mNull = data; }
00133 
00134         inline S32 getLength() const; // Warning, NOT O(1!)
00135 
00136         void dumpIter();
00137         void dumpBin(U32 bin);
00138 
00139 protected:
00140         // Only used by the iterator.
00141         void addIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter);
00142         void removeIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter);
00143 
00144         // Remove the item and shift all items afterward down the list,
00145         // fixing up iterators as we go.
00146         BOOL removeWithShift(const U32 local_id);
00147 
00148 protected:
00149         LLLocalIDHashNode<DATA_TYPE, SIZE> mNodes[256];
00150 
00151         S32 mIterCount;
00152         LLLocalIDHashMapIter<DATA_TYPE, SIZE> *mIters[MAX_ITERS];
00153 
00154         DATA_TYPE mNull;
00155 };
00156 
00157 
00158 //
00159 // LLLocalIDHashMap implementation
00160 //
00161 
00162 template <class DATA_TYPE, int SIZE>
00163 LLLocalIDHashMap<DATA_TYPE, SIZE>::LLLocalIDHashMap()
00164 :       mIterCount(0),
00165         mNull()
00166 {
00167         S32 i;
00168         for (i = 0; i < MAX_ITERS; i++)
00169         {
00170                 mIters[i] = NULL;
00171         }
00172 }
00173 
00174 template <class DATA_TYPE, int SIZE>
00175 LLLocalIDHashMap<DATA_TYPE, SIZE>::LLLocalIDHashMap(const DATA_TYPE &null_data)
00176 :       mIterCount(0),
00177         mNull(null_data)
00178 {
00179         S32 i;
00180         for (i = 0; i < MAX_ITERS; i++)
00181         {
00182                 mIters[i] = NULL;
00183         }
00184 }
00185 
00186 template <class DATA_TYPE, int SIZE>
00187 LLLocalIDHashMap<DATA_TYPE, SIZE>::~LLLocalIDHashMap()
00188 {
00189         S32 i;
00190         for (i = 0; i < MAX_ITERS; i++)
00191         {
00192                 if (mIters[i])
00193                 {
00194                         mIters[i]->mHashMapp = NULL;
00195                         mIterCount--;
00196                 }
00197         }
00198         removeAll();
00199 }
00200 
00201 template <class DATA_TYPE, int SIZE>
00202 void LLLocalIDHashMap<DATA_TYPE, SIZE>::removeAll()
00203 {
00204         S32 bin;
00205         for (bin = 0; bin < 256; bin++)
00206         {
00207                 LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
00208 
00209                 BOOL first = TRUE;
00210                 do // First node guaranteed to be there
00211                 {
00212                         S32 i;
00213                         const S32 count = nodep->mCount;
00214 
00215                         // Iterate through all members of this node
00216                         for (i = 0; i < count; i++)
00217                         {
00218                                 nodep->mData[i] = mNull;
00219                         }
00220 
00221                         nodep->mCount = 0;
00222                         // Done with all objects in this node, go to the next.
00223 
00224                         LLLocalIDHashNode<DATA_TYPE, SIZE>* curp = nodep;
00225                         nodep = nodep->mNextNodep;
00226 
00227                         // Delete the node if it's not the first node
00228                         if (first)
00229                         {
00230                                 first = FALSE;
00231                                 curp->mNextNodep = NULL;
00232                         }
00233                         else
00234                         {
00235                                 delete curp;
00236                         }
00237                 } while (nodep);
00238         }
00239 }
00240 
00241 template <class DATA_TYPE, int SIZE>
00242 void LLLocalIDHashMap<DATA_TYPE, SIZE>::dumpIter()
00243 {
00244         std::cout << "Hash map with " << mIterCount << " iterators" << std::endl;
00245 
00246         std::cout << "Hash Map Iterators:" << std::endl;
00247         S32 i;
00248         for (i = 0; i < MAX_ITERS; i++)
00249         {
00250                 if (mIters[i])
00251                 {
00252                         llinfos << i << " " << mIters[i]->mCurHashNodep << " " << mIters[i]->mCurHashNodeKey << llendl;
00253                 }
00254                 else
00255                 {
00256                         llinfos << i << "null" << llendl;
00257                 }
00258         }
00259 }
00260 
00261 template <class DATA_TYPE, int SIZE>
00262 void LLLocalIDHashMap<DATA_TYPE, SIZE>::dumpBin(U32 bin)
00263 {
00264         std::cout << "Dump bin " << bin << std::endl;
00265 
00266         LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
00267         S32 node = 0;
00268         do // First node guaranteed to be there.
00269         {
00270                 std::cout << "Bin " << bin 
00271                         << " node " << node
00272                         << " count " << nodep->mCount
00273                         << " contains " << std::flush;
00274 
00275                 S32 i;
00276                 for (i = 0; i < nodep->mCount; i++)
00277                 {
00278                         std::cout << nodep->mData[i] << " " << std::flush;
00279                 }
00280 
00281                 std::cout << std::endl;
00282 
00283                 nodep = nodep->mNextNodep;
00284                 node++;
00285         } while (nodep);
00286 }
00287 
00288 template <class DATA_TYPE, int SIZE>
00289 inline S32 LLLocalIDHashMap<DATA_TYPE, SIZE>::getLength() const
00290 {
00291         S32 count = 0;
00292         S32 bin;
00293         for (bin = 0; bin < 256; bin++)
00294         {
00295                 const LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
00296                 while (nodep)
00297                 {
00298                         count += nodep->mCount;
00299                         nodep = nodep->mNextNodep;
00300                 }
00301         }
00302         return count;
00303 }
00304 
00305 template <class DATA_TYPE, int SIZE>
00306 inline DATA_TYPE &LLLocalIDHashMap<DATA_TYPE, SIZE>::get(const U32 local_id)
00307 {
00308         LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
00309 
00310         do // First node guaranteed to be there
00311         {
00312                 S32 i;
00313                 const S32 count = nodep->mCount;
00314 
00315                 // Iterate through all members of this node
00316                 for (i = 0; i < count; i++)
00317                 {
00318                         if (nodep->mKey[i] == local_id)
00319                         {
00320                                 // We found it.
00321                                 return nodep->mData[i];
00322                         }
00323                 }
00324 
00325                 // Done with all objects in this node, go to the next.
00326                 nodep = nodep->mNextNodep;
00327         } while (nodep);
00328 
00329         return mNull;
00330 }
00331 
00332 
00333 template <class DATA_TYPE, int SIZE>
00334 inline BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::check(const U32 local_id) const
00335 {
00336         const LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
00337 
00338         do // First node guaranteed to be there
00339         {
00340                 S32 i;
00341                 const S32 count = nodep->mCount;
00342 
00343                 // Iterate through all members of this node
00344                 for (i = 0; i < count; i++)
00345                 {
00346                         if (nodep->mKey[i] == local_id)
00347                         {
00348                                 // We found it.
00349                                 return TRUE;
00350                         }
00351                 }
00352 
00353                 // Done with all objects in this node, go to the next.
00354                 nodep = nodep->mNextNodep;
00355         } while (nodep);
00356 
00357         // Didn't find anything
00358         return FALSE;
00359 }
00360 
00361 
00362 template <class DATA_TYPE, int SIZE>
00363 inline DATA_TYPE &LLLocalIDHashMap<DATA_TYPE, SIZE>::set(const U32 local_id, const DATA_TYPE data)
00364 {
00365         // Set is just like a normal find, except that if we find a match
00366         // we replace it with the input value.
00367         // If we don't find a match, we append to the end of the list.
00368 
00369         LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
00370 
00371         while (1)
00372         {
00373                 const S32 count = nodep->mCount;
00374 
00375                 S32 i;
00376                 for (i = 0; i < count; i++)
00377                 {
00378                         if (nodep->mKey[i] == local_id)
00379                         {
00380                                 // We found a match for this key, replace the data with
00381                                 // the incoming data.
00382                                 nodep->mData[i] = data;
00383                                 return nodep->mData[i];
00384                         }
00385                 }
00386                 if (!nodep->mNextNodep)
00387                 {
00388                         // We've iterated through all of the keys without finding a match
00389                         if (i < SIZE)
00390                         {
00391                                 // There's still some space on this node, append
00392                                 // the key and data to it.
00393                                 nodep->mKey[i] = local_id;
00394                                 nodep->mData[i] = data;
00395                                 nodep->mCount++;
00396 
00397                                 return nodep->mData[i];
00398                         }
00399                         else
00400                         {
00401                                 // This node is full, append a new node to the end.
00402                                 nodep->mNextNodep = new LLLocalIDHashNode<DATA_TYPE, SIZE>;
00403                                 nodep->mNextNodep->mKey[0] = local_id;
00404                                 nodep->mNextNodep->mData[0] = data;
00405                                 nodep->mNextNodep->mCount = 1;
00406 
00407                                 return nodep->mNextNodep->mData[0];
00408                         }
00409                 }
00410 
00411                 // No match on this node, go to the next
00412                 nodep = nodep->mNextNodep;
00413         }
00414 }
00415 
00416 
00417 template <class DATA_TYPE, int SIZE>
00418 inline BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::remove(const U32 local_id)
00419 {
00420         // Remove is the trickiest operation.
00421         // What we want to do is swap the last element of the last
00422         // node if we find the one that we want to remove, but we have
00423         // to deal with deleting the node from the tail if it's empty, but
00424         // NOT if it's the only node left.
00425 
00426         const S32 node_index = local_id & 0xff;
00427 
00428         LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[node_index];
00429 
00430         // A modification of the standard search algorithm.
00431         do // First node guaranteed to be there
00432         {
00433                 const S32 count = nodep->mCount;
00434 
00435                 S32 i;
00436                 for (i = 0; i < count; i++)
00437                 {
00438                         if (nodep->mKey[i] == local_id)
00439                         {
00440                                 // If we're removing the item currently pointed to by one
00441                                 // or more iterators, we can just swap in the last item
00442                                 // and back the iterator(s) up by one.
00443                                 // Otherwise, we need to do a slow and safe shift of all
00444                                 // items back to one position to fill the hole and fix up 
00445                                 // all iterators we find.
00446                                 BOOL need_shift = FALSE;
00447                                 S32 cur_iter;
00448                                 if (mIterCount)
00449                                 {
00450                                         for (cur_iter = 0; cur_iter < MAX_ITERS; cur_iter++)
00451                                         {
00452                                                 if (mIters[cur_iter])
00453                                                 {
00454                                                         // We only care if the hash map node is on the one
00455                                                         // that we're working on.  If it's before, we've already
00456                                                         // traversed it, if it's after, changing the order doesn't
00457                                                         // matter.
00458                                                         if (mIters[cur_iter]->mCurHashMapNodeNum == node_index)
00459                                                         {
00460                                                                 if ((mIters[cur_iter]->mCurHashNodep == nodep)
00461                                                                         && (mIters[cur_iter]->mCurHashNodeKey == i))
00462                                                                 {
00463                                                                         // it's on the one we're deleting, we'll
00464                                                                         // fix the iterator quickly below.
00465                                                                 }
00466                                                                 else
00467                                                                 {
00468                                                                         // We're trying to remove an item on this
00469                                                                         // iterator's chain that this
00470                                                                         // iterator doesn't point to!  We need to do
00471                                                                         // the slow remove-and-shift-down case.
00472                                                                         need_shift = TRUE;
00473                                                                 }
00474                                                         }
00475                                                 }
00476                                         }
00477                                 }
00478 
00479                                 // Removing an item that isn't pointed to by all iterators
00480                                 if (need_shift)
00481                                 {
00482                                         return removeWithShift(local_id);
00483                                 }
00484 
00485                                 // Fix the iterators that point to this node/i pair, the
00486                                 // one we're deleting
00487                                 for (cur_iter = 0; cur_iter < MAX_ITERS; cur_iter++)
00488                                 {
00489                                         if (mIters[cur_iter])
00490                                         {
00491                                                 // We only care if the hash map node is on the one
00492                                                 // that we're working on.  If it's before, we've already
00493                                                 // traversed it, if it's after, changing the order doesn't
00494                                                 // matter.
00495                                                 if (mIters[cur_iter]->mCurHashMapNodeNum == node_index)
00496                                                 {
00497                                                         if ((mIters[cur_iter]->mCurHashNodep == nodep)
00498                                                                 && (mIters[cur_iter]->mCurHashNodeKey == i))
00499                                                         {
00500                                                                 // We can handle the case where we're deleting 
00501                                                                 // the element we're on trivially (sort of).
00502                                                                 if (nodep->mCount > 1)
00503                                                                 {
00504                                                                         // If we're not going to delete this node,
00505                                                                         // it's OK.
00506                                                                         mIters[cur_iter]->mCurHashNodeKey--;
00507                                                                 }
00508                                                                 else
00509                                                                 {
00510                                                                         // We're going to delete this node, because this
00511                                                                         // is the last element on it.
00512                                                                         
00513                                                                         // Find the next node, and then back up one.
00514                                                                         mIters[cur_iter]->next();
00515                                                                         mIters[cur_iter]->mCurHashNodeKey--;
00516                                                                 }
00517                                                         }
00518                                                 }
00519                                         }
00520                                 }
00521 
00522                                 // We found the node that we want to remove.
00523                                 // Find the last (and next-to-last) node, and the index of the last
00524                                 // element.  We could conceviably start from the node we're on,
00525                                 // but that makes it more complicated, this is easier.
00526 
00527                                 LLLocalIDHashNode<DATA_TYPE, SIZE> *prevp = &mNodes[node_index];
00528                                 LLLocalIDHashNode<DATA_TYPE, SIZE> *lastp = prevp;
00529 
00530                                 // Find the last and next-to-last
00531                                 while (lastp->mNextNodep)
00532                                 {
00533                                         prevp = lastp;
00534                                         lastp = lastp->mNextNodep;
00535                                 }
00536 
00537                                 // First, swap in the last to the current location.
00538                                 nodep->mKey[i] = lastp->mKey[lastp->mCount - 1];
00539                                 nodep->mData[i] = lastp->mData[lastp->mCount - 1];
00540 
00541                                 // Now, we delete the entry
00542                                 lastp->mCount--;
00543                                 lastp->mData[lastp->mCount] = mNull;
00544 
00545                                 if (!lastp->mCount)
00546                                 {
00547                                         // We deleted the last element!
00548                                         if (lastp != &mNodes[local_id & 0xff])
00549                                         {
00550                                                 // Only blitz the node if it's not the head
00551                                                 // Set the previous node to point to NULL, then
00552                                                 // blitz the empty last node
00553                                                 prevp->mNextNodep = NULL;
00554                                                 delete lastp;
00555                                         }
00556                                 }
00557 
00558                                 return TRUE;
00559                         }
00560                 }
00561 
00562                 // Iterate to the next node, we've scanned all the entries in this one.
00563                 nodep = nodep->mNextNodep;
00564         } while (nodep);
00565 
00566         return FALSE;
00567 }
00568 
00569 template <class DATA_TYPE, int SIZE>
00570 BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::removeWithShift(const U32 local_id)
00571 {
00572         const S32 node_index = local_id & 0xFF;
00573         LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[node_index];
00574         LLLocalIDHashNode<DATA_TYPE, SIZE>* prevp = NULL;
00575         BOOL found = FALSE;
00576 
00577         do // First node guaranteed to be there
00578         {
00579                 const S32 count = nodep->mCount;
00580                 S32 i;
00581                 for (i = 0; i < count; i++)
00582                 {
00583                         if (nodep->mKey[i] == local_id)
00584                         {
00585                                 // Found the item.  Start shifting items from later
00586                                 // in the list over this item.
00587                                 found = TRUE;
00588                         }
00589 
00590                         if (found)
00591                         {
00592                                 // If there is an iterator on this node, we need to 
00593                                 // back it up.
00594                                 S32 cur_iter;
00595                                 for (cur_iter = 0; cur_iter <MAX_ITERS; cur_iter++)
00596                                 {
00597                                         LLLocalIDHashMapIter<DATA_TYPE, SIZE>* iter;
00598                                         iter = mIters[cur_iter];
00599                                         // If an iterator is on this node,i pair, then back it up.
00600                                         if (iter
00601                                                 && iter->mCurHashMapNodeNum == node_index
00602                                                 && iter->mCurHashNodep == nodep
00603                                                 && iter->mCurHashNodeKey == i)
00604                                         {
00605                                                 if (i > 0)
00606                                                 {
00607                                                         // Don't need to move iterator nodep, since 
00608                                                         // we're in the same node.
00609                                                         iter->mCurHashNodeKey--;
00610                                                 }
00611                                                 else if (prevp)
00612                                                 {
00613                                                         // need to go the previous node, last item
00614                                                         iter->mCurHashNodep = prevp;
00615                                                         iter->mCurHashNodeKey = prevp->mCount - 1;
00616                                                 }
00617                                                 else
00618                                                 {
00619                                                         // we're on the first item in the list, but
00620                                                         // need to go back anyhow.
00621 
00622                                                         // BUG: If this deletion empties the list, 
00623                                                         // iter->done() will be wrong until
00624                                                         // iter->next() is called.
00625                                                         iter->mCurHashNodeKey = -1;
00626                                                 }
00627                                         }
00628                                 }
00629 
00630                                 // Copy data from the next position into this position.
00631                                 if (i < count-1)
00632                                 {
00633                                         // we're not on the last item in the node,
00634                                         // so we can copy within the node
00635                                         nodep->mKey[i] = nodep->mKey[i+1];
00636                                         nodep->mData[i] = nodep->mData[i+1];
00637                                 }
00638                                 else if (nodep->mNextNodep)
00639                                 {
00640                                         // we're on the last item in the node,
00641                                         // but there's a next node we can copy from
00642                                         nodep->mKey[i] = nodep->mNextNodep->mKey[0];
00643                                         nodep->mData[i] = nodep->mNextNodep->mData[0];
00644                                 }
00645                                 else
00646                                 {
00647                                         // We're on the last position in the list.
00648                                         // No one to copy from.  Replace with nothing.
00649                                         nodep->mKey[i] = 0;
00650                                         nodep->mData[i] = mNull;
00651                                 }
00652                         }
00653                 }
00654 
00655                 // Last node in chain, so delete the last node
00656                 if (found
00657                         && !nodep->mNextNodep)
00658                 {
00659                         // delete the last item off the last node
00660                         nodep->mCount--;
00661 
00662                         if (nodep->mCount == 0)
00663                         {
00664                                 // We deleted the last element!
00665                                 if (nodep != &mNodes[node_index])
00666                                 {
00667                                         // Always have a prevp if we're not the head.
00668                                         llassert(prevp);
00669 
00670                                         // Only blitz the node if it's not the head
00671                                         // Set the previous node to point to NULL, then
00672                                         // blitz the empty last node
00673                                         prevp->mNextNodep = NULL;
00674                                         delete nodep;
00675                                         nodep = NULL;
00676                                 }
00677                         }
00678 
00679                         // Deleted last item in chain, so we're done.
00680                         return found;
00681                 }
00682 
00683                 prevp = nodep;
00684                 nodep = nodep->mNextNodep;
00685         } while (nodep);
00686 
00687         return found;
00688 }
00689 
00690 template <class DATA_TYPE, int SIZE>
00691 void LLLocalIDHashMap<DATA_TYPE, SIZE>::removeIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter)
00692 {
00693         S32 i;
00694         for (i = 0; i < MAX_ITERS; i++)
00695         {
00696                 if (mIters[i] == iter)
00697                 {
00698                         mIters[i] = NULL;
00699                         mIterCount--;
00700                         return;
00701                 }
00702         }
00703         llerrs << "Iterator " << iter << " not found for removal in hash map!" << llendl;
00704 }
00705 
00706 template <class DATA_TYPE, int SIZE>
00707 void LLLocalIDHashMap<DATA_TYPE, SIZE>::addIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter)
00708 {
00709         S32 i;
00710         for (i = 0; i < MAX_ITERS; i++)
00711         {
00712                 if (mIters[i] == NULL)
00713                 {
00714                         mIters[i] = iter;
00715                         mIterCount++;
00716                         return;
00717                 }
00718         }
00719         llerrs << "More than " << MAX_ITERS << " iterating over a map simultaneously!" << llendl;
00720 }
00721 
00722 
00723 
00724 //
00725 // LLLocalIDHashMapIter Implementation
00726 //
00727 template <class DATA_TYPE, int SIZE>
00728 LLLocalIDHashMapIter<DATA_TYPE, SIZE>::LLLocalIDHashMapIter(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp)
00729 {
00730         mHashMapp = NULL;
00731         setMap(hash_mapp);
00732 }
00733 
00734 template <class DATA_TYPE, int SIZE>
00735 LLLocalIDHashMapIter<DATA_TYPE, SIZE>::~LLLocalIDHashMapIter()
00736 {
00737         if (mHashMapp)
00738         {
00739                 mHashMapp->removeIter(this);
00740         }
00741 }
00742 
00743 template <class DATA_TYPE, int SIZE>
00744 void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::setMap(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp)
00745 {
00746         if (mHashMapp)
00747         {
00748                 mHashMapp->removeIter(this);
00749         }
00750         mHashMapp = hash_mapp;
00751         if (mHashMapp)
00752         {
00753                 mHashMapp->addIter(this);
00754         }
00755 
00756         mCurHashNodep = NULL;
00757         mCurHashMapNodeNum = -1;
00758         mCurHashNodeKey = 0;
00759 }
00760 
00761 template <class DATA_TYPE, int SIZE>
00762 inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::first()
00763 {
00764         // Iterate through until we find the first non-empty node;
00765         S32 i;
00766         for (i = 0; i < 256; i++)
00767         {
00768                 if (mHashMapp->mNodes[i].mCount)
00769                 {
00770 
00771                         mCurHashNodep = &mHashMapp->mNodes[i];
00772                         mCurHashMapNodeNum = i;
00773                         mCurHashNodeKey = 0;
00774                         //return mCurHashNodep->mData[0];
00775                         return;
00776                 }
00777         }
00778 
00779         // Completely empty!
00780         mCurHashNodep = NULL;
00781         //return mNull;
00782         return;
00783 }
00784 
00785 template <class DATA_TYPE, int SIZE>
00786 inline BOOL LLLocalIDHashMapIter<DATA_TYPE, SIZE>::done() const
00787 {
00788         return mCurHashNodep ? FALSE : TRUE;
00789 }
00790 
00791 template <class DATA_TYPE, int SIZE>
00792 inline S32 LLLocalIDHashMapIter<DATA_TYPE, SIZE>::currentBin() const
00793 {
00794         if (  (mCurHashMapNodeNum > 255)
00795                 ||(mCurHashMapNodeNum < 0))
00796         {
00797                 return 0;
00798         }
00799         else
00800         {
00801                 return mCurHashMapNodeNum;
00802         }
00803 }
00804 
00805 template <class DATA_TYPE, int SIZE>
00806 inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::setBin(S32 bin)
00807 {
00808         // Iterate through until we find the first non-empty node;
00809         S32 i;
00810         bin = llclamp(bin, 0, 255);
00811         for (i = bin; i < 256; i++)
00812         {
00813                 if (mHashMapp->mNodes[i].mCount)
00814                 {
00815 
00816                         mCurHashNodep = &mHashMapp->mNodes[i];
00817                         mCurHashMapNodeNum = i;
00818                         mCurHashNodeKey = 0;
00819                         return;
00820                 }
00821         }
00822         for (i = 0; i < bin; i++)
00823         {
00824                 if (mHashMapp->mNodes[i].mCount)
00825                 {
00826 
00827                         mCurHashNodep = &mHashMapp->mNodes[i];
00828                         mCurHashMapNodeNum = i;
00829                         mCurHashNodeKey = 0;
00830                         return;
00831                 }
00832         }
00833         // Completely empty!
00834         mCurHashNodep = NULL;
00835 }
00836 
00837 template <class DATA_TYPE, int SIZE>
00838 inline DATA_TYPE &LLLocalIDHashMapIter<DATA_TYPE, SIZE>::current()
00839 {
00840         if (!mCurHashNodep)
00841         {
00842                 return mNull;
00843         }
00844         return mCurHashNodep->mData[mCurHashNodeKey];
00845 }
00846 
00847 template <class DATA_TYPE, int SIZE>
00848 inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::next()
00849 {
00850         // No current entry, this iterator is done
00851         if (!mCurHashNodep)
00852         {
00853                 //return mNull;
00854                 return;
00855         }
00856 
00857         // Go to the next element
00858         mCurHashNodeKey++;
00859         if (mCurHashNodeKey < mCurHashNodep->mCount)
00860         {
00861                 // We're not done with this node, return the current element
00862                 //return mCurHashNodep->mData[mCurHashNodeKey];
00863                 return;
00864         }
00865 
00866         // Done with this node, move to the next
00867         mCurHashNodep = mCurHashNodep->mNextNodep;
00868         if (mCurHashNodep)
00869         {
00870                 // Return the first element
00871                 mCurHashNodeKey = 0;
00872                 //return mCurHashNodep->mData[0];
00873                 return;
00874         }
00875 
00876         // Find the next non-empty node (keyed on the first byte)
00877         mCurHashMapNodeNum++;
00878 
00879         S32 i;
00880         for (i = mCurHashMapNodeNum; i < 256; i++)
00881         {
00882                 if (mHashMapp->mNodes[i].mCount)
00883                 {
00884                         // We found one that wasn't empty
00885                         mCurHashNodep = &mHashMapp->mNodes[i];
00886                         mCurHashMapNodeNum = i;
00887                         mCurHashNodeKey = 0;
00888                         //return mCurHashNodep->mData[0];
00889                         return;
00890                 }
00891         }
00892 
00893         // OK, we're done, nothing else to iterate
00894         mCurHashNodep = NULL;
00895         mHashMapp->mIterCount--; // Decrement since we're safe to do removes now
00896         //return mNull;
00897         return;
00898 }
00899 
00900 #endif // LL_LLLOCALIDHASHMAP_H

Generated on Thu Jul 1 06:08:49 2010 for Second Life Viewer by  doxygen 1.4.7