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