/*
*****************************************************************************************
*                                                                                       *
* COPYRIGHT:                                                                            *
*   IBM Open Class Library                                                              *
*   (C) Copyright International Business Machines Corporation,  1997                    *
*   Licensed Material - Program-Property of IBM - All Rights Reserved.                  *
*                                                                                       *
*****************************************************************************************
*/
// Revision: 14 1.7.1.8 source/albert/graph2d/irawarr.inl, 2d, ioc.v400, 001006 
/*================
||
||  File:   RawArrayImp.h
||
||  What:   Definitions for Low level array template for objects that don't need construction
||
||
||  Change History:
*/

#ifndef _IRAWARR_INL_
#define _IRAWARR_INL_

#ifndef IC_BUILD
#define __IOC_INLINE inline
#else
#define __IOC_INLINE
#endif

#ifndef HIDE_TEMPLATE_DEFINITIONS
#define MAKE_TRawArray_DEFINITIONS_VISIBLE
#endif

#ifndef _IGREXEPT_
#include <igrexept.hpp>
#endif

#ifdef IC_MOTIF
#include <stdlib.h>
#endif //MOTIF

#include <malloc.h>

// Accessor functions are inline to provide equivalent performance

// If we are NOT defining the methods, then make the inlines visible
// to those who may need them

#ifdef MAKE_TRawArray_DEFINITIONS_VISIBLE
#ifdef IC_BUILD
#define inline
#endif
#endif

template <class AType>
inline
AType& IRawArray<AType>::operator[]( unsigned long i )
{
    return fValues[i];
}

template <class AType>
inline
const AType& IRawArray<AType>::operator[]( unsigned long i ) const
{
    return fValues[i];
}

#ifdef MAKE_TRawArray_DEFINITIONS_VISIBLE
#ifdef IC_BUILD
#undef inline
#endif
#else // MAKE_TRawArray_DEFINITIONS_VISIBLE

const kDefaultGrowAmount = 8;

template <class AType>
__IOC_INLINE
void IRawArray<AType>::setGrowIncrement( unsigned long increment )
{
    IGraphicException::InternalAssert(increment != 0, "RawArray grow amount zero");
    fGrowAmount = increment;
}

template <class AType>
__IOC_INLINE
unsigned long IRawArray<AType>::growIncrement() const
{
    return fGrowAmount;
}

template <class AType>
__IOC_INLINE
AType IRawArray<AType>::value( unsigned long i ) const
{
    IGraphicException::InternalAssert(i < fNumberOfValues, "RawArray index out of range" );
    return fValues[i];
}

template <class AType>
__IOC_INLINE
void IRawArray<AType>::setValue( unsigned long i, const AType& p )
{
    IGraphicException::InternalAssert(i < fNumberOfValues, "RawArray index out of range" );
    fValues[i] = p;
}

template <class AType>
__IOC_INLINE
void IRawArray<AType>::append( const AType& value )
{
    resize( fNumberOfValues + 1 ); // This changes fNumberOfValues!
    fValues[fNumberOfValues - 1] = value;
}

// Returns pointer to same heap as one object is in, or the default
// heap if object is not in a heap (i.e., allocated on stack frame)

/***********************************************************
template <class AType>
TMemoryHeap * IRawArray<AType>::myHeap() const
{
    TMemoryHeap * myheap;
    if (! (myheap = TMemoryHeap::HeapOf( this )))
        myheap = TMemoryHeap::GetDefaultHeap();
    return myheap;
}
***********************************************************/

template <class AType>
__IOC_INLINE
unsigned long IRawArray<AType>::roundUpSize( unsigned long newsize ) const
{
    unsigned long wholePieces = newsize / fGrowAmount;
    if (newsize % fGrowAmount)
        ++wholePieces;
    return wholePieces * fGrowAmount;
}

template <class AType>
__IOC_INLINE
IRawArray<AType>::IRawArray( unsigned long size )
{
    fNumberOfValues = size;
    fGrowAmount = kDefaultGrowAmount; // Must assign before calling roundUpSize!
    // Don't round up the size - saves heap space on arrays that never change
    fArraySize = size;

/***********************************************************
    fValues = fArraySize ? (AType *)myHeap()->Allocate(((size_t) fArraySize)
                                                          *sizeof( AType ))
        : 0; //NIL
***********************************************************/

    fValues = fArraySize ? (AType *)malloc(((size_t) fArraySize) * sizeof( AType)) : 0 /*NIL*/;
}

template <class AType>
__IOC_INLINE
IRawArray<AType>::IRawArray( const IRawArray<AType>& source )
{

    unsigned long i;
    AType *src, *dst;

    if (! source.fNumberOfValues)
        fValues = 0 /*NIL*/;
    else
    {

/***********************************************************
        TMemoryHeap * myheap = myHeap();
        fValues = (AType *) myheap->Allocate(((size_t) source.fArraySize)
                                             * sizeof( AType ));
***********************************************************/

        fValues = (AType *) malloc(((size_t) source.fArraySize) * sizeof( AType));

        src = source.fValues;
        dst = fValues;
        for (i = 0; i < source.fNumberOfValues; i++)
            *dst++ = *src++;
    }
    fGrowAmount = source.fGrowAmount;
    fArraySize = source.fArraySize;
    fNumberOfValues = source.fNumberOfValues;
}

template <class AType>
__IOC_INLINE
IRawArray<AType>::~IRawArray()
{

/***********************************************************
    if (fValues)
        TMemoryHeap::HeapOf( fValues )->Free( (void *) fValues );
***********************************************************/

    if (fValues) free(fValues);
    fValues = 0 /*NIL*/;

}

// Size access

template <class AType>
__IOC_INLINE
unsigned long  IRawArray<AType>::numberOfValues() const
{
    return fNumberOfValues;
}

template <class AType>
__IOC_INLINE
void IRawArray<AType>::resize( unsigned long newsize )
{
    if (newsize != fNumberOfValues)
    {
        if (fNumberOfValues == 0) // Empty to full...
        {
            fArraySize = roundUpSize( newsize );
/***********************************************************
            fValues = (AType *) myHeap()->Allocate(((size_t)fArraySize) *sizeof( AType ));
***********************************************************/

            fValues = (AType *) malloc(((size_t) fArraySize) * sizeof( AType ));
        }
        else
        if (newsize == 0)         // Full to empty...
        {
/***********************************************************
            TMemoryHeap::HeapOf( fValues )->Free( (void *) fValues );
***********************************************************/

            free(fValues);
            fValues = 0 /*NIL*/;

            fArraySize = 0;
        }                         // Full to full
        else
        {
            unsigned long newArraySize = roundUpSize( newsize );
            if (newArraySize != fArraySize)
            {
/***********************************************************
                fValues = (AType*)myHeap()
                    ->Reallocate((void*)fValues, (size_t)newArraySize*sizeof(AType));
***********************************************************/
                fValues = (AType*) realloc((void*)fValues, (size_t)newArraySize*sizeof(AType));
                fArraySize = newArraySize;
            }
        }
        fNumberOfValues = newsize;
    }
}

template <class AType>
__IOC_INLINE
void IRawArray<AType>::swap( IRawArray<AType>& victim )
{
    AType * tmpData;
    unsigned long tmpNum;

    tmpNum = fNumberOfValues;
    fNumberOfValues = victim.fNumberOfValues;
    victim.fNumberOfValues = tmpNum;

    tmpNum = fGrowAmount;
    fGrowAmount = victim.fGrowAmount;
    victim.fGrowAmount = tmpNum;

    tmpNum = fArraySize;
    fArraySize = victim.fArraySize;
    victim.fArraySize = tmpNum;

    tmpData = fValues;
    fValues = victim.fValues;
    victim.fValues = tmpData;
}

template <class AType>
__IOC_INLINE
IDataStream&    IRawArray<AType>::operator>>= (IDataStream& toWhere) const
{
        writeToStream(toWhere);
        return toWhere;
}

template <class AType>
__IOC_INLINE
IDataStream&    IRawArray<AType>::operator<<= (IDataStream& fromWhere)
{
        readFromStream (fromWhere);
        return fromWhere;
}

template <class AType>
__IOC_INLINE
void IRawArray<AType>::writeToStream( IDataStream& toWhere ) const
{
    unsigned long i;

    fNumberOfValues >>= toWhere;
    for (i = 0; i < fNumberOfValues; i++)
        fValues[i] >>= toWhere;
}

template <class AType>
__IOC_INLINE
void IRawArray<AType>::readFromStream( IDataStream& fromWhere )
{
    unsigned long i;

    if (fValues) free(fValues);
    fValues = 0 /*NIL*/;
    fNumberOfValues <<= fromWhere;
    fArraySize = fNumberOfValues;

    if (fNumberOfValues)
    {
        fValues = (AType *) malloc(((size_t) fArraySize) * sizeof( AType ));
        for (i = 0; i < fNumberOfValues; i++)
            fValues[i] <<= fromWhere;
    }
    else
        fValues = 0 /*NIL*/;
}

template <class AType>
__IOC_INLINE
IRawArray<AType>& IRawArray<AType>::operator=(const IRawArray<AType>& source)
{
    unsigned long i;
    AType *src, *dst;

    if (&source != this)
    {
        if (fArraySize != source.fArraySize)
        {
/***********************************************************
            if (fValues)
                myHeap()->Free( (void *) fValues );

            fValues = source.fNumberOfValues
                ? (AType *) myHeap()->Allocate(((size_t) source.fArraySize)
                                                  *sizeof( AType ) )
                : 0; //NIL
***********************************************************/
            if (fValues) free(fValues);
            fValues = source.fNumberOfValues ? (AType *) malloc(((size_t) source.fArraySize) * sizeof( AType )) : 0 /*NIL*/;
            fArraySize = source.fArraySize;
        }
        fGrowAmount = source.fGrowAmount;

        src = source.fValues;
        dst = fValues;
        for (i = 0; i < source.fNumberOfValues; i++)
            *dst++ = *src++;
        fNumberOfValues = source.fNumberOfValues;
    }
    return *this;
}

template <class AType>
__IOC_INLINE
bool IRawArray<AType>::operator==( const IRawArray<AType>& source ) const
{
    if (fNumberOfValues != source.fNumberOfValues)
        return false;

    bool returnValue = true;

    register unsigned long i;
    register AType *src = source.fValues, *dst = fValues;

    i = 0;

    while ((i < fNumberOfValues) && (returnValue = (*src++ == *dst++)))
        i++;

    return returnValue;
}

template <class AType>
__IOC_INLINE
bool IRawArray<AType>::operator!=( const IRawArray<AType>& src ) const
{
    return ! (*this == src);
}

#endif // MAKE_TRawArray_DEFINITIONS_VISIBLE

#endif // _IRAWARR_INL_
