/*****************************************************************************
 *
 * $Id$
 *
 * Copyright (C) 2009 - 2012  Richard Hacker <lerich@gmx.net>
 *                            Florian Pose <fp@igh-essen.com>
 *
 * This file is part of the PdCom library.
 *
 * The PdCom library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * The PdCom library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with the PdCom Library. If not, see <http://www.gnu.org/licenses/>.
 *
 ****************************************************************************/

#include <inttypes.h>

#include "pdcom/Data.h"

#define DEBUG 0

#if DEBUG
#include <iostream>
namespace {
    using std::cout;
    using std::cerr;
    using std::endl;
}
#endif

using namespace PdCom;

////////////////////////////////////////////////////////////////////////////
//  class Data
////////////////////////////////////////////////////////////////////////////
Data::Data(const Type& type, const Dimension& dim,
        const Allocator& a):
    type(type),
    dimension(dim),
    dataPtr(0),
    elementCount(dimension.getElementCount()),
    memSize(elementCount * getTypeWidth(type)),
    allocator(a)
{
#if DEBUG
    cout << __func__ << "() ctor: allocated " << memSize << " bytes" << endl;
#endif
}

/****************************************************************************/
Data::~Data()
{
    allocator.deallocate(dataPtr);
}

/****************************************************************************/
void Data::allocateMemory()
{
    if (!dataPtr)
        dataPtr = allocator.allocate(elementCount, type);
}

/****************************************************************************/
size_t Data::getTypeWidth(Type t)
{
    switch(t) {
        case bool_T:
            return sizeof(bool);
        case uint8_T:
        case sint8_T:
            return sizeof(char);
        case uint16_T:
        case sint16_T:
            return sizeof(uint16_t);
        case uint32_T:
        case sint32_T:
            return sizeof(uint32_t);
        case uint64_T:
        case sint64_T:
            return sizeof(uint64_t);
        case double_T:
            return sizeof(double);
        case single_T:
            return sizeof(float);
    }

    return 0;
}

/****************************************************************************/
const char* Data::getDataPtr(const Dimension* idx) const
{
#if DEBUG
    cout << __func__ << "(): returning " << dimension.getOffset(idx) << endl;
#endif
    return dataPtr + dimension.getOffset(idx);
}
