/*
 * 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: DOMDeepNodeListPool.c 568078 2007-08-21 11:43:25Z amassari $
 */


// ---------------------------------------------------------------------------
//  Include
// ---------------------------------------------------------------------------
#include <xercesc/util/XercesDefs.hpp>
#if defined(XERCES_TMPLSINC)
#include <xercesc/dom/impl/DOMDeepNodeListPool.hpp>
#endif

#include <assert.h>

XERCES_CPP_NAMESPACE_BEGIN



// ---------------------------------------------------------------------------
//  DOMDeepNodeListPool: Constructors and Destructor
// ---------------------------------------------------------------------------
template <class TVal>
DOMDeepNodeListPool<TVal>::DOMDeepNodeListPool( const XMLSize_t modulus
                                              , const bool adoptElems
                                              , const XMLSize_t initSize) :
	 fAdoptedElems(adoptElems)
    , fBucketList(0)
    , fHashModulus(modulus)
    , fHash(0)
    , fIdPtrs(0)
    , fIdPtrsCount(initSize)
    , fIdCounter(0)
    , fMemoryManager(XMLPlatformUtils::fgMemoryManager)
{
    initialize(modulus);

    // create default hasher
#if defined (XML_GCC_VERSION) && (XML_GCC_VERSION < 29600)
    fHash = new HashPtr();
#else
    fHash = new (fMemoryManager) HashPtr();
#endif
    //
    //  Allocate the initial id pointers array. We don't have to zero them
    //  out since the fIdCounter value tells us which ones are valid. The
    //  zeroth element is never used (and represents an invalid pool id.)
    //
    if (!fIdPtrsCount)
        fIdPtrsCount = 256;

    fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*));//new TVal*[fIdPtrsCount];
    fIdPtrs[0] = 0;
}

template <class TVal>
DOMDeepNodeListPool<TVal>::DOMDeepNodeListPool( const XMLSize_t modulus
                                              , const bool adoptElems
                                              , HashBase* hashBase
                                              , const XMLSize_t initSize) :
	 fAdoptedElems(adoptElems)
    , fBucketList(0)
    , fHashModulus(modulus)
    , fHash(0)
    , fIdPtrs(0)
    , fIdPtrsCount(initSize)
    , fIdCounter(0)
    , fMemoryManager(XMLPlatformUtils::fgMemoryManager)
{
    initialize(modulus);
    // set hasher
    fHash = hashBase;

    //
    //  Allocate the initial id pointers array. We don't have to zero them
    //  out since the fIdCounter value tells us which ones are valid. The
    //  zeroth element is never used (and represents an invalid pool id.)
    //
    if (!fIdPtrsCount)
        fIdPtrsCount = 256;

    fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*));//new TVal*[fIdPtrsCount];
    fIdPtrs[0] = 0;
}

template <class TVal>
DOMDeepNodeListPool<TVal>::DOMDeepNodeListPool( const XMLSize_t modulus
                                              , const XMLSize_t initSize) :
	 fAdoptedElems(true)
    , fBucketList(0)
    , fHashModulus(modulus)
    , fHash(0)
    , fIdPtrs(0)
    , fIdPtrsCount(initSize)
    , fIdCounter(0)
    , fMemoryManager(XMLPlatformUtils::fgMemoryManager)
{
    initialize(modulus);

    // create default hasher
#if defined (XML_GCC_VERSION) && (XML_GCC_VERSION < 29600)
    fHash = new HashPtr();
#else
    fHash = new (fMemoryManager) HashPtr();
#endif    

    //
    //  Allocate the initial id pointers array. We don't have to zero them
    //  out since the fIdCounter value tells us which ones are valid. The
    //  zeroth element is never used (and represents an invalid pool id.)
    //
    if (!fIdPtrsCount)
        fIdPtrsCount = 256;

    fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*));//new TVal*[fIdPtrsCount];
    fIdPtrs[0] = 0;
}

template <class TVal>
void DOMDeepNodeListPool<TVal>::initialize(const XMLSize_t modulus)
{
	if (modulus == 0)
        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus, fMemoryManager);

    // Allocate the bucket list and zero them
    fBucketList = (DOMDeepNodeListPoolTableBucketElem<TVal>**)
        fMemoryManager->allocate
        (
            fHashModulus * sizeof(DOMDeepNodeListPoolTableBucketElem<TVal>*)
        );//new DOMDeepNodeListPoolTableBucketElem<TVal>*[fHashModulus];
    for (XMLSize_t index = 0; index < fHashModulus; index++)
        fBucketList[index] = 0;
}

template <class TVal> DOMDeepNodeListPool<TVal>::~DOMDeepNodeListPool()
{
    removeAll();

    // Then delete the bucket list & hasher & id pointers list
    fMemoryManager->deallocate(fIdPtrs);//delete [] fIdPtrs;
    fMemoryManager->deallocate(fBucketList);//delete [] fBucketList;
    delete fHash;
}


// ---------------------------------------------------------------------------
//  DOMDeepNodeListPool: Element management
// ---------------------------------------------------------------------------
template <class TVal>
bool DOMDeepNodeListPool<TVal>::isEmpty() const
{
    // Just check the bucket list for non-empty elements
    for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++)
    {
        if (fBucketList[buckInd] != 0)
            return false;
    }
    return true;
}

template <class TVal>
bool DOMDeepNodeListPool<TVal>::containsKey( const void* const key1
                                           , const XMLCh* const key2
                                           , const XMLCh* const key3) const
{
    XMLSize_t hashVal;
    const DOMDeepNodeListPoolTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, key3, hashVal);
    return (findIt != 0);
}

template <class TVal>
void DOMDeepNodeListPool<TVal>::removeAll()
{
    if (fIdCounter == 0) return;

    // Clean up the buckets first
    for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++)
    {
        // Get the bucket list head for this entry
        DOMDeepNodeListPoolTableBucketElem<TVal>* curElem = fBucketList[buckInd];
        DOMDeepNodeListPoolTableBucketElem<TVal>* nextElem;
        while (curElem)
        {
            // Save the next element before we hose this one
            nextElem = curElem->fNext;

            // If we adopted the data, then delete it too
            //    (Note:  the userdata hash table instance has data type of void *.
            //    This will generate compiler warnings here on some platforms, but they
            //    can be ignored since fAdoptedElements is false.
            if (fAdoptedElems)
                delete curElem->fData;

            // Then delete the current element and move forward
            fMemoryManager->deallocate(curElem->fKey2);//delete [] curElem->fKey2;
            fMemoryManager->deallocate(curElem->fKey3);//delete [] curElem->fKey3;

            delete curElem;
            curElem = nextElem;
        }

        // Clean out this entry
        fBucketList[buckInd] = 0;
    }

    // Reset the id counter
    fIdCounter = 0;
}

template <class TVal> void DOMDeepNodeListPool<TVal>::cleanup()
{
    removeAll();

    // Then delete the bucket list & hasher & id pointers list
    fMemoryManager->deallocate(fIdPtrs);//delete [] fIdPtrs;
    fMemoryManager->deallocate(fBucketList);//delete [] fBucketList;
    delete fHash;
}



// ---------------------------------------------------------------------------
//  DOMDeepNodeListPool: Getters
// ---------------------------------------------------------------------------
template <class TVal> TVal*
DOMDeepNodeListPool<TVal>::getByKey(const void* const key1, const XMLCh* const key2, const XMLCh* const key3)
{
    XMLSize_t hashVal;
    DOMDeepNodeListPoolTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, key3, hashVal);
    if (!findIt)
        return 0;
    return findIt->fData;
}

template <class TVal> const TVal*
DOMDeepNodeListPool<TVal>::getByKey(const void* const key1, const XMLCh* const key2, const XMLCh* const key3) const
{
    XMLSize_t hashVal;
    const DOMDeepNodeListPoolTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, key3, hashVal);
    if (!findIt)
        return 0;
    return findIt->fData;
}

template <class TVal> TVal*
DOMDeepNodeListPool<TVal>::getById(const XMLSize_t elemId)
{
    // If its either zero or beyond our current id, its an error
    if (!elemId || (elemId > fIdCounter))
        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_InvalidId, fMemoryManager);

    return fIdPtrs[elemId];
}

template <class TVal> const TVal*
DOMDeepNodeListPool<TVal>::getById(const XMLSize_t elemId) const
{
    // If its either zero or beyond our current id, its an error
    if (!elemId || (elemId > fIdCounter))
        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_InvalidId, fMemoryManager);

    return fIdPtrs[elemId];
}

// ---------------------------------------------------------------------------
//  DOMDeepNodeListPool: Putters
// ---------------------------------------------------------------------------
template <class TVal> XMLSize_t
DOMDeepNodeListPool<TVal>::put(void* key1, XMLCh* key2, XMLCh* key3, TVal* const valueToAdopt)
{
    // First see if the key exists already
    XMLSize_t hashVal;
    DOMDeepNodeListPoolTableBucketElem<TVal>* newBucket = findBucketElem(key1, key2, key3, hashVal);

    //
    //  If so,then update its value. If not, then we need to add it to
    //  the right bucket
    //
    if (newBucket)
    {
        if (fAdoptedElems)
            delete newBucket->fData;

        fMemoryManager->deallocate(newBucket->fKey2);//delete[] newBucket->fKey2;
        fMemoryManager->deallocate(newBucket->fKey3);//delete[] newBucket->fKey3;

        newBucket->fData = valueToAdopt;
        newBucket->fKey1 = key1;
        newBucket->fKey2 = XMLString::replicate(key2, fMemoryManager);
        newBucket->fKey3 = XMLString::replicate(key3, fMemoryManager);
    }
    else
    {
    // Revisit: the gcc compiler 2.95.x is generating an
    // internal compiler error message. So we use the default
    // memory manager for now.
#if defined (XML_GCC_VERSION) && (XML_GCC_VERSION < 29600)
        newBucket = new DOMDeepNodeListPoolTableBucketElem<TVal>
        (
            key1
            , key2
            , key3
            , valueToAdopt
            , fBucketList[hashVal]
            , fMemoryManager
        );
#else
        newBucket = new (fMemoryManager) DOMDeepNodeListPoolTableBucketElem<TVal>
        (
            key1
            , key2
            , key3
            , valueToAdopt
            , fBucketList[hashVal]
            , fMemoryManager
        );
#endif
        fBucketList[hashVal] = newBucket;
    }

    //
    //  Give this new one the next available id and add to the pointer list.
    //  Expand the list if that is now required.
    //
    if (fIdCounter + 1 == fIdPtrsCount)
    {
        // Create a new count 1.5 times larger and allocate a new array
        XMLSize_t newCount = (XMLSize_t)(fIdPtrsCount * 1.5);
        TVal** newArray = (TVal**) fMemoryManager->allocate
        (
            newCount * sizeof(TVal*)
        );//new TVal*[newCount];

        // Copy over the old contents to the new array
        memcpy(newArray, fIdPtrs, fIdPtrsCount * sizeof(TVal*));

        // Ok, toss the old array and store the new data
        fMemoryManager->deallocate(fIdPtrs); //delete [] fIdPtrs;
        fIdPtrs = newArray;
        fIdPtrsCount = newCount;
    }
    const XMLSize_t retId = ++fIdCounter;
    fIdPtrs[retId] = valueToAdopt;

    // Return the id that we gave to this element
    return retId;
}

// ---------------------------------------------------------------------------
//  DOMDeepNodeListPool: Private methods
// ---------------------------------------------------------------------------
template <class TVal> DOMDeepNodeListPoolTableBucketElem<TVal>* DOMDeepNodeListPool<TVal>::
findBucketElem(const void* const key1, const XMLCh* const key2, const XMLCh* const key3, XMLSize_t& hashVal)
{
    // Hash the key
    hashVal = fHash->getHashVal(key1, fHashModulus, fMemoryManager);
    assert(hashVal < fHashModulus);

    // Search that bucket for the key
    DOMDeepNodeListPoolTableBucketElem<TVal>* curElem = fBucketList[hashVal];
    while (curElem)
    {
        //key2 and key3 are XMLCh*, compareString takes null pointer vs zero len string the same
        //but we need them to be treated as different keys in this case
        if (fHash->equals(key1, curElem->fKey1) && (XMLString::equals(key2, curElem->fKey2)) && (XMLString::equals(key3, curElem->fKey3))) {
            if (!key2 || !curElem->fKey2) {
                if (key2 || curElem->fKey2) {
                    curElem = curElem->fNext;
                    continue;
                }
            }
            if (!key3 || !curElem->fKey3) {
                if (key3 || curElem->fKey3) {
                    curElem = curElem->fNext;
                    continue;
                }
            }

            return curElem;
        }

        curElem = curElem->fNext;
    }
    return 0;
}

template <class TVal> const DOMDeepNodeListPoolTableBucketElem<TVal>* DOMDeepNodeListPool<TVal>::
findBucketElem(const void* const key1, const XMLCh* const key2, const XMLCh* const key3, XMLSize_t& hashVal) const
{
    // Hash the key
    hashVal = fHash->getHashVal(key1, fHashModulus, fMemoryManager);
    assert(hashVal < fHashModulus);
    
    // Search that bucket for the key
    const DOMDeepNodeListPoolTableBucketElem<TVal>* curElem = fBucketList[hashVal];
    while (curElem)
    {
        //key2 and key3 are XMLCh*, compareString takes null pointer vs zero len string the same
        //but we need them to be treated as different keys in this case
        if (fHash->equals(key1, curElem->fKey1) && (XMLString::equals(key2, curElem->fKey2)) && (XMLString::equals(key3, curElem->fKey3))) {
            if (!key2 || !curElem->fKey2) {
                if (key2 || curElem->fKey2) {
                    curElem = curElem->fNext;
                    continue;
                }
            }
            if (!key3 || !curElem->fKey3) {
                if (key3 || curElem->fKey3) {
                    curElem = curElem->fNext;
                    continue;
                }
            }
            return curElem;
        }

        curElem = curElem->fNext;
    }
    return 0;
}

XERCES_CPP_NAMESPACE_END

