/*
 * 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.
 */
#if !defined(XALANARRAYALLOCATOR_HEADER_GUARD_1357924680)
#define XALANARRAYALLOCATOR_HEADER_GUARD_1357924680



#include <xalanc/PlatformSupport/PlatformSupportDefinitions.hpp>



#include <cassert>
#include <utility>



#include <xalanc/Include/XalanVector.hpp>
#include <xalanc/Include/XalanList.hpp>



namespace XALAN_CPP_NAMESPACE {



template<class Type>
class XALAN_PLATFORMSUPPORT_EXPORT XalanArrayAllocator
{
public:

    typedef XalanVector<Type>               VectorType;
    typedef typename VectorType::size_type  size_type;

    typedef std::pair<size_type, VectorType * >      ListEntryType;
    typedef XalanList<ListEntryType>                                ListType;

    typedef Type                            value_type;

    typedef typename ListType::iterator     ListIteratorType;

    // Default size for vector allocation.
    enum { eDefaultBlockSize = 500 };

    /**
     * Constructor.
     *
     * @param theBlockSize The block size when allocating.
     */
    XalanArrayAllocator(MemoryManager&       theManager,
                        size_type   theBlockSize = eDefaultBlockSize) :
        m_list(theManager),
        m_blockSize(theBlockSize),
        m_lastEntryFound(0)
    {
    }

    ~XalanArrayAllocator()
    {        
        typename ListType::iterator iter = m_list.begin();

        MemoryManager& theManager = m_list.getMemoryManager();

        for( iter = m_list.begin(); iter != m_list.end(); ++iter)
        {
            if( (*iter).second != 0)
            {
                (*iter).second->VectorType::~VectorType();
                theManager.deallocate((void*)(*iter).second);
            }
        }
    }

    /**
     * Clear the instance, and release all allocated memory
     */
    void
    clear()
    {
        m_list.clear();

        m_lastEntryFound = 0;
    }

    /**
     * Reset the instance, but keep all memory so it can be
     * reused for allocations.  This invalidates all previous
     * allocations.
     */
    void
    reset()
    {
        if (m_list.empty() == true)
        {
            m_lastEntryFound = 0;
        }
        else
        {
            const ListIteratorType  theEnd = m_list.end();
            ListIteratorType        theCurrent = m_list.begin();

            do
            {
                (*theCurrent).first = (*theCurrent).second->size();

                ++theCurrent;
            } while(theCurrent != theEnd);

            m_lastEntryFound = &*m_list.begin();
        }
    }

    /**
     * Allocate slots for the given number of Types
     * instance and return the address of the slots.
     *
     * @param theCount The number of slots to allocate
     */
    Type*
    allocate(size_type  theCount)
    {
        // Handle the case of theCount being greater than the block size first...
        if (theCount >= m_blockSize)
        {
            return createEntry(theCount, theCount);
        }
        else
        {
            ListEntryType*  theEntry =
                findEntry(theCount);

            // Did we find a slot?
            if (theEntry == 0)
            {
                // Nope, create a new one...
                return createEntry(m_blockSize, theCount);
            }
            else
            {
                // The address we want is that of the first free element in the
                // vector...
                assert( theEntry->second != 0);
                Type* const     thePointer =
                    &*theEntry->second->begin() + (theEntry->second->size() - theEntry->first);

                // Resize the vector to the appropriate size...
                theEntry->first -= theCount;

                return thePointer;
            }
        }
    }

private:

    // Utility functions...
    Type*
    createEntry(
            size_type   theBlockSize,
            size_type   theCount)
    {
        assert(theBlockSize >= theCount);

        // Push on a new entry.  The entry has no open space,
        // since it's greater than our block size...
        m_list.push_back(ListEntryType(0, VectorType::create(m_list.getMemoryManager())));

        // Get the new entry...
        ListEntryType&  theNewEntry = m_list.back();

        // Resize the vector to the appropriate size...
        assert(theNewEntry.second);

        theNewEntry.second->resize(theBlockSize, value_type());

        // Set the number of free spaces accordingly...
        theNewEntry.first = theBlockSize - theCount;

        if (theNewEntry.first != 0)
        {
            m_lastEntryFound = &theNewEntry;
        }

        // Return a pointer to the beginning of the allocated memory...
        return &*theNewEntry.second->begin();
    }

    ListEntryType*
    findEntry(size_type     theCount)
    {
        // Search for an entry that has some free space.

        if (m_lastEntryFound != 0 && m_lastEntryFound->first >= theCount)
        {
            return m_lastEntryFound;
        }
        else
        {
            const ListIteratorType  theEnd = m_list.end();
            ListIteratorType        theCurrent = m_list.begin();

            ListEntryType*  theEntry = 0;

            while(theCurrent != theEnd)
            {
                // We're looking for the best fit, so
                // if the free space and the count we're
                // looking for are equal, that's pretty
                // much the best we can do...
                if ((*theCurrent).first == theCount)
                {
                    theEntry = &*theCurrent;

                    break;
                }
                else if ((*theCurrent).first >= theCount)
                {
                    // If we haven't found anything yet, the first
                    // entry we find that's large enough becomes
                    // our best fit.
                    //
                    // Otherwise, we'll assume that a smaller
                    // slot is a better fit, though I may be
                    // wrong about this...
                    if (theEntry == 0 ||
                        (*theCurrent).first < theEntry->first)
                    {
                        // Nope, so this becomes our best-fit so far.
                        theEntry = &*theCurrent;
                    }

                    ++theCurrent;
                }
                else
                {
                    // Won't fit, so just continue...
                    ++theCurrent;
                }
            }

            m_lastEntryFound = theEntry;

            return theEntry;
        }
    }

    // Not implemented...
    XalanArrayAllocator(const XalanArrayAllocator<Type>&    theSource);

    XalanArrayAllocator<Type>&
    operator=(const XalanArrayAllocator<Type>&  theSource);

    bool
    operator==(const XalanArrayAllocator<Type>& theRHS) const;


    // Data members...
    ListType            m_list;

    const size_type     m_blockSize;

    ListEntryType*      m_lastEntryFound;
};



}



#endif  // !defined(XALANARRAYALLOCATOR_HEADER_GUARD_1357924680)
