/*
 * 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(XTOKENNUMBERADAPTERALLOCATOR_INCLUDE_GUARD_1357924680)
#define XTOKENNUMBERADAPTERALLOCATOR_INCLUDE_GUARD_1357924680



// Base include file.  Must be first.
#include <xalanc/XPath/XPathDefinitions.hpp>



#include <xalanc/XPath/XTokenNumberAdapter.hpp>



#include <xalanc/PlatformSupport/ReusableArenaAllocator.hpp>



namespace XALAN_CPP_NAMESPACE {



class XALAN_XPATH_EXPORT XTokenNumberAdapterAllocator
{
public:

    typedef XTokenNumberAdapter                     object_type;

    typedef ReusableArenaAllocator<object_type>     ArenaAllocatorType;
    typedef ArenaAllocatorType::size_type           size_type;

    /**
     * Construct an instance that will allocate blocks of the specified size.
     *
     * @param theBlockSize The block size.
     */
    XTokenNumberAdapterAllocator(
            MemoryManager&  theMemoryManager,
            size_type       theBlockCount);

    ~XTokenNumberAdapterAllocator();

    /**
     * Create an instance from an XToken.
     * 
     * @param theXToken The source XToken
     *
     * @return A pointer to the new object
     */
    object_type*
    create(const XToken&    theXToken);

    /**
     * Delete an XStringAdapter object from allocator.   
     */
    bool
    destroy(object_type*    theObject);

    /**
     * Determine if an object is owned by the allocator...
     */
    bool
    ownsObject(const object_type*   theObject)
    {
        return m_allocator.ownsObject(theObject);
    }

    /**
     * Delete all XStringAdapter objects from allocator.     
     */
    void 
    reset();

    /**
     * Get size of an ArenaBlock, that is, the number
     * of objects in each block.
     *
     * @return The size of the block
     */
    size_type
    getBlockCount() const
    {
        return m_allocator.getBlockCount();
    }

    /**
     * Get the number of ArenaBlocks currently allocated.
     *
     * @return The number of blocks.
     */
    size_type
    getBlockSize() const
    {
        return m_allocator.getBlockSize();
    }

private:

    MemoryManager&
    getMemoryManager()
    {
        return m_allocator.getMemoryManager();
    }

    // Not implemented...
    XTokenNumberAdapterAllocator(const XTokenNumberAdapterAllocator&);

    XTokenNumberAdapterAllocator&
    operator=(const XTokenNumberAdapterAllocator&);

    // Data members...
    ArenaAllocatorType  m_allocator;
};



}



#endif  // XTOKENNUMBERADAPTERALLOCATOR_INCLUDE_GUARD_1357924680
