186 lines
4.2 KiB
C
186 lines
4.2 KiB
C
/*---------------------------------------------------------------------------
|
|
D Y N A M I C A R R A Y
|
|
|
|
Implementation file for a dynamically resizing array of void pointers.
|
|
|
|
Mark Koennecke, September 1997
|
|
|
|
copyright: see copyright.h
|
|
|
|
-----------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include "fortify.h"
|
|
#include "sdynar.h"
|
|
#include "sdynar.i"
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
pDynar CreateDynar(int iStart, int iEnd, int iGrain,
|
|
void (*DataFree) (void *pData))
|
|
{
|
|
pDynar pNew = NULL;
|
|
int iSize;
|
|
|
|
pNew = (pDynar) malloc(sizeof(Dynar));
|
|
if (!pNew) {
|
|
return NULL;
|
|
}
|
|
memset(pNew, 0, sizeof(Dynar));
|
|
|
|
pNew->iStart = iStart;
|
|
pNew->iEnd = iEnd;
|
|
pNew->iGrain = iGrain;
|
|
pNew->DataFree = DataFree;
|
|
iSize = iEnd - iStart;
|
|
assert(iSize > 0);
|
|
pNew->pArray = (void **) malloc(iSize * sizeof(void *));
|
|
if (!pNew->pArray) {
|
|
free(pNew);
|
|
return NULL;
|
|
}
|
|
memset(pNew->pArray, 0, iSize * sizeof(void *));
|
|
return pNew;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
void DeleteDynar(pDynar self)
|
|
{
|
|
int i, iSize;
|
|
|
|
assert(self);
|
|
|
|
iSize = self->iEnd - self->iStart;
|
|
for (i = 0; i < iSize; i++) {
|
|
if (self->pArray[i]) {
|
|
if (self->DataFree) {
|
|
self->DataFree(self->pArray[i]);
|
|
}
|
|
}
|
|
}
|
|
free(self->pArray);
|
|
free(self);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int DynarResize(pDynar self, int iRequest)
|
|
{
|
|
void **pNew = NULL;
|
|
int i, iNewStart, iNewEnd, iOldSize, iNewSize, iOffset;
|
|
|
|
assert(self);
|
|
iOldSize = self->iEnd - self->iStart;
|
|
|
|
iNewStart = self->iStart;
|
|
iNewEnd = self->iEnd;
|
|
if (iRequest <= self->iStart) {
|
|
iNewStart -= self->iGrain;
|
|
}
|
|
if (iRequest >= (self->iEnd - 1)) {
|
|
iNewEnd += self->iGrain;
|
|
}
|
|
iNewSize = iNewEnd - iNewStart;
|
|
|
|
pNew = (void **) malloc(iNewSize * sizeof(void *));
|
|
if (!pNew) {
|
|
return 0;
|
|
}
|
|
memset(pNew, 0, iNewSize * sizeof(void *));
|
|
|
|
iOffset = self->iStart - iNewStart;
|
|
if (iOffset < 0) {
|
|
iOffset = -iOffset;
|
|
}
|
|
for (i = 0; i < iOldSize; i++) {
|
|
pNew[i + iOffset] = self->pArray[i];
|
|
}
|
|
self->iStart = iNewStart;
|
|
self->iEnd = iNewEnd;
|
|
free(self->pArray);
|
|
self->pArray = pNew;
|
|
return 1;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
int DynarPut(pDynar self, int iIndex, void *pData)
|
|
{
|
|
int iReal, iRet;
|
|
|
|
assert(self);
|
|
|
|
if ((iIndex < self->iStart) || (iIndex > self->iEnd - 1)) {
|
|
iRet = DynarResize(self, iIndex);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
iReal = iIndex - self->iStart;
|
|
if (self->pArray[iReal]) {
|
|
if (self->DataFree) {
|
|
self->DataFree(self->pArray[iReal]);
|
|
}
|
|
}
|
|
self->pArray[iReal] = pData;
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int DynarPutCopy(pDynar self, int iIndex, void *pBuffer, int iDataLen)
|
|
{
|
|
char *pPtr = NULL;
|
|
|
|
pPtr = (char *) malloc(iDataLen);
|
|
if (!pPtr) {
|
|
return 0;
|
|
}
|
|
memcpy(pPtr, pBuffer, iDataLen);
|
|
return DynarPut(self, iIndex, pPtr);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int DynarReplace(pDynar self, int iIndex, void *pData, int iDataLen)
|
|
{
|
|
int iReal, iRet;
|
|
|
|
assert(self);
|
|
|
|
if ((iIndex < self->iStart) || (iIndex >= self->iEnd - 1)) {
|
|
iRet = DynarResize(self, iIndex);
|
|
if (!iRet) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
iReal = iIndex - self->iStart;
|
|
if (self->pArray[iReal]) {
|
|
memcpy(self->pArray[iReal], pData, iDataLen);
|
|
return 1;
|
|
} else {
|
|
return DynarPutCopy(self, iIndex, pData, iDataLen);
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
int DynarGet(pDynar self, int iIndex, void **pData)
|
|
{
|
|
int iReal;
|
|
|
|
assert(self);
|
|
|
|
iReal = iIndex - self->iStart;
|
|
*pData = self->pArray[iReal];
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int DynarGetCopy(pDynar self, int iIndex, void *pData, int iDataLen)
|
|
{
|
|
int iReal;
|
|
|
|
assert(self);
|
|
|
|
iReal = iIndex - self->iStart;
|
|
memcpy(pData, self->pArray[iReal], iDataLen);
|
|
return 1;
|
|
}
|