blob: 92bbc5c5e56e8c3d18238aa8f918afd4700f0ae3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: StringPool.cpp 568078 2007-08-21 11:43:25Z amassari $
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/StringPool.hpp>
#include <assert.h>
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// XMLStringPool: Constructors and Destructor
// ---------------------------------------------------------------------------
XMLStringPool::XMLStringPool(const unsigned int modulus,
MemoryManager* const manager) :
fMemoryManager(manager)
, fIdMap(0)
, fHashTable(0)
, fMapCapacity(64)
, fCurId(1)
{
// Create the hash table, passing it the modulus
fHashTable = new (fMemoryManager) RefHashTableOf<PoolElem>(modulus, false, fMemoryManager);
// Do an initial allocation of the id map and zero it all out
fIdMap = (PoolElem**) fMemoryManager->allocate
(
fMapCapacity * sizeof(PoolElem*)
); //new PoolElem*[fMapCapacity];
memset(fIdMap, 0, sizeof(PoolElem*) * fMapCapacity);
}
XMLStringPool::~XMLStringPool()
{
// delete all buckelements, since the hashtable doesn't adopt the elements anymore
for (unsigned int index = 1; index < fCurId; index++)
{
//fIdMap[index]->~PoolElem(); // we have no destructor
fMemoryManager->deallocate((void*) fIdMap[index]->fString); // deallocate memory
fMemoryManager->deallocate(fIdMap[index]); // deallocate memory
}
delete fHashTable;
fMemoryManager->deallocate(fIdMap); //delete [] fIdMap;
}
// ---------------------------------------------------------------------------
// XMLStringPool: Pool management methods
// ---------------------------------------------------------------------------
void XMLStringPool::flushAll()
{
// delete all buckelements, since the hashtable doesn't adopt the elements anymore
for (unsigned int index = 1; index < fCurId; index++)
{
//fIdMap[index]->~PoolElem(); // we have no destructor
fMemoryManager->deallocate((void*) fIdMap[index]->fString); // deallocate memory
fMemoryManager->deallocate(fIdMap[index]); // deallocate memory
}
fCurId = 1;
fHashTable->removeAll();
}
// ---------------------------------------------------------------------------
// XMLStringPool: Private helper methods
// ---------------------------------------------------------------------------
unsigned int XMLStringPool::addNewEntry(const XMLCh* const newString)
{
// See if we need to expand the id map
if (fCurId == fMapCapacity)
{
// Calculate the new capacity, create a temp new map, and zero it
const unsigned int newCap = (unsigned int)(fMapCapacity * 1.5);
PoolElem** newMap = (PoolElem**) fMemoryManager->allocate
(
newCap * sizeof(PoolElem*)
); //new PoolElem*[newCap];
memset(newMap, 0, sizeof(PoolElem*) * newCap);
//
// Copy over the old elements from the old map. They are just pointers
// so we can do it all at once.
//
memcpy(newMap, fIdMap, sizeof(PoolElem*) * fMapCapacity);
// Clean up the old map and store the new info
fMemoryManager->deallocate(fIdMap); //delete [] fIdMap;
fIdMap = newMap;
fMapCapacity = newCap;
}
//
// Ok, now create a new element and add it to the hash table. Then store
// this new element in the id map at the current id index, then bump the
// id index.
//
PoolElem* newElem = (PoolElem*) fMemoryManager->allocate(sizeof(PoolElem));
newElem->fId = fCurId;
newElem->fString = XMLString::replicate(newString, fMemoryManager);
fHashTable->put((void*)newElem->fString, newElem);
fIdMap[fCurId] = newElem;
// Bump the current id and return the id of the new elem we just added
fCurId++;
return newElem->fId;
}
/***
* Support for Serialization/De-serialization
***/
IMPL_XSERIALIZABLE_TOCREATE(XMLStringPool)
void XMLStringPool::serialize(XSerializeEngine& serEng)
{
/***
* Since we are pretty sure that fIdMap and fHashTable is
* not shared by any other object, therefore there is no owned/referenced
* issue. Thus we can serialize the raw data only, rather than serializing
* both fIdMap and fHashTable.
*
* And we can rebuild the fIdMap and fHashTable out of the raw data during
* deserialization.
*
***/
if (serEng.isStoring())
{
serEng<<fCurId;
for (unsigned int index = 1; index < fCurId; index++)
{
const XMLCh* stringData = getValueForId(index);
serEng.writeString(stringData);
}
}
else
{
unsigned int mapSize;
serEng>>mapSize;
assert(1 == fCurId); //make sure empty
for (unsigned int index = 1; index < mapSize; index++)
{
XMLCh* stringData;
serEng.readString(stringData);
addNewEntry(stringData);
//we got to deallocate this string
//since stringpool will duplicate this string in the PoolElem and own that copy
fMemoryManager->deallocate(stringData);
}
}
}
XMLStringPool::XMLStringPool(MemoryManager* const manager) :
fMemoryManager(manager)
, fIdMap(0)
, fHashTable(0)
, fMapCapacity(64)
, fCurId(1)
{
// Create the hash table, passing it the modulus
fHashTable = new (fMemoryManager) RefHashTableOf<PoolElem>(109, false, fMemoryManager);
// Do an initial allocation of the id map and zero it all out
fIdMap = (PoolElem**) fMemoryManager->allocate
(
fMapCapacity * sizeof(PoolElem*)
); //new PoolElem*[fMapCapacity];
memset(fIdMap, 0, sizeof(PoolElem*) * fMapCapacity);
}
XERCES_CPP_NAMESPACE_END