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: seanhalle@33: #include "DynArray.h" seanhalle@33: seanhalle@33: //== declarations seanhalle@33: void seanhalle@33: increaseSizeOfDynArrayTo_Ext( PtrToPrivDynArray *info, int32 newSize ); seanhalle@33: //== seanhalle@33: seanhalle@33: PtrToPrivDynArray * seanhalle@33: makePrivDynArrayInfoFrom( void ***addrOfPtrToArray, int32 sizeOfArray ) seanhalle@33: { PtrToPrivDynArray *info; seanhalle@33: seanhalle@33: info = PR_int__malloc( sizeof(PtrToPrivDynArray) ); seanhalle@33: seanhalle@33: info->addrOfPtrToArray = addrOfPtrToArray; seanhalle@33: info->sizeOfArray = sizeOfArray; seanhalle@33: info->numInArray = 0; seanhalle@33: return info; seanhalle@33: } seanhalle@33: seanhalle@33: PtrToPrivDynArray * seanhalle@33: makePrivDynArrayOfSize( void ***addrOfPtrToArray, int32 sizeOfArray ) seanhalle@33: { PtrToPrivDynArray *info; seanhalle@33: seanhalle@33: info = PR_int__malloc( sizeof(PtrToPrivDynArray) ); seanhalle@33: seanhalle@33: info->addrOfPtrToArray = addrOfPtrToArray; seanhalle@33: seanhalle@33: *(addrOfPtrToArray) = PR_int__malloc( sizeOfArray * sizeof(void *) ); seanhalle@33: info->sizeOfArray = sizeOfArray; seanhalle@33: info->numInArray = 0; seanhalle@33: return info; seanhalle@33: } seanhalle@33: seanhalle@33: PtrToPrivDynArray * seanhalle@33: makePrivDynArrayOfSize_Ext( void ***addrOfPtrToArray, int32 sizeOfArray ) seanhalle@33: { PtrToPrivDynArray *info; seanhalle@33: seanhalle@33: info = malloc( sizeof(PtrToPrivDynArray) ); seanhalle@33: seanhalle@33: info->addrOfPtrToArray = addrOfPtrToArray; seanhalle@33: seanhalle@33: *(addrOfPtrToArray) = malloc( sizeOfArray * sizeof(void *) ); seanhalle@33: info->sizeOfArray = sizeOfArray; seanhalle@33: info->numInArray = 0; 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: addToDynArray( void *value, PtrToPrivDynArray *info ) seanhalle@33: { int32 numInArray, sizeOfArray; seanhalle@33: void **array; seanhalle@33: seanhalle@33: numInArray = info->numInArray; seanhalle@33: sizeOfArray = info->sizeOfArray; seanhalle@33: seanhalle@33: if( numInArray >= sizeOfArray ) seanhalle@33: { seanhalle@33: increaseSizeOfDynArrayTo( info, sizeOfArray * 2 ); seanhalle@33: } seanhalle@33: seanhalle@33: array = *(info->addrOfPtrToArray); seanhalle@33: array[ numInArray ] = value; seanhalle@33: info->numInArray++; seanhalle@33: seanhalle@33: return numInArray; //pre-incr value is the index put value into seanhalle@33: } seanhalle@33: int32 seanhalle@33: addToDynArray_Ext( void *value, PtrToPrivDynArray *ptrToArray ) seanhalle@33: { int32 numInArray, sizeOfArray; seanhalle@33: void **array; seanhalle@33: seanhalle@33: numInArray = ptrToArray->numInArray; seanhalle@33: sizeOfArray = ptrToArray->sizeOfArray; seanhalle@33: seanhalle@33: if( numInArray >= sizeOfArray ) seanhalle@33: { seanhalle@33: increaseSizeOfDynArrayTo_Ext( ptrToArray, sizeOfArray * 2 ); seanhalle@33: } seanhalle@33: seanhalle@33: array = *(ptrToArray->addrOfPtrToArray); seanhalle@33: array[ numInArray ] = value; seanhalle@33: ptrToArray->numInArray++; seanhalle@33: seanhalle@33: return numInArray; //pre-incr value is the index put value into seanhalle@33: } seanhalle@33: seanhalle@33: 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: makeHighestDynArrayIndexBe( PtrToPrivDynArray *info, int32 highestIndex ) seanhalle@33: { seanhalle@33: if( info->sizeOfArray <= highestIndex ) seanhalle@33: { seanhalle@33: increaseSizeOfDynArrayTo( info, highestIndex + 1 ); seanhalle@33: } seanhalle@33: info->numInArray = highestIndex + 1; seanhalle@33: } seanhalle@33: seanhalle@33: void seanhalle@33: makeHighestDynArrayIndexBeAtLeast(PtrToPrivDynArray *info, int32 index) seanhalle@33: { seanhalle@33: if( index < info->numInArray ) return; seanhalle@33: else makeHighestDynArrayIndexBe( info, 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: increaseSizeOfDynArrayTo( PtrToPrivDynArray *info, int32 newSize ) seanhalle@33: { int32 oldSizeOfArray, i; seanhalle@33: void **newArray, **oldArray; seanhalle@33: seanhalle@33: oldSizeOfArray = info->sizeOfArray; seanhalle@33: if( newSize <= oldSizeOfArray ) return; seanhalle@33: seanhalle@33: oldArray = *(info->addrOfPtrToArray); seanhalle@33: newArray = PR_int__malloc( newSize * sizeof(void *) ); seanhalle@33: seanhalle@33: for( i = 0; i < oldSizeOfArray; i++ ) seanhalle@33: { seanhalle@33: newArray[i] = oldArray[i]; seanhalle@33: } seanhalle@33: *(info->addrOfPtrToArray) = newArray; //change location of array-ptr seanhalle@33: info->sizeOfArray = newSize; seanhalle@33: seanhalle@33: PR_int__free( oldArray ); seanhalle@33: } seanhalle@33: seanhalle@33: /*Can't mix PR_int__malloc locations with external malloc locations -- so use seanhalle@33: * this version inside PR, which will perform normal malloc in the core seanhalle@33: * loop -- hopefully avoiding the annoying system-stack bugs.. seanhalle@33: */ seanhalle@33: void seanhalle@33: increaseSizeOfDynArrayTo_Ext( PtrToPrivDynArray *info, int32 newSize ) seanhalle@33: { int32 oldSizeOfArray, i; seanhalle@33: void **newArray, **oldArray; seanhalle@33: seanhalle@33: oldSizeOfArray = info->sizeOfArray; seanhalle@33: if( newSize <= oldSizeOfArray ) return; seanhalle@33: seanhalle@33: oldArray = *(info->addrOfPtrToArray); seanhalle@33: newArray = malloc( newSize * sizeof(void *) ); seanhalle@33: seanhalle@33: for( i = 0; i < oldSizeOfArray; i++ ) seanhalle@33: { seanhalle@33: newArray[i] = oldArray[i]; seanhalle@33: } seanhalle@33: *(info->addrOfPtrToArray) = newArray; //change location of array-ptr seanhalle@33: info->sizeOfArray = newSize; seanhalle@33: seanhalle@33: free( oldArray ); seanhalle@33: } seanhalle@33: seanhalle@33: seanhalle@33: /* Frees the array, plus the info seanhalle@33: */ seanhalle@33: void seanhalle@33: freeDynArrayDeep( PtrToPrivDynArray *info, FreeFnPtr freeFnPtr ) seanhalle@33: { seanhalle@33: forAllInDynArrayDo( info, freeFnPtr ); seanhalle@33: PR_int__free( *(info->addrOfPtrToArray) ); seanhalle@33: PR_int__free( info ); seanhalle@33: } seanhalle@33: seanhalle@33: /* Only frees the info seanhalle@33: */ seanhalle@33: void seanhalle@33: freeDynArrayFlat( PtrToPrivDynArray *info ) 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: forAllInDynArrayDo( PtrToPrivDynArray *info, DynArrayFnPtr fnPtr ) seanhalle@33: { int32 idx; seanhalle@33: void **array; seanhalle@33: seanhalle@33: array = *(info->addrOfPtrToArray); seanhalle@33: for( idx = 0; idx < info->numInArray; idx++ ) seanhalle@33: { seanhalle@33: (*fnPtr)(array[idx]); seanhalle@33: } seanhalle@33: } seanhalle@33: