/* 
 * File:   Vector.h
 * Author: Me
 *
 * Created on May 14, 2010, 3:08 PM
 */

#ifndef _DYNARRAY_H
#define	_DYNARRAY_H

#include <PR__include/PR__primitive_data_types.h>



/*WARNING: Passing a DynArray as a param is dangerous if add to the DynArray
 * inside the function called!   After adding or other operation that might
 * change the size, must re-read the addr of the chunk of memory that is the
 * array, via the DynArrayInfo.
 *Here's why: An array variable is a location, either on the stack
 * or in a field of a struct, whose contents is an addr.  That addr is of the
 * first location of a chunk of locations.  The DynArray works by changing
 * the chunk of locations, then modifying the contents of the original 
 * array variable.  It overwrites the addr of the old chunk of locations
 * with the addr of the new chunk.
 *But when the array variable is passed as a parameter, such as 
 * in this: "foo( myDynArray )", then there are now two locations that hold
 * the addr of the same chunk of locations.  So when a call is made that
 * adds to the DynArray, and inside the DynArray expands, it only updates
 * the original location with  the new addr.  Hence, the function will begin
 * overwriting memory past the end of the old chunk, because it still has 
 * the pointer to the old chunk of locations.
 *
 *A dynamic array is accessed same as any other array.  However, must use
 * dyn array calls, defined in here, in order to add or increase the size.
 * Must re-read the original array variable after any size-changing calls.
 *To pass a DynArray as a parameter to a function, can only pass the 
 * DynArrayInfo, then inside the function, to read the addr of the first 
 * location in the chunk of locations that is the array, do this:
 * "localArrayCopy = *(myDynArrayInfo->addrOfPtrToArray).  After that, can 
 * treat localArrayCopy as a normal array, as long as don't make any calls
 * that add or otherwise could increase the size of the array.  If do make
 * such a call, then re-copy the array via the above.  Can then use the
 * copy up until another add to the array.
 * 
 */
typedef struct
 {
   void ***addrOfPtrToArray; //addr of var that is array of ptrs == triple *
   int32   numInArray;  //num entries added
   int32   sizeOfArray; //num elems alloc'd
   int32   sizeOfElem;  //num bytes in one elem of array -- used in 2nd version
 }
PrivDynArrayInfo;

PrivDynArrayInfo *
makePrivDynArrayInfoFrom( void ***addrOfPtrToArray, int32 sizeOfArray );

PrivDynArrayInfo *
makePrivDynArrayOfSize( void ***addrOfPtrToArray, int32 sizeOfArray );

PrivDynArrayInfo *
makePrivDynArrayOfSize_Ext( void ***addrOfPtrToArray, int32 sizeOfArray );

int32
addToDynArray( void *value, PrivDynArrayInfo *info );

void
makeHighestDynArrayIndexBe( PrivDynArrayInfo *info, int32 highestIndex );

void
makeHighestDynArrayIndexBeAtLeast(PrivDynArrayInfo *info,int32 highestIndex);

void
increaseSizeOfDynArrayTo( PrivDynArrayInfo *info, int32 newSize );

typedef void  (*FreeFnPtr)  ( void * ); //fn has to cast void * to whatever

void
freeDynArrayDeep( PrivDynArrayInfo *info, FreeFnPtr freeFnPtr );

void
freeDynArrayFlat( PrivDynArrayInfo *info );


typedef void  (*DynArrayFnPtr)  ( void * );  //fn has to cast void *

void
forAllInDynArrayDo( PrivDynArrayInfo *info, DynArrayFnPtr fnPtr );

#endif	/* _DYNARRAY_H */

