/* 
 * $Id: XDTPObjectWrapper.cpp,v 1.4 2006/03/05 05:00:09 ozawa Exp $
 *
 * Copyright 2005- ONGS Inc. All rights reserved.
 * 
 * author: Masanori OZAWA (ozawa@ongs.co.jp)
 * version: $Revision: 1.4 $
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY ONGS INC ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL ONGS INC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of the ONGS Inc.
 * 
 */

#include "xdtp.h"
#include "XDTPObjectWrapper.h"

#define CHECK_OUT_OF_RANGE(POS)     if (0 > POS || size() <= POS) { \
                                        THROW("XDTPObjectWrapper: Out of range."); \
                                    }

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
namespace XDTP {
void objectwrapper_null_destractor(void*)
{
    // no operation
}
};

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
using namespace XDTP;

Int2PointerMap  XDTPObjectWrapper::m_Destractors;

XDTPObjectWrapper::XDTPObjectWrapper()
{
}

XDTPObjectWrapper::~XDTPObjectWrapper()
{
    clear();
}

void XDTPObjectWrapper::add(int aType, const void* aValue)
{
#ifdef DEBUG
    if (m_Destractors.find(aType) == m_Destractors.end()) {
        fprintf(stderr, "%s: warning: XDTPObjectWrapper has no destractor." LINE_SEP
                        "%s: warning: Maybe this object leak. (%d)",
                APP_NAME, APP_NAME, aType);
    }
#endif
    
    m_Types.push_back(aType);
    m_Pointers.push_back((void*)aValue);
}

void XDTPObjectWrapper::insert(int aPos, int aType, const void* aValue)
{
#ifdef DEBUG
    if (m_Destractors.find(aType) == m_Destractors.end()) {
        fprintf(stderr, "%s: warning: XDTPObjectWrapper has no destractor." LINE_SEP
                        "%s: warning: Maybe this object leak. (%d)",
                APP_NAME, APP_NAME, aType);
    }
#endif

    CHECK_OUT_OF_RANGE(aPos);
    
    IntVector::iterator iiter = m_Types.begin();
    PointerVector::iterator piter = m_Pointers.begin();
    for (int count = 0; count < aPos; iiter++, piter++);

    m_Types.insert(iiter, aType);
    m_Pointers.insert(piter, (void*)aValue);
}

void XDTPObjectWrapper::set(int aPos, int aType, const void* aValue)
{
#ifdef DEBUG
    if (m_Destractors.find(aType) == m_Destractors.end()) {
        fprintf(stderr, "%s: warning: XDTPObjectWrapper has no destractor." LINE_SEP
                        "%s: warning: Maybe this object leak. (%d)",
                APP_NAME, APP_NAME, aType);
    }
#endif
    
    CHECK_OUT_OF_RANGE(aPos);
    
    m_Types.at(aPos) = aType;
    m_Pointers.at(aPos) = (void*)aValue;
}

void* XDTPObjectWrapper::get(int aPos, int *aType) const
{
    CHECK_OUT_OF_RANGE(aPos);
    
    if (aType) *aType = m_Types.at(aPos);
    return (void*)m_Pointers.at(aPos);
}

void XDTPObjectWrapper::erase(int aPos, bool bErase)
{
    CHECK_OUT_OF_RANGE(aPos);
    
    int type;
    void *value = get(aPos, &type);
    Int2PointerMap::iterator iter = m_Destractors.find(type);
    
    IntVector::iterator iiter = m_Types.begin();
    PointerVector::iterator piter = m_Pointers.begin();
    for (int count = 0; count < aPos; iiter++, piter++);

    if (bErase) {
        if (iter != m_Destractors.end() && iter->second) {
            void(*destractor)(void*) = (void(*)(void*))iter->second;
            destractor(value);
        }
        else {
            fprintf(stderr, "%s: warning: XDTPObjectWrapper has no destractor." LINE_SEP
                            "%s: warning: Maybe this object leak. (%d)",
                    APP_NAME, APP_NAME, type);
        }
    }
    
    m_Types.erase(iiter);
    m_Pointers.erase(piter);
}

void XDTPObjectWrapper::clear(bool bErase)
{
    while (0 < size()) {
        erase(0, bErase);
    }
}

int XDTPObjectWrapper::size() const
{
    return m_Types.size();
}

void XDTPObjectWrapper::setDestractor(int aType, void(*destractor)(void*))
{
    m_Destractors[aType] = (void*)destractor;
}


syntax highlighted by Code2HTML, v. 0.9.1