/*
* 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: RefHash2KeysTableOf.c 679340 2008-07-24 10:28:29Z borisk $
*/
// ---------------------------------------------------------------------------
// Include
// ---------------------------------------------------------------------------
#if defined(XERCES_TMPLSINC)
#include <xercesc/util/RefHash2KeysTableOf.hpp>
#endif
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/NullPointerException.hpp>
#include <assert.h>
#include <new>
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// RefHash2KeysTableOf: Constructors and Destructor
// ---------------------------------------------------------------------------
template <class TVal, class THasher>
RefHash2KeysTableOf<TVal, THasher>::RefHash2KeysTableOf(
const XMLSize_t modulus,
MemoryManager* const manager)
: fMemoryManager(manager)
, fAdoptedElems(true)
, fBucketList(0)
, fHashModulus(modulus)
, fCount(0)
{
initialize(modulus);
}
template <class TVal, class THasher>
RefHash2KeysTableOf<TVal, THasher>::RefHash2KeysTableOf(
const XMLSize_t modulus,
const THasher& hasher,
MemoryManager* const manager)
: fMemoryManager(manager)
, fAdoptedElems(true)
, fBucketList(0)
, fHashModulus(modulus)
, fCount(0)
, fHasher (hasher)
{
initialize(modulus);
}
template <class TVal, class THasher>
RefHash2KeysTableOf<TVal, THasher>::RefHash2KeysTableOf(
const XMLSize_t modulus,
const bool adoptElems,
MemoryManager* const manager)
: fMemoryManager(manager)
, fAdoptedElems(adoptElems)
, fBucketList(0)
, fHashModulus(modulus)
, fCount(0)
{
initialize(modulus);
}
template <class TVal, class THasher>
RefHash2KeysTableOf<TVal, THasher>::RefHash2KeysTableOf(
const XMLSize_t modulus,
const bool adoptElems,
const THasher& hasher,
MemoryManager* const manager)
: fMemoryManager(manager)
, fAdoptedElems(adoptElems)
, fBucketList(0)
, fHashModulus(modulus)
, fCount(0)
, fHasher (hasher)
{
initialize(modulus);
}
template <class TVal, class THasher>
void RefHash2KeysTableOf<TVal, THasher>::initialize(const XMLSize_t modulus)
{
if (modulus == 0)
ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus, fMemoryManager);
// Allocate the bucket list and zero them
fBucketList = (RefHash2KeysTableBucketElem<TVal>**) fMemoryManager->allocate
(
fHashModulus * sizeof(RefHash2KeysTableBucketElem<TVal>*)
); //new RefHash2KeysTableBucketElem<TVal>*[fHashModulus];
memset(fBucketList, 0, sizeof(fBucketList[0]) * fHashModulus);
}
template <class TVal, class THasher>
RefHash2KeysTableOf<TVal, THasher>::~RefHash2KeysTableOf()
{
removeAll();
// Then delete the bucket list & hasher
fMemoryManager->deallocate(fBucketList); //delete [] fBucketList;
fBucketList = 0;
}
// ---------------------------------------------------------------------------
// RefHash2KeysTableOf: Element management
// ---------------------------------------------------------------------------
template <class TVal, class THasher>
bool RefHash2KeysTableOf<TVal, THasher>::isEmpty() const
{
return (fCount==0);
}
template <class TVal, class THasher>
bool RefHash2KeysTableOf<TVal, THasher>::
containsKey(const void* const key1, const int key2) const
{
XMLSize_t hashVal;
const RefHash2KeysTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, hashVal);
return (findIt != 0);
}
template <class TVal, class THasher>
void RefHash2KeysTableOf<TVal, THasher>::
removeKey(const void* const key1, const int key2)
{
// Hash the key
XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus);
assert(hashVal < fHashModulus);
//
// Search the given bucket for this key. Keep up with the previous
// element so we can patch around it.
//
RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal];
RefHash2KeysTableBucketElem<TVal>* lastElem = 0;
while (curElem)
{
if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1)))
{
if (!lastElem)
{
// It was the first in the bucket
fBucketList[hashVal] = curElem->fNext;
}
else
{
// Patch around the current element
lastElem->fNext = curElem->fNext;
}
// If we adopted the elements, then delete the data
if (fAdoptedElems)
delete curElem->fData;
// Delete the current element
// delete curElem;
// destructor is empty...
// curElem->~RefHash2KeysTableBucketElem();
fMemoryManager->deallocate(curElem);
fCount--;
return;
}
// Move both pointers upwards
lastElem = curElem;
curElem = curElem->fNext;
}
// We never found that key
ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists, fMemoryManager);
}
template <class TVal, class THasher>
void RefHash2KeysTableOf<TVal, THasher>::
removeKey(const void* const key1)
{
// Hash the key
XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus);
assert(hashVal < fHashModulus);
//
// Search the given bucket for this key. Keep up with the previous
// element so we can patch around it.
//
RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal];
RefHash2KeysTableBucketElem<TVal>* lastElem = 0;
while (curElem)
{
if(fHasher.equals(key1, curElem->fKey1))
{
if (!lastElem)
{
// It was the first in the bucket
fBucketList[hashVal] = curElem->fNext;
}
else
{
// Patch around the current element
lastElem->fNext = curElem->fNext;
}
// If we adopted the elements, then delete the data
if (fAdoptedElems)
delete curElem->fData;
RefHash2KeysTableBucketElem<TVal>* toBeDeleted=curElem;
curElem = curElem->fNext;
// Delete the current element
// delete curElem;
// destructor is empty...
// curElem->~RefHash2KeysTableBucketElem();
fMemoryManager->deallocate(toBeDeleted);
fCount--;
}
else
{
// Move both pointers upwards
lastElem = curElem;
curElem = curElem->fNext;
}
}
}
template <class TVal, class THasher>
void RefHash2KeysTableOf<TVal, THasher>::removeAll()
{
if(isEmpty())
return;
// Clean up the buckets first
for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++)
{
// Get the bucket list head for this entry
RefHash2KeysTableBucketElem<TVal>*