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