RefHashTableOf.c
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:23k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /**
  57.  * $Log: RefHashTableOf.c,v $
  58.  * Revision 1.10  2003/05/18 14:02:05  knoaman
  59.  * Memory manager implementation: pass per instance manager.
  60.  *
  61.  * Revision 1.9  2003/05/16 21:36:59  knoaman
  62.  * Memory manager implementation: Modify constructors to pass in the memory manager.
  63.  *
  64.  * Revision 1.8  2003/05/15 19:04:35  knoaman
  65.  * Partial implementation of the configurable memory manager.
  66.  *
  67.  * Revision 1.7  2003/05/15 10:37:08  gareth
  68.  * Optimization. We now resize the hash when appropriate. Patch by Nathan Codding.
  69.  *
  70.  * Revision 1.6  2002/11/04 15:22:04  tng
  71.  * C++ Namespace Support.
  72.  *
  73.  * Revision 1.5  2002/07/11 18:49:53  knoaman
  74.  * Add setAdoptElements method.
  75.  * Rename removeBucketElemSafe to orphanKey.
  76.  *
  77.  * Revision 1.4  2002/07/05 11:31:04  tng
  78.  * Fix typo.
  79.  *
  80.  * Revision 1.3  2002/07/04 15:24:57  tng
  81.  * DOM L3: add transferElement and removeBucketElemSafe for use in DOMDocument::renameNode.
  82.  *
  83.  * Revision 1.2  2002/06/12 17:14:03  tng
  84.  * Add function cleanup, reinitialize and nextElementKey for ease of use.
  85.  *
  86.  * Revision 1.1.1.1  2002/02/01 22:22:12  peiyongz
  87.  * sane_include
  88.  *
  89.  * Revision 1.9  2001/07/19 18:43:18  peiyongz
  90.  * fix: detect null poiniter in enumerator's ctor.
  91.  *
  92.  * Revision 1.8  2001/06/04 13:45:04  tng
  93.  * The "hash" argument clashes with STL hash.  Fixed by Pei Yong Zhang.
  94.  *
  95.  * Revision 1.7  2000/09/06 00:24:16  andyh
  96.  * Clean up misc compiler warnings
  97.  *
  98.  * Revision 1.6  2000/07/07 22:16:50  jpolast
  99.  * remove old put(value) function.  use put(key,value) instead.
  100.  *
  101.  * Revision 1.5  2000/06/29 18:27:09  jpolast
  102.  * bug fix for passing hasher class references to constructor
  103.  *
  104.  * Revision 1.4  2000/06/27 22:11:12  jpolast
  105.  * added more general functionality to hashtables.
  106.  * able to specify which hasher to use.
  107.  * default: HashXMLCh [hashes XMLCh* strings]
  108.  *
  109.  * future todo: make hasher class references static so only
  110.  * one instance of a hasher is ever created.
  111.  *
  112.  * Revision 1.3  2000/03/02 19:54:44  roddey
  113.  * This checkin includes many changes done while waiting for the
  114.  * 1.1.0 code to be finished. I can't list them all here, but a list is
  115.  * available elsewhere.
  116.  *
  117.  * Revision 1.2  2000/02/06 07:48:03  rahulj
  118.  * Year 2K copyright swat.
  119.  *
  120.  * Revision 1.1.1.1  1999/11/09 01:04:59  twl
  121.  * Initial checkin
  122.  *
  123.  * Revision 1.2  1999/11/08 20:45:12  rahul
  124.  * Swat for adding in Product name and CVS comment log variable.
  125.  *
  126.  */
  127. // ---------------------------------------------------------------------------
  128. //  Include
  129. // ---------------------------------------------------------------------------
  130. #if defined(XERCES_TMPLSINC)
  131. #include <xercesc/util/RefHashTableOf.hpp>
  132. #endif
  133. #include <xercesc/util/NullPointerException.hpp>
  134. XERCES_CPP_NAMESPACE_BEGIN
  135. // ---------------------------------------------------------------------------
  136. //  RefHashTableOf: Constructors and Destructor
  137. // ---------------------------------------------------------------------------
  138. template <class TVal>
  139. RefHashTableOf<TVal>::RefHashTableOf( const unsigned int modulus
  140.                                     , const bool adoptElems
  141.                                     , MemoryManager* const manager)
  142.     : fMemoryManager(manager)
  143.     , fAdoptedElems(adoptElems)
  144.     , fBucketList(0)
  145.     , fHashModulus(modulus)
  146.     , fHash(0)
  147.     , fInitialModulus(modulus)
  148.     , fCount(0)
  149. {
  150.     initialize(modulus);
  151. // create default hasher
  152. fHash = new (fMemoryManager) HashXMLCh();
  153. }
  154. template <class TVal>
  155. RefHashTableOf<TVal>::RefHashTableOf( const unsigned int modulus
  156.                                     , const bool adoptElems
  157.                                     , HashBase* hashBase
  158.                                     , MemoryManager* const manager)
  159.     : fMemoryManager(manager)
  160.     , fAdoptedElems(adoptElems)
  161.     , fBucketList(0)
  162.     , fHashModulus(modulus)
  163.     , fHash(0)
  164.     , fInitialModulus(modulus)
  165.     , fCount(0)
  166. {
  167.     initialize(modulus);
  168.     // set hasher
  169.     fHash = hashBase;
  170. }
  171. template <class TVal>
  172. RefHashTableOf<TVal>::RefHashTableOf(const unsigned int modulus
  173.                                      , MemoryManager* const manager)
  174.     : fMemoryManager(manager)
  175.     , fAdoptedElems(true)
  176.     , fBucketList(0)
  177.     , fHashModulus(modulus)
  178.     , fHash(0)
  179.     , fInitialModulus(modulus)
  180.     , fCount(0)
  181. {
  182.     initialize(modulus);
  183.     // create default hasher
  184.     fHash = new (fMemoryManager) HashXMLCh();
  185. }
  186. template <class TVal> void RefHashTableOf<TVal>::initialize(const unsigned int modulus)
  187. {
  188.     if (modulus == 0)
  189.         ThrowXML(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus);
  190.     // Allocate the bucket list and zero them
  191.     fBucketList = (RefHashTableBucketElem<TVal>**) fMemoryManager->allocate
  192.     (
  193.         fHashModulus * sizeof(RefHashTableBucketElem<TVal>*)
  194.     ); //new RefHashTableBucketElem<TVal>*[fHashModulus];
  195.     for (unsigned int index = 0; index < fHashModulus; index++)
  196.         fBucketList[index] = 0;
  197. }
  198. template <class TVal> RefHashTableOf<TVal>::~RefHashTableOf()
  199. {
  200.     removeAll();
  201.     // Then delete the bucket list & hasher
  202.     fMemoryManager->deallocate(fBucketList); //delete [] fBucketList;
  203.     delete fHash;
  204. }
  205. // ---------------------------------------------------------------------------
  206. //  RefHashTableOf: Element management
  207. // ---------------------------------------------------------------------------
  208. template <class TVal> bool RefHashTableOf<TVal>::isEmpty() const
  209. {
  210.     // Just check the bucket list for non-empty elements
  211.     for (unsigned int buckInd = 0; buckInd < fHashModulus; buckInd++)
  212.     {
  213.         if (fBucketList[buckInd] != 0)
  214.             return false;
  215.     }
  216.     return true;
  217. }
  218. template <class TVal> bool RefHashTableOf<TVal>::
  219. containsKey(const void* const key) const
  220. {
  221.     unsigned int hashVal;
  222.     const RefHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
  223.     return (findIt != 0);
  224. }
  225. template <class TVal> void RefHashTableOf<TVal>::
  226. removeKey(const void* const key)
  227. {
  228.     unsigned int hashVal;
  229.     removeBucketElem(key, hashVal);
  230. }
  231. template <class TVal> void RefHashTableOf<TVal>::removeAll()
  232. {
  233.     // Clean up the buckets first
  234.     for (unsigned int buckInd = 0; buckInd < fHashModulus; buckInd++)
  235.     {
  236.         // Get the bucket list head for this entry
  237.         RefHashTableBucketElem<TVal>* curElem = fBucketList[buckInd];
  238.         RefHashTableBucketElem<TVal>* nextElem;
  239.         while (curElem)
  240.         {
  241.             // Save the next element before we hose this one
  242.             nextElem = curElem->fNext;
  243.             // If we adopted the data, then delete it too
  244.             //    (Note:  the userdata hash table instance has data type of void *.
  245.             //    This will generate compiler warnings here on some platforms, but they
  246.             //    can be ignored since fAdoptedElements is false.
  247.             if (fAdoptedElems)
  248.                 delete curElem->fData;
  249.             // Then delete the current element and move forward
  250.             delete curElem;
  251.             curElem = nextElem;
  252.         }
  253.         // Clean out this entry
  254.         fBucketList[buckInd] = 0;
  255.     }
  256.     fCount = 0;
  257. }
  258. // This method returns the data associated with a key. The key entry is deleted. The caller
  259. // now owns the returned data (case of hashtable adopting the data).
  260. // This function is called by transferElement so that the undeleted data can be transferred
  261. // to a new key which will own that data.
  262. template <class TVal> TVal* RefHashTableOf<TVal>::
  263. orphanKey(const void* const key)
  264. {
  265.     // Hash the key
  266.     TVal* retVal = 0;
  267.     unsigned int hashVal = fHash->getHashVal(key, fHashModulus);
  268.     if (hashVal > fHashModulus)
  269.         ThrowXML(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey);
  270.     //
  271.     //  Search the given bucket for this key. Keep up with the previous
  272.     //  element so we can patch around it.
  273.     //
  274.     RefHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
  275.     RefHashTableBucketElem<TVal>* lastElem = 0;
  276.     while (curElem)
  277.     {
  278.         if (fHash->equals(key, curElem->fKey))
  279.         {
  280.             if (!lastElem)
  281.             {
  282.                 // It was the first in the bucket
  283.                 fBucketList[hashVal] = curElem->fNext;
  284.             }
  285.              else
  286.             {
  287.                 // Patch around the current element
  288.                 lastElem->fNext = curElem->fNext;
  289.             }
  290.             retVal = curElem->fData;
  291.             // Delete the current element
  292.             delete curElem;
  293.             break;
  294.         }
  295.         // Move both pointers upwards
  296.         lastElem = curElem;
  297.         curElem = curElem->fNext;
  298.     }
  299.     // We never found that key
  300.     if (!retVal)
  301.         ThrowXML(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists);
  302.     return retVal;
  303. }
  304. //
  305. // cleanup():
  306. //   similar to destructor
  307. //   called to cleanup the memory, in case destructor cannot be called
  308. //
  309. template <class TElem> void RefHashTableOf<TElem>::cleanup()
  310. {
  311.     removeAll();
  312.     // Then delete the bucket list & hasher
  313.     fMemoryManager->deallocate(fBucketList); //delete [] fBucketList;
  314.     fBucketList = 0;
  315.     delete fHash;
  316. }
  317. //
  318. // reinitialize():
  319. //   similar to constructor
  320. //   called to re-construct the fElemList from scratch again
  321. //
  322. template <class TElem> void RefHashTableOf<TElem>::reinitialize(HashBase* hashBase)
  323. {
  324.     if (fBucketList || fHash)
  325.         cleanup();
  326.     fHashModulus = fInitialModulus;
  327.     initialize(fHashModulus);
  328.     if (hashBase)
  329.         fHash = hashBase;
  330.     else
  331.         fHash = new (fMemoryManager) HashXMLCh();   // create default hasher
  332. }
  333. // this function transfer the data from key1 to key2
  334. // this is equivalent to calling
  335. //  1.  get(key1) to retrieve the data,
  336. //  2.  removeKey(key1),
  337. //  3.  and then put(key2, data)
  338. // except that the data is not deleted in "removeKey" even it is adopted so that it
  339. // can be transferred to key2.
  340. // whatever key2 has originally will be purged (if adopted)
  341. template <class TElem> void RefHashTableOf<TElem>::transferElement(const void* const key1, void* key2)
  342. {
  343.     put(key2, orphanKey(key1));
  344. }
  345. // ---------------------------------------------------------------------------
  346. //  RefHashTableOf: Getters
  347. // ---------------------------------------------------------------------------
  348. template <class TVal> TVal* RefHashTableOf<TVal>::get(const void* const key)
  349. {
  350.     unsigned int hashVal;
  351.     RefHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
  352.     if (!findIt)
  353.         return 0;
  354.     return findIt->fData;
  355. }
  356. template <class TVal> const TVal* RefHashTableOf<TVal>::
  357. get(const void* const key) const
  358. {
  359.     unsigned int hashVal;
  360.     const RefHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
  361.     if (!findIt)
  362.         return 0;
  363.     return findIt->fData;
  364. }
  365. template <class TVal>
  366. MemoryManager* RefHashTableOf<TVal>::getMemoryManager() const
  367. {
  368.     return fMemoryManager;
  369. }
  370. // ---------------------------------------------------------------------------
  371. //  RefHashTableOf: Getters
  372. // ---------------------------------------------------------------------------
  373. template <class TVal>
  374. void RefHashTableOf<TVal>::setAdoptElements(const bool aValue)
  375. {
  376.     fAdoptedElems = aValue;
  377. }
  378. // ---------------------------------------------------------------------------
  379. //  RefHashTableOf: Putters
  380. // ---------------------------------------------------------------------------
  381. template <class TVal> void RefHashTableOf<TVal>::put(void* key, TVal* const valueToAdopt)
  382. {
  383.     // Apply 0.75 load factor to find threshold.
  384.     unsigned int threshold = fHashModulus * 3 / 4;
  385.     
  386.     // If we've grown too big, expand the table and rehash.
  387.     if (fCount >= threshold)
  388.         rehash();
  389.     // First see if the key exists already
  390.     unsigned int hashVal;
  391.     RefHashTableBucketElem<TVal>* newBucket = findBucketElem(key, hashVal);
  392.     //
  393.     //  If so,then update its value. If not, then we need to add it to
  394.     //  the right bucket
  395.     //
  396.     if (newBucket)
  397.     {
  398.         if (fAdoptedElems)
  399.             delete newBucket->fData;
  400.         newBucket->fData = valueToAdopt;
  401. newBucket->fKey = key;
  402.     }
  403.      else
  404.     {
  405.         newBucket = new (fMemoryManager) RefHashTableBucketElem<TVal>(key, valueToAdopt, fBucketList[hashVal]);
  406.         fBucketList[hashVal] = newBucket;
  407.     }
  408.     fCount++;
  409. }
  410. // ---------------------------------------------------------------------------
  411. //  RefHashTableOf: Private methods
  412. // ---------------------------------------------------------------------------
  413. template <class TVal> void RefHashTableOf<TVal>::rehash()
  414. {
  415.     unsigned int index;
  416.     unsigned int oldMod = fHashModulus;
  417.     fHashModulus *= 2;
  418.     
  419.     RefHashTableBucketElem<TVal>** oldBucketList = fBucketList;
  420.     
  421.     fBucketList = (RefHashTableBucketElem<TVal>**) fMemoryManager->allocate
  422.     (
  423.         fHashModulus * sizeof(RefHashTableBucketElem<TVal>*)
  424.     );//new RefHashTableBucketElem<TVal>*[fHashModulus];
  425.     for (index = 0; index < fHashModulus; index++)
  426.         fBucketList[index] = 0;
  427.     
  428.     
  429.     // Rehash all existing entries.
  430.     for (index = 0; index < oldMod; index++)
  431.     {
  432.         // Get the bucket list head for this entry
  433.         RefHashTableBucketElem<TVal>* curElem = oldBucketList[index];
  434.         RefHashTableBucketElem<TVal>* nextElem;
  435.         while (curElem)
  436.         {
  437.             // Save the next element before we detach this one
  438.             nextElem = curElem->fNext;
  439.             unsigned int hashVal = fHash->getHashVal(curElem->fKey, fHashModulus);
  440.             if (hashVal > fHashModulus)
  441.                 ThrowXML(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey);
  442.             
  443.             RefHashTableBucketElem<TVal>* newHeadElem = fBucketList[hashVal];
  444.             
  445.             // Insert at the start of this bucket's list.
  446.             curElem->fNext = newHeadElem;
  447.             fBucketList[hashVal] = curElem;
  448.             
  449.             curElem = nextElem;
  450.         }
  451.     }
  452.             
  453.     fMemoryManager->deallocate(oldBucketList);//delete[] oldBucketList;
  454.     
  455. }
  456. template <class TVal> RefHashTableBucketElem<TVal>* RefHashTableOf<TVal>::
  457. findBucketElem(const void* const key, unsigned int& hashVal)
  458. {
  459.     // Hash the key
  460.     hashVal = fHash->getHashVal(key, fHashModulus);
  461.     if (hashVal > fHashModulus)
  462.         ThrowXML(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey);
  463.     // Search that bucket for the key
  464.     RefHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
  465.     while (curElem)
  466.     {
  467. if (fHash->equals(key, curElem->fKey))
  468.             return curElem;
  469.         curElem = curElem->fNext;
  470.     }
  471.     return 0;
  472. }
  473. template <class TVal> const RefHashTableBucketElem<TVal>* RefHashTableOf<TVal>::
  474. findBucketElem(const void* const key, unsigned int& hashVal) const
  475. {
  476.     // Hash the key
  477.     hashVal = fHash->getHashVal(key, fHashModulus);
  478.     if (hashVal > fHashModulus)
  479.         ThrowXML(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey);
  480.     // Search that bucket for the key
  481.     const RefHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
  482.     while (curElem)
  483.     {
  484.         if (fHash->equals(key, curElem->fKey))
  485.             return curElem;
  486.         curElem = curElem->fNext;
  487.     }
  488.     return 0;
  489. }
  490. template <class TVal> void RefHashTableOf<TVal>::
  491. removeBucketElem(const void* const key, unsigned int& hashVal)
  492. {
  493.     // Hash the key
  494.     hashVal = fHash->getHashVal(key, fHashModulus);
  495.     if (hashVal > fHashModulus)
  496.         ThrowXML(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey);
  497.     //
  498.     //  Search the given bucket for this key. Keep up with the previous
  499.     //  element so we can patch around it.
  500.     //
  501.     RefHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
  502.     RefHashTableBucketElem<TVal>* lastElem = 0;
  503.     while (curElem)
  504.     {
  505.         if (fHash->equals(key, curElem->fKey))
  506.         {
  507.             if (!lastElem)
  508.             {
  509.                 // It was the first in the bucket
  510.                 fBucketList[hashVal] = curElem->fNext;
  511.             }
  512.              else
  513.             {
  514.                 // Patch around the current element
  515.                 lastElem->fNext = curElem->fNext;
  516.             }
  517.             // If we adopted the elements, then delete the data
  518.             if (fAdoptedElems)
  519.                 delete curElem->fData;
  520.             // Delete the current element
  521.             delete curElem;
  522.             fCount--;
  523.             return;
  524.         }
  525.         // Move both pointers upwards
  526.         lastElem = curElem;
  527.         curElem = curElem->fNext;
  528.     }
  529.     // We never found that key
  530.     ThrowXML(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists);
  531. }
  532. // ---------------------------------------------------------------------------
  533. //  RefHashTableOfEnumerator: Constructors and Destructor
  534. // ---------------------------------------------------------------------------
  535. template <class TVal> RefHashTableOfEnumerator<TVal>::
  536. RefHashTableOfEnumerator(RefHashTableOf<TVal>* const toEnum, const bool adopt)
  537. : fAdopted(adopt), fCurElem(0), fCurHash((unsigned int)-1), fToEnum(toEnum)
  538. {
  539.     if (!toEnum)
  540.         ThrowXML(NullPointerException, XMLExcepts::CPtr_PointerIsZero);
  541.     //
  542.     //  Find the next available bucket element in the hash table. If it
  543.     //  comes back zero, that just means the table is empty.
  544.     //
  545.     //  Note that the -1 in the current hash tells it to start from the
  546.     //  beginning.
  547.     //
  548.     findNext();
  549. }
  550. template <class TVal> RefHashTableOfEnumerator<TVal>::~RefHashTableOfEnumerator()
  551. {
  552.     if (fAdopted)
  553.         delete fToEnum;
  554. }
  555. // ---------------------------------------------------------------------------
  556. //  RefHashTableOfEnumerator: Enum interface
  557. // ---------------------------------------------------------------------------
  558. template <class TVal> bool RefHashTableOfEnumerator<TVal>::hasMoreElements() const
  559. {
  560.     //
  561.     //  If our current has is at the max and there are no more elements
  562.     //  in the current bucket, then no more elements.
  563.     //
  564.     if (!fCurElem && (fCurHash == fToEnum->fHashModulus))
  565.         return false;
  566.     return true;
  567. }
  568. template <class TVal> TVal& RefHashTableOfEnumerator<TVal>::nextElement()
  569. {
  570.     // Make sure we have an element to return
  571.     if (!hasMoreElements())
  572.         ThrowXML(NoSuchElementException, XMLExcepts::Enum_NoMoreElements);
  573.     //
  574.     //  Save the current element, then move up to the next one for the
  575.     //  next time around.
  576.     //
  577.     RefHashTableBucketElem<TVal>* saveElem = fCurElem;
  578.     findNext();
  579.     return *saveElem->fData;
  580. }
  581. template <class TVal> void* RefHashTableOfEnumerator<TVal>::nextElementKey()
  582. {
  583.     // Make sure we have an element to return
  584.     if (!hasMoreElements())
  585.         ThrowXML(NoSuchElementException, XMLExcepts::Enum_NoMoreElements);
  586.     //
  587.     //  Save the current element, then move up to the next one for the
  588.     //  next time around.
  589.     //
  590.     RefHashTableBucketElem<TVal>* saveElem = fCurElem;
  591.     findNext();
  592.     return saveElem->fKey;
  593. }
  594. template <class TVal> void RefHashTableOfEnumerator<TVal>::Reset()
  595. {
  596.     fCurHash = (unsigned int)-1;
  597.     fCurElem = 0;
  598.     findNext();
  599. }
  600. // ---------------------------------------------------------------------------
  601. //  RefHashTableOfEnumerator: Private helper methods
  602. // ---------------------------------------------------------------------------
  603. template <class TVal> void RefHashTableOfEnumerator<TVal>::findNext()
  604. {
  605.     //
  606.     //  If there is a current element, move to its next element. If this
  607.     //  hits the end of the bucket, the next block will handle the rest.
  608.     //
  609.     if (fCurElem)
  610.         fCurElem = fCurElem->fNext;
  611.     //
  612.     //  If the current element is null, then we have to move up to the
  613.     //  next hash value. If that is the hash modulus, then we cannot
  614.     //  go further.
  615.     //
  616.     if (!fCurElem)
  617.     {
  618.         fCurHash++;
  619.         if (fCurHash == fToEnum->fHashModulus)
  620.             return;
  621.         // Else find the next non-empty bucket
  622.         while (true)
  623.         {
  624.             if (fToEnum->fBucketList[fCurHash])
  625.                 break;
  626.             // Bump to the next hash value. If we max out return
  627.             fCurHash++;
  628.             if (fCurHash == fToEnum->fHashModulus)
  629.                 return;
  630.         }
  631.         fCurElem = fToEnum->fBucketList[fCurHash];
  632.     }
  633. }
  634. XERCES_CPP_NAMESPACE_END