Me@15: /* Me@15: * Copyright 2010 OpenSourceCodeStewardshipFoundation Me@15: * Me@15: * Licensed under BSD Me@15: */ Me@15: Me@15: Me@15: Me@15: #include Me@15: Me@15: #include "DynArray.h" Me@15: Me@15: //== declarations Me@15: void Me@15: increaseSizeOfDynArrayTo_Ext( PrivDynArrayInfo *info, int32 newSize ); Me@15: //== Me@15: Me@15: PrivDynArrayInfo * Me@15: makePrivDynArrayInfoFrom( void ***addrOfPtrToArray, int32 sizeOfArray ) Me@15: { PrivDynArrayInfo *info; Me@15: Me@15: info = VMS__malloc( sizeof(PrivDynArrayInfo) ); Me@15: Me@15: info->addrOfPtrToArray = addrOfPtrToArray; Me@15: info->sizeOfArray = sizeOfArray; Me@15: info->numInArray = 0; Me@15: return info; Me@15: } Me@15: Me@15: PrivDynArrayInfo * Me@15: makePrivDynArrayOfSize( void ***addrOfPtrToArray, int32 sizeOfArray ) Me@15: { PrivDynArrayInfo *info; Me@15: Me@15: info = VMS__malloc( sizeof(PrivDynArrayInfo) ); Me@15: Me@15: info->addrOfPtrToArray = addrOfPtrToArray; Me@15: Me@15: *(addrOfPtrToArray) = VMS__malloc( sizeOfArray * sizeof(void *) ); Me@15: info->sizeOfArray = sizeOfArray; Me@15: info->numInArray = 0; Me@15: return info; Me@15: } Me@15: Me@15: PrivDynArrayInfo * Me@15: makePrivDynArrayOfSize_Ext( void ***addrOfPtrToArray, int32 sizeOfArray ) Me@15: { PrivDynArrayInfo *info; Me@15: Me@15: info = malloc( sizeof(PrivDynArrayInfo) ); Me@15: Me@15: info->addrOfPtrToArray = addrOfPtrToArray; Me@15: Me@15: *(addrOfPtrToArray) = malloc( sizeOfArray * sizeof(void *) ); Me@15: info->sizeOfArray = sizeOfArray; Me@15: info->numInArray = 0; Me@15: } Me@15: Me@15: Me@15: /*A dynamic array is same as any other array, but add a DynArrayInfo next Me@15: * to it. Accesses and updates of array indexes are done normally, it's Me@15: * only when add a new element into array that use the extra info. Me@15: * An add can cause the pointer to the normal array to change.. so must Me@15: * be protected to single VP at a time. Me@15: * Me@15: *Only need to use this Fn when need a new index, higher than any previous Me@15: */ Me@15: int32 Me@15: addToDynArray( void *value, PrivDynArrayInfo *info ) Me@15: { int32 numInArray, sizeOfArray; Me@15: void **array; Me@15: Me@15: numInArray = info->numInArray; Me@15: sizeOfArray = info->sizeOfArray; Me@15: Me@15: if( numInArray >= sizeOfArray ) Me@15: { Me@15: increaseSizeOfDynArrayTo( info, sizeOfArray * 2 ); Me@15: } Me@15: Me@15: array = *(info->addrOfPtrToArray); Me@15: array[ numInArray ] = value; Me@15: info->numInArray++; Me@15: Me@15: return numInArray; //pre-incr value is the index put value into Me@15: } Me@15: int32 Me@15: addToDynArray_Ext( void *value, PrivDynArrayInfo *info ) Me@15: { int32 numInArray, sizeOfArray; Me@15: void **array; Me@15: Me@15: numInArray = info->numInArray; Me@15: sizeOfArray = info->sizeOfArray; Me@15: Me@15: if( numInArray >= sizeOfArray ) Me@15: { Me@15: increaseSizeOfDynArrayTo_Ext( info, sizeOfArray * 2 ); Me@15: } Me@15: Me@15: array = *(info->addrOfPtrToArray); Me@15: array[ numInArray ] = value; Me@15: info->numInArray++; Me@15: Me@15: return numInArray; //pre-incr value is the index put value into Me@15: } Me@15: Me@15: Me@15: /*Use this when know how many things going to add in -- then can do this Me@15: * once and use as normal array afterwards. If later add another chunk, Me@15: * do this again. Note, this makes new size be just big enough to hold Me@15: * highest index, so will do a linear number of copies if use only this. Me@15: *To cut down on number of copies, can use the increaseSizeTo Fn to Me@15: * exponentially increase size.. Me@15: */ Me@15: void Me@15: makeHighestDynArrayIndexBe( PrivDynArrayInfo *info, int32 highestIndex ) Me@15: { Me@15: if( info->sizeOfArray <= highestIndex ) Me@15: { Me@15: increaseSizeOfDynArrayTo( info, highestIndex + 1 ); Me@15: } Me@15: info->numInArray = highestIndex + 1; Me@15: } Me@15: Me@15: void Me@15: makeHighestDynArrayIndexBeAtLeast(PrivDynArrayInfo *info, int32 index) Me@15: { Me@15: if( index < info->numInArray ) return; Me@15: else makeHighestDynArrayIndexBe( info, index ); Me@15: } Me@15: Me@15: Me@15: /*Only use this if certain new size is bigger than current size Me@15: */ Me@15: void Me@15: increaseSizeOfDynArrayTo( PrivDynArrayInfo *info, int32 newSize ) Me@15: { int32 oldSizeOfArray, i; Me@15: void **newArray, **oldArray; Me@15: Me@15: oldSizeOfArray = info->sizeOfArray; Me@15: if( newSize <= oldSizeOfArray ) return; Me@15: Me@15: oldArray = *(info->addrOfPtrToArray); Me@15: newArray = VMS__malloc( newSize * sizeof(void *) ); Me@15: Me@15: for( i = 0; i < oldSizeOfArray; i++ ) Me@15: { Me@15: newArray[i] = oldArray[i]; Me@15: } Me@15: *(info->addrOfPtrToArray) = newArray; //change location of array-ptr Me@15: info->sizeOfArray = newSize; Me@15: Me@15: VMS__free( oldArray ); Me@15: } Me@15: Me@15: /*Can't mix VMS__malloc locations with external malloc locations -- so use Me@15: * this version inside VMS, which will perform normal malloc in the core Me@15: * loop -- hopefully avoiding the annoying system-stack bugs.. Me@15: */ Me@15: void Me@15: increaseSizeOfDynArrayTo_Ext( PrivDynArrayInfo *info, int32 newSize ) Me@15: { int32 oldSizeOfArray, i; Me@15: void **newArray, **oldArray; Me@15: Me@15: oldSizeOfArray = info->sizeOfArray; Me@15: if( newSize <= oldSizeOfArray ) return; Me@15: Me@15: oldArray = *(info->addrOfPtrToArray); Me@15: newArray = malloc( newSize * sizeof(void *) ); Me@15: Me@15: for( i = 0; i < oldSizeOfArray; i++ ) Me@15: { Me@15: newArray[i] = oldArray[i]; Me@15: } Me@15: *(info->addrOfPtrToArray) = newArray; //change location of array-ptr Me@15: info->sizeOfArray = newSize; Me@15: Me@15: free( oldArray ); Me@15: } Me@15: Me@15: Me@15: /* Frees the array, plus the info Me@15: */ Me@15: void Me@15: freeDynArrayDeep( PrivDynArrayInfo *info, FreeFnPtr freeFnPtr ) Me@15: { Me@15: forAllInDynArrayDo( info, freeFnPtr ); Me@15: VMS__free( *(info->addrOfPtrToArray) ); Me@15: VMS__free( info ); Me@15: } Me@15: Me@15: /* Only frees the info Me@15: */ Me@15: void Me@15: freeDynArrayFlat( PrivDynArrayInfo *info ) Me@15: { Me@15: VMS__free( info ); Me@15: } Me@15: Me@15: Me@15: /*The function has a fixed prototype: takes a void * returns void Me@15: * So, the function has to internally cast void * to whatever data struc.. Me@15: */ Me@15: void Me@15: forAllInDynArrayDo( PrivDynArrayInfo *info, DynArrayFnPtr fnPtr ) Me@15: { int32 idx; Me@15: void **array; Me@15: Me@15: array = *(info->addrOfPtrToArray); Me@15: for( idx = 0; idx < info->numInArray; idx++ ) Me@15: { Me@15: (*fnPtr)(array[idx]); Me@15: } Me@15: } Me@15: