/*------------------------------------------------------------------------------
	FILE	:	DynArray.h
	CREATED	:	97/12/02
	AUTHOR	:	Catalin Cocos
	CONTENTS:	dynamic pointer array with sorting capabilities
------------------------------------------------------------------------------*/

#ifndef __DMS_DYN_ARRAY__
#define __DMS_DYN_ARRAY__

/*
 *  To export code.
 */
#undef CPA_EXPORT
#if defined(CPA_WANTS_IMPORT)
#define CPA_EXPORT __declspec(dllimport)
#elif defined(CPA_WANTS_EXPORT)
#define CPA_EXPORT __declspec(dllexport)
#else /* CPA_WANTS_IMPORT */
#define CPA_EXPORT
#endif /* CPA_WANTS_IMPORT */

/*------------------------------------------------------------------------------
	TYPES
------------------------------------------------------------------------------*/

typedef struct LDT_tdst_DSArray_  LDT_tdst_DSArray;

struct LDT_tdst_DSArray_
{
	void**	pData;		/*the array of pointers*/
	int		nSize;		/*the size of the array*/
	int		nMaxSize;	/*the allocated size*/
	int		nGrowBy;	
	int		nSortKey;	/*the key to sort the array by*/
	int (* pfnCompare)(const void**, const void** ); /*the comparison function*/
};

/*------------------------------------------------------------------------------
	FUNCTIONS
------------------------------------------------------------------------------*/

/*creation, initialization, deletion
--------------------------------------*/

CPA_EXPORT LDT_tdst_DSArray* LDT_DSAr_new();				/* creates a new array */
CPA_EXPORT int LDT_DSAr_Init( LDT_tdst_DSArray* );			/* initializes an array */
CPA_EXPORT void LDT_DSAr_delete( LDT_tdst_DSArray* );		/* deletes an existing array*/

CPA_EXPORT void LDT_DSAr_SetGranularity(LDT_tdst_DSArray*, int);
CPA_EXPORT void LDT_DSAr_SetSortMethod(LDT_tdst_DSArray*, int (*)(const void**, const void** ));

/* standard pointer array functionality
-----------------------------------------*/

	/* Attributes */

CPA_EXPORT int LDT_DSAr_GetSize( LDT_tdst_DSArray* );
CPA_EXPORT int LDT_DSAr_GetUpperBound( LDT_tdst_DSArray* );
CPA_EXPORT int LDT_DSAr_SetSize( LDT_tdst_DSArray*, int nNewSize );

/* Operations */
	
	/* Clean up */

CPA_EXPORT void LDT_DSAr_FreeExtra( LDT_tdst_DSArray* );
CPA_EXPORT void LDT_DSAr_RemoveAll( LDT_tdst_DSArray* );

	/* Accessing elements */

CPA_EXPORT void* LDT_DSAr_GetAt(LDT_tdst_DSArray*, int nIndex);
CPA_EXPORT void LDT_DSAr_SetAt(LDT_tdst_DSArray*, int nIndex, void* newElement);
CPA_EXPORT void** LDT_DSAr_ElementAt(LDT_tdst_DSArray*, int nIndex);

	/* Potentially growing the array */

CPA_EXPORT int LDT_DSAr_Add(LDT_tdst_DSArray*, void* newElement);

	/* Operations that move elements around */

CPA_EXPORT int LDT_DSAr_InsertAt(LDT_tdst_DSArray*, int nIndex, void* newElement );
CPA_EXPORT void* LDT_DSAr_RemoveAt(LDT_tdst_DSArray*, int nIndex );
CPA_EXPORT int LDT_DSAr_InsertArrayAt(LDT_tdst_DSArray*, int nStartIndex, LDT_tdst_DSArray* pNewArray);

/* sorting facilities 
------------------------*/

	/* Sorting elements */

CPA_EXPORT void LDT_DSAr_QSort( LDT_tdst_DSArray* );

	/* Adding elements */

CPA_EXPORT int LDT_DSAr_SAdd( LDT_tdst_DSArray*, void* newElement, int AdmitDuplicates, int* position );

	/* Searching elements */
CPA_EXPORT int LDT_DSAr_Index( LDT_tdst_DSArray*, void* newElement, int *p_iidx );
CPA_EXPORT int LDT_DSAr_UpperBound( LDT_tdst_DSArray*, int idx);
CPA_EXPORT int LDT_DSAr_LowerBound( LDT_tdst_DSArray*, int idx);




/*------------------------------------------------------------------------------
	INLINE FUNCTIONS IMPLEMENTATION
------------------------------------------------------------------------------*/



/*------------------------------------------------------------------------------
	DESC.	:	sets the array's granularity
	CREATED	:	97/12/02	
	AUTHOR	:	Catalin Cocos
------------------------------------------------------------------------------*/
__inline void LDT_DSAr_SetGranularity(LDT_tdst_DSArray* pst_Ar, int _nGrowBy )
{
	pst_Ar->nGrowBy = ( 0>_nGrowBy? 0: _nGrowBy );
}

/*------------------------------------------------------------------------------
	DESC.	:	sets the array's sort method. If NULL, the array's sort functions
				are not effective.
	WARNING	:	The sort method must be set prior to the use of any sort-related
				functions.
	CREATED	:	97/12/02	
	AUTHOR	:	Catalin Cocos
------------------------------------------------------------------------------*/
__inline void LDT_DSAr_SetSortMethod(LDT_tdst_DSArray* pst_Ar,
								 int (*_pfnCompare)(const void**, const void** ))
{
	pst_Ar->pfnCompare = _pfnCompare;
}

/*------------------------------------------------------------------------------
	DESC.	:	gets the array's number of elements
	CREATED	:	97/12/02	
	AUTHOR	:	Catalin Cocos
------------------------------------------------------------------------------*/
__inline int LDT_DSAr_GetSize( LDT_tdst_DSArray* pst_Ar )
{
	return pst_Ar->nSize;
}

/*------------------------------------------------------------------------------
	DESC.	:	gets the array's upper bound (maximum index)
	CREATED	:	97/12/02	
	AUTHOR	:	Catalin Cocos
------------------------------------------------------------------------------*/
__inline int LDT_DSAr_GetUpperBound( LDT_tdst_DSArray* pst_Ar )
{
	return pst_Ar->nSize-1;
}

/*------------------------------------------------------------------------------
	DESC.	:	sets the array's size. - returns 1 if successful, 0 on error;
	CREATED	:	97/12/02	
	AUTHOR	:	Catalin Cocos
------------------------------------------------------------------------------*/
__inline void LDT_DSAr_RemoveAll( LDT_tdst_DSArray* pst_Ar )
{
	LDT_DSAr_SetSize( pst_Ar, 0 ); /* clean-up */
}


/*------------------------------------------------------------------------------
	DESC.	:	Gets the value of an array element. returns NULL on error
	CREATED	:	97/12/02	
	AUTHOR	:	Catalin Cocos
------------------------------------------------------------------------------*/
__inline void* LDT_DSAr_GetAt(LDT_tdst_DSArray* pst_Ar, int nIndex)
{
	if(nIndex < 0 || nIndex >= pst_Ar->nSize) return NULL;
	return pst_Ar->pData[nIndex];
}

/*------------------------------------------------------------------------------
	DESC.	:	Sets an array element. If the index is out of bounds, nothing happens
	CREATED	:	97/12/02	
	AUTHOR	:	Catalin Cocos
------------------------------------------------------------------------------*/
__inline void LDT_DSAr_SetAt(LDT_tdst_DSArray* pst_Ar, int nIndex, void* newElement)
{
	if(nIndex < 0 || nIndex >= pst_Ar->nSize) return;
	pst_Ar->pData[nIndex] = newElement;
}


/*------------------------------------------------------------------------------
	DESC.	:	Gets an array element. returns NULL on error
	CREATED	:	97/12/02	
	AUTHOR	:	Catalin Cocos
------------------------------------------------------------------------------*/
__inline void** LDT_DSAr_ElementAt(LDT_tdst_DSArray* pst_Ar, int nIndex)
{
	if(nIndex < 0 || nIndex >= pst_Ar->nSize) return NULL;
	return pst_Ar->pData + nIndex;
}

#endif/*__DMS_DYN_ARRAY__*/
