GME  13
StringPool.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  * 
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  * 
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: StringPool.cpp 471747 2006-11-06 14:31:56Z amassari $
00020  */
00021 
00022 
00023 // ---------------------------------------------------------------------------
00024 //  Includes
00025 // ---------------------------------------------------------------------------
00026 #include <xercesc/util/StringPool.hpp>
00027 #include <assert.h>
00028 
00029 XERCES_CPP_NAMESPACE_BEGIN
00030 
00031 // ---------------------------------------------------------------------------
00032 //  XMLStringPool: Constructors and Destructor
00033 // ---------------------------------------------------------------------------
00034 XMLStringPool::XMLStringPool(const  unsigned int  modulus,
00035                              MemoryManager* const manager) :
00036 
00037     fMemoryManager(manager)
00038     , fIdMap(0)
00039     , fHashTable(0)
00040     , fMapCapacity(64)
00041     , fCurId(1)
00042 {
00043     // Create the hash table, passing it the modulus
00044     fHashTable = new (fMemoryManager) RefHashTableOf<PoolElem>(modulus, false, fMemoryManager);
00045 
00046     // Do an initial allocation of the id map and zero it all out
00047     fIdMap = (PoolElem**) fMemoryManager->allocate
00048     (
00049         fMapCapacity * sizeof(PoolElem*)
00050     ); //new PoolElem*[fMapCapacity];
00051     memset(fIdMap, 0, sizeof(PoolElem*) * fMapCapacity);
00052 }
00053 
00054 XMLStringPool::~XMLStringPool()
00055 {
00056     // delete all buckelements, since the hashtable doesn't adopt the elements anymore
00057     for (unsigned int index = 1; index < fCurId; index++)
00058     {
00059         //fIdMap[index]->~PoolElem();                                // we have no destructor
00060         fMemoryManager->deallocate((void*) fIdMap[index]->fString);  // deallocate memory
00061         fMemoryManager->deallocate(fIdMap[index]);                   // deallocate memory
00062     }
00063     delete fHashTable;
00064     fMemoryManager->deallocate(fIdMap); //delete [] fIdMap;
00065 }
00066 
00067 // ---------------------------------------------------------------------------
00068 //  XMLStringPool: Pool management methods
00069 // ---------------------------------------------------------------------------
00070 void XMLStringPool::flushAll()
00071 {
00072     // delete all buckelements, since the hashtable doesn't adopt the elements anymore
00073     for (unsigned int index = 1; index < fCurId; index++)
00074     {
00075         //fIdMap[index]->~PoolElem();                                // we have no destructor
00076         fMemoryManager->deallocate((void*) fIdMap[index]->fString);  // deallocate memory
00077         fMemoryManager->deallocate(fIdMap[index]);                   // deallocate memory
00078     }
00079     fCurId = 1;
00080     fHashTable->removeAll();
00081 }
00082 
00083 // ---------------------------------------------------------------------------
00084 //  XMLStringPool: Private helper methods
00085 // ---------------------------------------------------------------------------
00086 unsigned int XMLStringPool::addNewEntry(const XMLCh* const newString)
00087 {
00088     // See if we need to expand the id map
00089     if (fCurId == fMapCapacity)
00090     {
00091         // Calculate the new capacity, create a temp new map, and zero it
00092         const unsigned int newCap = (unsigned int)(fMapCapacity * 1.5);
00093         PoolElem** newMap = (PoolElem**) fMemoryManager->allocate
00094         (
00095             newCap * sizeof(PoolElem*)
00096         ); //new PoolElem*[newCap];
00097         memset(newMap, 0, sizeof(PoolElem*) * newCap);
00098 
00099         //
00100         //  Copy over the old elements from the old map. They are just pointers
00101         //  so we can do it all at once.
00102         //
00103         memcpy(newMap, fIdMap, sizeof(PoolElem*) * fMapCapacity);
00104 
00105         // Clean up the old map and store the new info
00106         fMemoryManager->deallocate(fIdMap); //delete [] fIdMap;
00107         fIdMap = newMap;
00108         fMapCapacity = newCap;
00109     }
00110 
00111     //
00112     //  Ok, now create a new element and add it to the hash table. Then store
00113     //  this new element in the id map at the current id index, then bump the
00114     //  id index.
00115     //
00116     PoolElem* newElem = (PoolElem*) fMemoryManager->allocate(sizeof(PoolElem));
00117     newElem->fId      = fCurId;
00118     newElem->fString  = XMLString::replicate(newString, fMemoryManager);
00119     fHashTable->put((void*)newElem->fString, newElem);
00120     fIdMap[fCurId] = newElem;
00121 
00122     // Bump the current id and return the id of the new elem we just added
00123     fCurId++;
00124     return newElem->fId;
00125 }
00126 
00127 /***
00128  * Support for Serialization/De-serialization
00129  ***/
00130 
00131 IMPL_XSERIALIZABLE_TOCREATE(XMLStringPool)
00132 
00133 void XMLStringPool::serialize(XSerializeEngine& serEng)
00134 {
00135     /***
00136      * Since we are pretty sure that fIdMap and fHashTable is 
00137      * not shared by any other object, therefore there is no owned/referenced
00138      * issue. Thus we can serialize the raw data only, rather than serializing 
00139      * both fIdMap and fHashTable.
00140      *
00141      * And we can rebuild the fIdMap and fHashTable out of the raw data during
00142      * deserialization.
00143      *
00144     ***/
00145     if (serEng.isStoring())
00146     {
00147         serEng<<fCurId;
00148         for (unsigned int index = 1; index < fCurId; index++)
00149         {
00150             const XMLCh* stringData = getValueForId(index);
00151             serEng.writeString(stringData);
00152         }
00153     }
00154     else
00155     {
00156         unsigned int mapSize;
00157         serEng>>mapSize;
00158         assert(1 == fCurId);  //make sure empty
00159 
00160         for (unsigned int index = 1; index < mapSize; index++)
00161         {
00162             XMLCh* stringData;
00163             serEng.readString(stringData);
00164             addNewEntry(stringData);
00165 
00166             //we got to deallocate this string 
00167             //since stringpool will duplicate this string in the PoolElem and own that copy
00168             fMemoryManager->deallocate(stringData);
00169         }
00170     }
00171 }
00172 
00173 XMLStringPool::XMLStringPool(MemoryManager* const manager) :
00174     fMemoryManager(manager)
00175     , fIdMap(0)
00176     , fHashTable(0)
00177     , fMapCapacity(64)
00178     , fCurId(1)
00179 {
00180     // Create the hash table, passing it the modulus
00181     fHashTable = new (fMemoryManager) RefHashTableOf<PoolElem>(109, false, fMemoryManager);
00182 
00183     // Do an initial allocation of the id map and zero it all out
00184     fIdMap = (PoolElem**) fMemoryManager->allocate
00185     (
00186         fMapCapacity * sizeof(PoolElem*)
00187     ); //new PoolElem*[fMapCapacity];
00188     memset(fIdMap, 0, sizeof(PoolElem*) * fMapCapacity);
00189 }
00190 
00191 XERCES_CPP_NAMESPACE_END