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