/*
 * 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.
 */



#include "XalanMemoryManagerDefault.hpp"



#include "xercesc/util/OutOfMemoryException.hpp"



namespace XALAN_CPP_NAMESPACE {



XalanMemoryManagerDefault::XalanMemoryManagerDefault()
{
}



XalanMemoryManagerDefault::~XalanMemoryManagerDefault()
{
}



void*
XalanMemoryManagerDefault::allocate(size_type   size)
{
    using xercesc::OutOfMemoryException;

    void*   thePointer;

    try
    {
        thePointer = ::operator new(size);
    }
    catch(...)
    {
        throw OutOfMemoryException();
    }

    if (thePointer != 0)
    {
        return thePointer;
    }

    throw OutOfMemoryException();
}



void
XalanMemoryManagerDefault::deallocate(void*     pointer)
{
    ::operator delete(pointer);
}



MemoryManager*
XalanMemoryManagerDefault::getExceptionMemoryManager()
{
    return this;
}



}
