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

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. #include "DOMString.hpp"
  57. #include "AttrImpl.hpp"
  58. #include "NodeIDMap.hpp"
  59. #include <util/XMLString.hpp>
  60. #include <stdio.h>
  61. static const int gPrimes[] = {997, 9973, 99991, 999983, 0 };  // To do - add a few more.
  62. static const float gMaxFill = 0.8f;   // The maximum fraction of the total
  63.                                     // table entries to consume before exanding.
  64. NodeIDMap::NodeIDMap(int initialSize) 
  65. {
  66.     for (fSizeIndex = 0; gPrimes[fSizeIndex] < initialSize; fSizeIndex++)
  67.     {
  68.         if (gPrimes[fSizeIndex] == 0)
  69.         {
  70.             // We need a bigger size than the largest available one.
  71.             //   Big trouble.
  72.             fSizeIndex--;
  73.             throw "NodeIDMap::NodeIDMap - big trouble.";
  74.         }
  75.     }
  76.     
  77.     fSize = gPrimes[fSizeIndex];
  78.     fNumEntries = 0;
  79.     fMaxEntries = (unsigned long)(float(fSize) * gMaxFill);
  80.     fTable = new AttrImpl *[fSize];
  81.     unsigned int i;
  82.     for (i=0; i<fSize; i++)
  83.         fTable[i] = 0;
  84. };
  85. NodeIDMap::~NodeIDMap()
  86. {
  87.     delete[] fTable;
  88.     fTable = 0;
  89. };
  90. void NodeIDMap::add(AttrImpl *attr)
  91. {
  92. //
  93. //  If the table is getting too full, grow it.  We arbitrarily limit
  94. //   the table to 80 full, which should limit the average number of
  95. //   rehashes to a reasonable value.
  96. //
  97. if (fNumEntries >= fMaxEntries)
  98. growTable();
  99.     fNumEntries++;
  100. //
  101. // Hash the value string from the ID attribute being added to the table
  102. //      0 < Initial hash value < table size.
  103. //      An initial hash of zero would cause the rehash to fail.
  104. //
  105. DOMString id=attr->getValue();
  106. unsigned int initalHash = XMLString::hashN(id.rawBuffer(), id.length(), fSize-1);
  107. initalHash++;
  108. unsigned int currentHash = initalHash;
  109. //
  110. // Loop looking for an empty slot for this ID.
  111. //   Don't even bother checking to see if the ID is already there - 
  112. //   the table is only filled by the parser from valid documents, which
  113. //   can not have duplicates.  Behavior of invalid docs is not defined.
  114. //
  115.     while (true)
  116. {
  117. AttrImpl *tableSlot = fTable[currentHash];
  118. if (tableSlot == 0 ||
  119. tableSlot == (AttrImpl *)-1)
  120. break;
  121. currentHash += initalHash;  // rehash
  122.         if (currentHash >= fSize)
  123.             currentHash = currentHash % fSize;
  124.     }
  125.     //
  126.     // We've found our slot.  Stick the pointer to the attr into it.
  127.     //
  128.     fTable[currentHash] = attr;
  129. };
  130. void NodeIDMap::remove(AttrImpl *attr)
  131. {
  132.     //
  133. // Hash the value string from the ID attribute being added to the table
  134. //      0 < Initial hash value < table size.
  135. //      An initial hash of zero would cause the rehash to fail.
  136. //
  137. DOMString id=attr->getValue();
  138. unsigned int initalHash = XMLString::hashN(id.rawBuffer(), id.length(), fSize-1);
  139. initalHash++;
  140. unsigned int currentHash = initalHash;
  141. //
  142. // Loop looking for a slot pointing to an attr with this id.
  143.     //
  144.     while (true)
  145. {
  146. AttrImpl *tableSlot = fTable[currentHash];
  147. if (tableSlot == 0)
  148.         {
  149.             // There is no matching entry in the table
  150.             return;
  151.         }
  152.         if (tableSlot == attr)
  153.         {
  154.             //  Found the attribute.  Set the slot to -1 to indicate
  155.             //   that it was once used, meaning that lookups, while never
  156.             //   matching here, can not stop either, but must rehash again
  157.             //   and continue searching.
  158.             fTable[currentHash] = (AttrImpl *)-1;
  159.             return;
  160.         }
  161.         currentHash += initalHash;  // rehash.
  162.         if (currentHash >= fSize)
  163.             currentHash = currentHash % fSize;
  164.     }
  165. };
  166. AttrImpl *NodeIDMap::find(const DOMString &id)
  167. {
  168.     //
  169.     //  Get the hashcode for the supplied string.
  170.     //
  171. unsigned int initalHash = XMLString::hashN(id.rawBuffer(), id.length(), fSize-1);
  172. initalHash++;
  173. unsigned int currentHash = initalHash;
  174. //
  175. // Loop looking for a slot pointing to an attr with this id.
  176.     //
  177.     while (true)
  178. {
  179. AttrImpl *tableSlot = fTable[currentHash];
  180. if (tableSlot == 0)
  181.         {
  182.             // There is no matching entry in the table
  183.             return 0;
  184.         }
  185.         if ((tableSlot != (AttrImpl *)-1) && tableSlot->getValue().equals(id))
  186.             return tableSlot;
  187.         currentHash += initalHash;  // rehash
  188.         if (currentHash >= fSize)
  189.             currentHash = currentHash % fSize;
  190.     }
  191.     return 0;  // Never gets here, but keeps some compilers happy.
  192. };
  193. //
  194. //  Grow the table to the next larger size.
  195. //      It has gotten too full for efficient operation.
  196. //     (We never fill it all the way)
  197. //
  198. void NodeIDMap::growTable()
  199. {
  200.     AttrImpl     **oldTable = fTable;
  201.     unsigned int oldSize  = fSize;
  202.     //
  203.     //  Figure the new table size.
  204.     //
  205.     fprintf(stderr, "growing...n");
  206.     fSizeIndex++;
  207.     fSize = gPrimes[fSizeIndex];
  208.     if (fSize == 0)
  209.     {
  210.         // We need to grow bigger than the largest available size.
  211.         //   Big trouble.
  212.         fSizeIndex--;
  213.         throw "NodeIDMap::growTable - big trouble.";
  214.     }
  215.     //
  216.     //  Allocate the new table.
  217.     //
  218.     fTable = new AttrImpl *[fSize];
  219.     unsigned int i;
  220.     for (i=0; i<fSize; i++)
  221.         fTable[i] = 0;
  222.     fMaxEntries = (unsigned long)(float(fSize) * gMaxFill);
  223.     //
  224.     // Move entries over from the old table to the new one.
  225.     //
  226.     for (i=0; i<oldSize; i++)
  227.     {
  228.         if ((oldTable[i] != 0)  &&  (oldTable[i] != (AttrImpl *)-1))
  229.             add(oldTable[i]);
  230.     }
  231.     
  232.     delete [] oldTable;
  233.     
  234. };