seanhalle@33: /* seanhalle@33: * Copyright 2010 OpenSourceCodeStewardshipFoundation seanhalle@33: * seanhalle@33: * Licensed under BSD seanhalle@33: */ seanhalle@33: seanhalle@33: seanhalle@33: seanhalle@33: #include seanhalle@33: #include seanhalle@33: seanhalle@33: #include "DynArray.h" seanhalle@33: seanhalle@33: //== declarations seanhalle@33: #define giveInfoFor( array ) &(((PrivDynArrayInfo*)array)[-1]) seanhalle@33: //== seanhalle@33: seanhalle@33: /*This updates the contents of the array variable, by side-effect. There can seanhalle@33: * only ever be one variable that holds a pointer to the dyn array, and all seanhalle@33: * accesses must use that variable. An add can cause the contents of that seanhalle@33: * variable to change! (Meaning the position of the array has moved) seanhalle@33: */ seanhalle@33: void * seanhalle@33: makePrivDynArray2( void ***addrOfArrayVar, int32 numElemsToAllocate, int32 sizeOfElem ) seanhalle@33: { PrivDynArrayInfo *info; seanhalle@33: int32 bytesInArray = numElemsToAllocate * sizeOfElem; seanhalle@33: seanhalle@33: info = PR_int__malloc( sizeof(PrivDynArrayInfo) + bytesInArray ); seanhalle@33: info->addrOfPtrToArray = addrOfArrayVar; seanhalle@33: info->sizeOfArray = numElemsToAllocate; seanhalle@33: info->sizeOfElem = sizeOfElem; seanhalle@33: info->numInArray = 0; seanhalle@33: return &(info[1]); //skip over prolog -- info is prolog seanhalle@33: } seanhalle@33: seanhalle@33: seanhalle@33: /*A dynamic array is same as any other array, but add a DynArrayInfo next seanhalle@33: * to it. Accesses and updates of array indexes are done normally, it's seanhalle@33: * only when add a new element into array that use the extra info. seanhalle@33: * An add can cause the pointer to the normal array to change.. so must seanhalle@33: * be protected to single VP at a time. seanhalle@33: * seanhalle@33: *Only need to use this Fn when need a new index, higher than any previous seanhalle@33: */ seanhalle@33: int32 seanhalle@33: addToDynArray2( void *value, void **array ) seanhalle@33: { int32 numInArray, sizeOfArray; seanhalle@33: PrivDynArrayInfo *info = giveInfoFor(array); //go backward to prolog seanhalle@33: seanhalle@33: numInArray = info->numInArray; seanhalle@33: sizeOfArray = info->sizeOfArray; seanhalle@33: seanhalle@33: if( numInArray >= sizeOfArray ) seanhalle@33: { seanhalle@33: array = increaseSizeOfDynArrayTo2( array, sizeOfArray * 2 ); seanhalle@33: info = giveInfoFor( array ); seanhalle@33: } seanhalle@33: seanhalle@33: array[ numInArray ] = value; seanhalle@33: info->numInArray++; seanhalle@33: seanhalle@33: return numInArray; //index of last elem is one less than num in array seanhalle@33: } seanhalle@33: seanhalle@33: seanhalle@33: /*Sets num in array to exactly value give seanhalle@33: *Use this when know how many things going to add in -- then can do this seanhalle@33: * once and use as normal array afterwards. If later add another chunk, seanhalle@33: * do this again. Note, this makes new size be just big enough to hold seanhalle@33: * highest index, so will do a linear number of copies if use only this. seanhalle@33: *To cut down on number of copies, can use the increaseSizeTo Fn to seanhalle@33: * exponentially increase size.. seanhalle@33: */ seanhalle@33: void seanhalle@33: makeNumInArrayBe2( void **array, int32 numInArray ) seanhalle@33: { PrivDynArrayInfo *info = giveInfoFor( array ); seanhalle@33: seanhalle@33: if( info->sizeOfArray <= numInArray ) seanhalle@33: { seanhalle@33: array = increaseSizeOfDynArrayTo2( array, numInArray ); seanhalle@33: info = giveInfoFor( array ); seanhalle@33: } seanhalle@33: info->numInArray = numInArray; //num is highest index plus 1 seanhalle@33: } seanhalle@33: seanhalle@33: /*Allows highest index to remain higher than index give*/ seanhalle@33: void seanhalle@33: makeHighestDynArrayIndexBeAtLeast2( void **array, int32 index) seanhalle@33: { PrivDynArrayInfo *info = giveInfoFor( array ); seanhalle@33: seanhalle@33: if( index < info->numInArray ) return; //num added diff than size seanhalle@33: else makeNumInArrayBe2( array, index ); seanhalle@33: } seanhalle@33: seanhalle@33: seanhalle@33: /*Only use this if certain new size is bigger than current size seanhalle@33: */ seanhalle@33: void ** seanhalle@33: increaseSizeOfDynArrayTo2( void **oldArray, int32 newSize ) seanhalle@33: { int32 oldsizeOfArray, i, numBytesToCopy; seanhalle@33: void **newArray; seanhalle@33: PrivDynArrayInfo *oldInfo = giveInfoFor( oldArray ); seanhalle@33: PrivDynArrayInfo *newInfo; seanhalle@33: seanhalle@33: oldsizeOfArray = oldInfo->sizeOfArray; seanhalle@33: if( newSize <= oldsizeOfArray ) return; seanhalle@33: seanhalle@33: newInfo = PR_int__malloc( newSize * oldInfo->sizeOfElem + sizeof(PrivDynArrayInfo) ); seanhalle@33: newArray = &(newInfo[1]); seanhalle@33: seanhalle@33: numBytesToCopy = oldInfo->numInArray * oldInfo->sizeOfElem + sizeof(PrivDynArrayInfo); seanhalle@33: memcpy( newInfo, oldInfo, numBytesToCopy ); //copies info + array contents seanhalle@33: seanhalle@33: *(newInfo->addrOfPtrToArray) = newArray; //change contents of array var seanhalle@33: newInfo->sizeOfArray = newSize; seanhalle@33: seanhalle@33: PR_int__free( oldInfo ); seanhalle@33: seanhalle@33: return newArray; seanhalle@33: } seanhalle@33: seanhalle@33: seanhalle@33: /* Frees the array, plus the info seanhalle@33: */ seanhalle@33: void seanhalle@33: freeDynArrayDeep2( void *array, FreeFnPtr freeFnPtr ) seanhalle@33: { PrivDynArrayInfo *info = giveInfoFor( array ); seanhalle@33: seanhalle@33: forAllInDynArrayDo2( array, freeFnPtr ); seanhalle@33: PR_int__free( info ); seanhalle@33: } seanhalle@33: seanhalle@33: /* Only frees the info seanhalle@33: */ seanhalle@33: void seanhalle@33: freeDynArrayFlat2( void *array ) seanhalle@33: { PrivDynArrayInfo *info = giveInfoFor( array ); seanhalle@33: seanhalle@33: PR_int__free( info ); seanhalle@33: } seanhalle@33: seanhalle@33: seanhalle@33: /*The function has a fixed prototype: takes a void * returns void seanhalle@33: * So, the function has to internally cast void * to whatever data struc.. seanhalle@33: */ seanhalle@33: void seanhalle@33: forAllInDynArrayDo2( void *array, DynArrayFnPtr fnPtr ) seanhalle@33: { PrivDynArrayInfo *info = giveInfoFor( array ); seanhalle@33: int32 idx, sizeOfElem; seanhalle@33: void *addrOfElem; seanhalle@33: seanhalle@33: sizeOfElem = info->sizeOfElem; seanhalle@33: for( idx = 0; idx < info->numInArray; idx++ ) seanhalle@33: { addrOfElem = ((int8 *)array) + idx * sizeOfElem; seanhalle@33: (*fnPtr)( addrOfElem ); seanhalle@33: } seanhalle@33: } seanhalle@33: