RefHashTableOf.c
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:15k
源码类别:

xml/soap/webservice

开发平台:

C/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.9  2001/07/19 18:43:18  peiyongz
  59.  * fix: detect null poiniter in enumerator's ctor.
  60.  *
  61.  * Revision 1.8  2001/06/04 13:45:04  tng
  62.  * The "hash" argument clashes with STL hash.  Fixed by Pei Yong Zhang.
  63.  *
  64.  * Revision 1.7  2000/09/06 00:24:16  andyh
  65.  * Clean up misc compiler warnings
  66.  *
  67.  * Revision 1.6  2000/07/07 22:16:50  jpolast
  68.  * remove old put(value) function.  use put(key,value) instead.
  69.  *
  70.  * Revision 1.5  2000/06/29 18:27:09  jpolast
  71.  * bug fix for passing hasher class references to constructor
  72.  *
  73.  * Revision 1.4  2000/06/27 22:11:12  jpolast
  74.  * added more general functionality to hashtables.
  75.  * able to specify which hasher to use.
  76.  * default: HashXMLCh [hashes XMLCh* strings]
  77.  *
  78.  * future todo: make hasher class references static so only
  79.  * one instance of a hasher is ever created.
  80.  *
  81.  * Revision 1.3  2000/03/02 19:54:44  roddey
  82.  * This checkin includes many changes done while waiting for the
  83.  * 1.1.0 code to be finished. I can't list them all here, but a list is
  84.  * available elsewhere.
  85.  *
  86.  * Revision 1.2  2000/02/06 07:48:03  rahulj
  87.  * Year 2K copyright swat.
  88.  *
  89.  * Revision 1.1.1.1  1999/11/09 01:04:59  twl
  90.  * Initial checkin
  91.  *
  92.  * Revision 1.2  1999/11/08 20:45:12  rahul
  93.  * Swat for adding in Product name and CVS comment log variable.
  94.  *
  95.  */
  96. // ---------------------------------------------------------------------------
  97. //  Include
  98. // ---------------------------------------------------------------------------
  99. #if defined(XERCES_TMPLSINC)
  100. #include <util/RefHashTableOf.hpp>
  101. #endif
  102. #include <util/NullPointerException.hpp>
  103. // ---------------------------------------------------------------------------
  104. //  RefHashTableOf: Constructors and Destructor
  105. // ---------------------------------------------------------------------------
  106. template <class TVal> RefHashTableOf<TVal>::RefHashTableOf(const unsigned int modulus, const bool adoptElems) 
  107. : fAdoptedElems(adoptElems), fBucketList(0), fHashModulus(modulus)
  108. {
  109.     initialize(modulus);
  110. // create default hasher
  111. fHash = new HashXMLCh();
  112. }
  113. template <class TVal> RefHashTableOf<TVal>::RefHashTableOf(const unsigned int modulus, const bool adoptElems, HashBase* hashBase)
  114. : fAdoptedElems(adoptElems), fBucketList(0), fHashModulus(modulus)
  115. {
  116. initialize(modulus);
  117. // set hasher
  118. fHash = hashBase;
  119. }
  120. template <class TVal> RefHashTableOf<TVal>::RefHashTableOf(const unsigned int modulus)
  121. : fAdoptedElems(true), fBucketList(0), fHashModulus(modulus)
  122. {
  123. initialize(modulus);
  124. // create default hasher
  125. fHash = new HashXMLCh();
  126. }
  127. template <class TVal> void RefHashTableOf<TVal>::initialize(const unsigned int modulus)
  128. {
  129. if (modulus == 0)
  130.         ThrowXML(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus);
  131.     // Allocate the bucket list and zero them
  132.     fBucketList = new RefHashTableBucketElem<TVal>*[fHashModulus];
  133.     for (unsigned int index = 0; index < fHashModulus; index++)
  134.         fBucketList[index] = 0;
  135. }
  136. template <class TVal> RefHashTableOf<TVal>::~RefHashTableOf()
  137. {
  138.     removeAll();
  139.     // Then delete the bucket list & hasher
  140.     delete [] fBucketList;
  141. delete fHash;
  142. }
  143. // ---------------------------------------------------------------------------
  144. //  RefHashTableOf: Element management
  145. // ---------------------------------------------------------------------------
  146. template <class TVal> bool RefHashTableOf<TVal>::isEmpty() const
  147. {
  148.     // Just check the bucket list for non-empty elements
  149.     for (unsigned int buckInd = 0; buckInd < fHashModulus; buckInd++)
  150.     {
  151.         if (fBucketList[buckInd] != 0)
  152.             return false;
  153.     }
  154.     return true;
  155. }
  156. template <class TVal> bool RefHashTableOf<TVal>::
  157. containsKey(const void* const key) const
  158. {
  159.     unsigned int hashVal;
  160.     const RefHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
  161.     return (findIt != 0);
  162. }
  163. template <class TVal> void RefHashTableOf<TVal>::
  164. removeKey(const void* const key)
  165. {
  166.     unsigned int hashVal;
  167.     removeBucketElem(key, hashVal);
  168. }
  169. template <class TVal> void RefHashTableOf<TVal>::removeAll()
  170. {
  171.     // Clean up the buckets first
  172.     for (unsigned int buckInd = 0; buckInd < fHashModulus; buckInd++)
  173.     {
  174.         // Get the bucket list head for this entry
  175.         RefHashTableBucketElem<TVal>* curElem = fBucketList[buckInd];
  176.         RefHashTableBucketElem<TVal>* nextElem;
  177.         while (curElem)
  178.         {
  179.             // Save the next element before we hose this one
  180.             nextElem = curElem->fNext;
  181.             // If we adopted the data, then delete it too
  182.             //    (Note:  the userdata hash table instance has data type of void *. 
  183.             //    This will generate compiler warnings here on some platforms, but they
  184.             //    can be ignored since fAdoptedElements is false.
  185.             if (fAdoptedElems)
  186.                 delete curElem->fData;
  187.             // Then delete the current element and move forward
  188.             delete curElem;
  189.             curElem = nextElem;
  190.         }
  191.         // Clean out this entry
  192.         fBucketList[buckInd] = 0;
  193.     }
  194. }
  195. // ---------------------------------------------------------------------------
  196. //  RefHashTableOf: Getters
  197. // ---------------------------------------------------------------------------
  198. template <class TVal> TVal* RefHashTableOf<TVal>::get(const void* const key)
  199. {
  200.     unsigned int hashVal;
  201.     RefHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
  202.     if (!findIt)
  203.         return 0;
  204.     return findIt->fData;
  205. }
  206. template <class TVal> const TVal* RefHashTableOf<TVal>::
  207. get(const void* const key) const
  208. {
  209.     unsigned int hashVal;
  210.     const RefHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
  211.     if (!findIt)
  212.         return 0;
  213.     return findIt->fData;
  214. }
  215. // ---------------------------------------------------------------------------
  216. //  RefHashTableOf: Putters
  217. // ---------------------------------------------------------------------------
  218. template <class TVal> void RefHashTableOf<TVal>::put(void* key, TVal* const valueToAdopt)
  219. {
  220.     // First see if the key exists already
  221.     unsigned int hashVal;
  222.     RefHashTableBucketElem<TVal>* newBucket = findBucketElem(key, hashVal);
  223.     //
  224.     //  If so,then update its value. If not, then we need to add it to
  225.     //  the right bucket
  226.     //
  227.     if (newBucket)
  228.     {
  229.         if (fAdoptedElems)
  230.             delete newBucket->fData;
  231.         newBucket->fData = valueToAdopt;
  232. newBucket->fKey = key;
  233.     }
  234.      else
  235.     {
  236.         newBucket = new RefHashTableBucketElem<TVal>(key, valueToAdopt, fBucketList[hashVal]);
  237.         fBucketList[hashVal] = newBucket;
  238.     }
  239. }
  240. // ---------------------------------------------------------------------------
  241. //  RefHashTableOf: Private methods
  242. // ---------------------------------------------------------------------------
  243. template <class TVal> RefHashTableBucketElem<TVal>* RefHashTableOf<TVal>::
  244. findBucketElem(const void* const key, unsigned int& hashVal)
  245. {
  246.     // Hash the key
  247.     hashVal = fHash->getHashVal(key, fHashModulus);
  248.     if (hashVal > fHashModulus)
  249.         ThrowXML(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey);
  250.     // Search that bucket for the key
  251.     RefHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
  252.     while (curElem)
  253.     {
  254. if (fHash->equals(key, curElem->fKey))
  255.             return curElem;
  256.         curElem = curElem->fNext;
  257.     }
  258.     return 0;
  259. }
  260. template <class TVal> const RefHashTableBucketElem<TVal>* RefHashTableOf<TVal>::
  261. findBucketElem(const void* const key, unsigned int& hashVal) const
  262. {
  263.     // Hash the key
  264.     hashVal = fHash->getHashVal(key, fHashModulus);
  265.     if (hashVal > fHashModulus)
  266.         ThrowXML(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey);
  267.     // Search that bucket for the key
  268.     const RefHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
  269.     while (curElem)
  270.     {
  271.         if (fHash->equals(key, curElem->fKey))
  272.             return curElem;
  273.         curElem = curElem->fNext;
  274.     }
  275.     return 0;
  276. }
  277. template <class TVal> void RefHashTableOf<TVal>::
  278. removeBucketElem(const void* const key, unsigned int& hashVal)
  279. {
  280.     // Hash the key
  281.     hashVal = fHash->getHashVal(key, fHashModulus);
  282.     if (hashVal > fHashModulus)
  283.         ThrowXML(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey);
  284.     //
  285.     //  Search the given bucket for this key. Keep up with the previous
  286.     //  element so we can patch around it.
  287.     //
  288.     RefHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
  289.     RefHashTableBucketElem<TVal>* lastElem = 0;
  290.     while (curElem)
  291.     {
  292.         if (fHash->equals(key, curElem->fKey))
  293.         {
  294.             if (!lastElem)
  295.             {
  296.                 // It was the first in the bucket
  297.                 fBucketList[hashVal] = curElem->fNext;
  298.             }
  299.              else
  300.             {
  301.                 // Patch around the current element
  302.                 lastElem->fNext = curElem->fNext;
  303.             }
  304.             // If we adopted the elements, then delete the data
  305.             if (fAdoptedElems)
  306.                 delete curElem->fData;
  307.             // Delete the current element
  308.             delete curElem;
  309.             return;
  310.         }
  311.         // Move both pointers upwards
  312.         lastElem = curElem;
  313.         curElem = curElem->fNext;
  314.     }
  315.     // We never found that key
  316.     ThrowXML(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists);
  317. }
  318. // ---------------------------------------------------------------------------
  319. //  RefHashTableOfEnumerator: Constructors and Destructor
  320. // ---------------------------------------------------------------------------
  321. template <class TVal> RefHashTableOfEnumerator<TVal>::
  322. RefHashTableOfEnumerator(RefHashTableOf<TVal>* const toEnum, const bool adopt)
  323. : fAdopted(adopt), fCurElem(0), fCurHash((unsigned int)-1), fToEnum(toEnum)
  324. {
  325.     if (!toEnum)  
  326.         ThrowXML(NullPointerException, XMLExcepts::CPtr_PointerIsZero);        
  327.     //
  328.     //  Find the next available bucket element in the hash table. If it
  329.     //  comes back zero, that just means the table is empty.
  330.     //
  331.     //  Note that the -1 in the current hash tells it to start from the
  332.     //  beginning.
  333.     //
  334.     findNext();
  335. }
  336. template <class TVal> RefHashTableOfEnumerator<TVal>::~RefHashTableOfEnumerator()
  337. {
  338.     if (fAdopted)
  339.         delete fToEnum;
  340. }
  341. // ---------------------------------------------------------------------------
  342. //  RefHashTableOfEnumerator: Enum interface
  343. // ---------------------------------------------------------------------------
  344. template <class TVal> bool RefHashTableOfEnumerator<TVal>::hasMoreElements() const
  345. {
  346.     //
  347.     //  If our current has is at the max and there are no more elements
  348.     //  in the current bucket, then no more elements.
  349.     //
  350.     if (!fCurElem && (fCurHash == fToEnum->fHashModulus))
  351.         return false;
  352.     return true;
  353. }
  354. template <class TVal> TVal& RefHashTableOfEnumerator<TVal>::nextElement()
  355. {
  356.     // Make sure we have an element to return
  357.     if (!hasMoreElements())
  358.         ThrowXML(NoSuchElementException, XMLExcepts::Enum_NoMoreElements);
  359.     //
  360.     //  Save the current element, then move up to the next one for the
  361.     //  next time around.
  362.     //
  363.     RefHashTableBucketElem<TVal>* saveElem = fCurElem;
  364.     findNext();
  365.     return *saveElem->fData;
  366. }
  367. template <class TVal> void RefHashTableOfEnumerator<TVal>::Reset()
  368. {
  369.     fCurHash = (unsigned int)-1;
  370.     fCurElem = 0;
  371.     findNext();
  372. }
  373. // ---------------------------------------------------------------------------
  374. //  RefHashTableOfEnumerator: Private helper methods
  375. // ---------------------------------------------------------------------------
  376. template <class TVal> void RefHashTableOfEnumerator<TVal>::findNext()
  377. {
  378.     //
  379.     //  If there is a current element, move to its next element. If this
  380.     //  hits the end of the bucket, the next block will handle the rest.
  381.     //
  382.     if (fCurElem)
  383.         fCurElem = fCurElem->fNext;
  384.     //
  385.     //  If the current element is null, then we have to move up to the
  386.     //  next hash value. If that is the hash modulus, then we cannot
  387.     //  go further.
  388.     //
  389.     if (!fCurElem)
  390.     {
  391.         fCurHash++;
  392.         if (fCurHash == fToEnum->fHashModulus)
  393.             return;
  394.         // Else find the next non-empty bucket
  395.         while (true)
  396.         {
  397.             if (fToEnum->fBucketList[fCurHash])
  398.                 break;
  399.             // Bump to the next hash value. If we max out return
  400.             fCurHash++;
  401.             if (fCurHash == fToEnum->fHashModulus)
  402.                 return;
  403.         }
  404.         fCurElem = fToEnum->fBucketList[fCurHash];
  405.     }
  406. }