///////////////////////////////////////////////////////////////////////////////
/// @file deDynamicArray.cpp
///
/// @brief Dynamic Array Class
///
/// @author Hootie
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Oct 2001
/// @author Hootie
/// @remarks Rearchitecture II
///
///////////////////////////////////////////////////////////////////////////////


//=================================================================================
// Includes
//=================================================================================

#include "deShared.hpp"
#include <memory.h> // memcpy, etc



//=================================================================================
// deDynamicArray::deDynamicArray()
//
// Constructor 
//=================================================================================
deDynamicArray::deDynamicArray(const unsigned int Size, const unsigned int Count)
{
   ElementSize = 0;
   ElementCount = 0;
   Array = NULL;
   CreationResult = deFALSE;
   ArrayGrowthRate = 100;


   if (Size == 0 || Count == 0)
   {
      //error - Invalid parms
      return;
   }

   Array = malloc(Size * Count);

   if (!Array)
   {
      //error - Array allocation failed
      return;
   }

   ElementSize = Size;
   ElementCount = Count;
   CreationResult = deTRUE;

   return;
}



//=======================================================================================
// deDynamicArray::deDynamicArray()
//
// Copy Constructor
//=======================================================================================
deDynamicArray::deDynamicArray(deDynamicArray &deDynamicArraySource)
{
   ElementSize = 0;
   ElementCount = 0;
   Array = NULL;
   CreationResult = deFALSE;


   if (deDynamicArraySource.ElementSize == 0 || deDynamicArraySource.ElementCount == 0)
   {
      //error - Copying null array
      return;
   }

   Array = malloc(deDynamicArraySource.ElementSize * deDynamicArraySource.ElementCount);

   if (!Array)
   {
      //error - Array allocation failed
      return;
   }

   memcpy(Array, deDynamicArraySource.Array, deDynamicArraySource.ElementSize * deDynamicArraySource.ElementCount);

   ElementSize = deDynamicArraySource.ElementSize;
   ElementCount = deDynamicArraySource.ElementCount;
   CreationResult = deTRUE;

   return;
}



//=======================================================================================
// deDynamicArray::~deDynamicArray()
//
// Destructor
//=======================================================================================
deDynamicArray::~deDynamicArray()
{
   if (Array)
   {
      free(Array);
      Array = NULL;
   }
} 



//=======================================================================================
// deDynamicArray::GetElement()
//
// Get an indexed element.
//=======================================================================================
void *deDynamicArray::GetElement(unsigned int Index)
{
   if (Index > ElementCount)
   {
      //error - Array bounds exceeded
      return NULL;
   }

   return (void *)(((long)(Array)) + (Index * ElementSize));
} 



//=======================================================================================
// deDynamicArray::SetElement()
//
// Set an indexed element.
//=======================================================================================
deBoolean deDynamicArray::SetElement(void *Element, unsigned int Index)
{
   if (Index > ElementCount)
   {
      if ((Index - ElementCount) > ArrayGrowthRate)
      {
         if (!GrowArray(Index - ElementCount))
         {
            //error - GrowArray failed
            return deFALSE;
         }
      }
      else
      {
         if (!GrowArray(ArrayGrowthRate))
         {
            //error - GrowArray failed
            return deFALSE;
         }
      }
   }

   memcpy((void *)(((long)(Array)) + (Index * ElementSize)), Element, ElementSize);

   return deTRUE;
} 



//=======================================================================================
// deDynamicArray::GrowArray()
//
// Increase the array size.
//=======================================================================================
deBoolean deDynamicArray::GrowArray(unsigned int SizeIncrease)
{
   void *NewArray = NULL;

   
   NewArray = realloc(Array, (ElementCount + SizeIncrease) * ElementSize);

   if (!NewArray)
   {
      //error - Realloc failed
      return deFALSE;
   }

   Array = NewArray;
   ElementCount = ElementCount + SizeIncrease;

   return deTRUE;
} 


