annotate DynArray2.c @ 33:3ed337b6a04f

creating version of dyn array that keeps info in prolog instead of 2nd var
author Sean Halle <seanhalle@yahoo.com>
date Fri, 19 Jul 2013 12:27:43 -0700
parents
children
rev   line source
seanhalle@33 1 /*
seanhalle@33 2 * Copyright 2010 OpenSourceCodeStewardshipFoundation
seanhalle@33 3 *
seanhalle@33 4 * Licensed under BSD
seanhalle@33 5 */
seanhalle@33 6
seanhalle@33 7
seanhalle@33 8
seanhalle@33 9 #include <stdio.h>
seanhalle@33 10 #include <malloc.h>
seanhalle@33 11
seanhalle@33 12 #include "DynArray.h"
seanhalle@33 13
seanhalle@33 14 //== declarations
seanhalle@33 15 #define giveInfoFor( array ) &(((PrivDynArrayInfo*)array)[-1])
seanhalle@33 16 //==
seanhalle@33 17
seanhalle@33 18 /*This updates the contents of the array variable, by side-effect. There can
seanhalle@33 19 * only ever be one variable that holds a pointer to the dyn array, and all
seanhalle@33 20 * accesses must use that variable. An add can cause the contents of that
seanhalle@33 21 * variable to change! (Meaning the position of the array has moved)
seanhalle@33 22 */
seanhalle@33 23 void *
seanhalle@33 24 makePrivDynArray2( void ***addrOfArrayVar, int32 numElemsToAllocate, int32 sizeOfElem )
seanhalle@33 25 { PrivDynArrayInfo *info;
seanhalle@33 26 int32 bytesInArray = numElemsToAllocate * sizeOfElem;
seanhalle@33 27
seanhalle@33 28 info = PR_int__malloc( sizeof(PrivDynArrayInfo) + bytesInArray );
seanhalle@33 29 info->addrOfPtrToArray = addrOfArrayVar;
seanhalle@33 30 info->sizeOfArray = numElemsToAllocate;
seanhalle@33 31 info->sizeOfElem = sizeOfElem;
seanhalle@33 32 info->numInArray = 0;
seanhalle@33 33 return &(info[1]); //skip over prolog -- info is prolog
seanhalle@33 34 }
seanhalle@33 35
seanhalle@33 36
seanhalle@33 37 /*A dynamic array is same as any other array, but add a DynArrayInfo next
seanhalle@33 38 * to it. Accesses and updates of array indexes are done normally, it's
seanhalle@33 39 * only when add a new element into array that use the extra info.
seanhalle@33 40 * An add can cause the pointer to the normal array to change.. so must
seanhalle@33 41 * be protected to single VP at a time.
seanhalle@33 42 *
seanhalle@33 43 *Only need to use this Fn when need a new index, higher than any previous
seanhalle@33 44 */
seanhalle@33 45 int32
seanhalle@33 46 addToDynArray2( void *value, void **array )
seanhalle@33 47 { int32 numInArray, sizeOfArray;
seanhalle@33 48 PrivDynArrayInfo *info = giveInfoFor(array); //go backward to prolog
seanhalle@33 49
seanhalle@33 50 numInArray = info->numInArray;
seanhalle@33 51 sizeOfArray = info->sizeOfArray;
seanhalle@33 52
seanhalle@33 53 if( numInArray >= sizeOfArray )
seanhalle@33 54 {
seanhalle@33 55 array = increaseSizeOfDynArrayTo2( array, sizeOfArray * 2 );
seanhalle@33 56 info = giveInfoFor( array );
seanhalle@33 57 }
seanhalle@33 58
seanhalle@33 59 array[ numInArray ] = value;
seanhalle@33 60 info->numInArray++;
seanhalle@33 61
seanhalle@33 62 return numInArray; //index of last elem is one less than num in array
seanhalle@33 63 }
seanhalle@33 64
seanhalle@33 65
seanhalle@33 66 /*Sets num in array to exactly value give
seanhalle@33 67 *Use this when know how many things going to add in -- then can do this
seanhalle@33 68 * once and use as normal array afterwards. If later add another chunk,
seanhalle@33 69 * do this again. Note, this makes new size be just big enough to hold
seanhalle@33 70 * highest index, so will do a linear number of copies if use only this.
seanhalle@33 71 *To cut down on number of copies, can use the increaseSizeTo Fn to
seanhalle@33 72 * exponentially increase size..
seanhalle@33 73 */
seanhalle@33 74 void
seanhalle@33 75 makeNumInArrayBe2( void **array, int32 numInArray )
seanhalle@33 76 { PrivDynArrayInfo *info = giveInfoFor( array );
seanhalle@33 77
seanhalle@33 78 if( info->sizeOfArray <= numInArray )
seanhalle@33 79 {
seanhalle@33 80 array = increaseSizeOfDynArrayTo2( array, numInArray );
seanhalle@33 81 info = giveInfoFor( array );
seanhalle@33 82 }
seanhalle@33 83 info->numInArray = numInArray; //num is highest index plus 1
seanhalle@33 84 }
seanhalle@33 85
seanhalle@33 86 /*Allows highest index to remain higher than index give*/
seanhalle@33 87 void
seanhalle@33 88 makeHighestDynArrayIndexBeAtLeast2( void **array, int32 index)
seanhalle@33 89 { PrivDynArrayInfo *info = giveInfoFor( array );
seanhalle@33 90
seanhalle@33 91 if( index < info->numInArray ) return; //num added diff than size
seanhalle@33 92 else makeNumInArrayBe2( array, index );
seanhalle@33 93 }
seanhalle@33 94
seanhalle@33 95
seanhalle@33 96 /*Only use this if certain new size is bigger than current size
seanhalle@33 97 */
seanhalle@33 98 void **
seanhalle@33 99 increaseSizeOfDynArrayTo2( void **oldArray, int32 newSize )
seanhalle@33 100 { int32 oldsizeOfArray, i, numBytesToCopy;
seanhalle@33 101 void **newArray;
seanhalle@33 102 PrivDynArrayInfo *oldInfo = giveInfoFor( oldArray );
seanhalle@33 103 PrivDynArrayInfo *newInfo;
seanhalle@33 104
seanhalle@33 105 oldsizeOfArray = oldInfo->sizeOfArray;
seanhalle@33 106 if( newSize <= oldsizeOfArray ) return;
seanhalle@33 107
seanhalle@33 108 newInfo = PR_int__malloc( newSize * oldInfo->sizeOfElem + sizeof(PrivDynArrayInfo) );
seanhalle@33 109 newArray = &(newInfo[1]);
seanhalle@33 110
seanhalle@33 111 numBytesToCopy = oldInfo->numInArray * oldInfo->sizeOfElem + sizeof(PrivDynArrayInfo);
seanhalle@33 112 memcpy( newInfo, oldInfo, numBytesToCopy ); //copies info + array contents
seanhalle@33 113
seanhalle@33 114 *(newInfo->addrOfPtrToArray) = newArray; //change contents of array var
seanhalle@33 115 newInfo->sizeOfArray = newSize;
seanhalle@33 116
seanhalle@33 117 PR_int__free( oldInfo );
seanhalle@33 118
seanhalle@33 119 return newArray;
seanhalle@33 120 }
seanhalle@33 121
seanhalle@33 122
seanhalle@33 123 /* Frees the array, plus the info
seanhalle@33 124 */
seanhalle@33 125 void
seanhalle@33 126 freeDynArrayDeep2( void *array, FreeFnPtr freeFnPtr )
seanhalle@33 127 { PrivDynArrayInfo *info = giveInfoFor( array );
seanhalle@33 128
seanhalle@33 129 forAllInDynArrayDo2( array, freeFnPtr );
seanhalle@33 130 PR_int__free( info );
seanhalle@33 131 }
seanhalle@33 132
seanhalle@33 133 /* Only frees the info
seanhalle@33 134 */
seanhalle@33 135 void
seanhalle@33 136 freeDynArrayFlat2( void *array )
seanhalle@33 137 { PrivDynArrayInfo *info = giveInfoFor( array );
seanhalle@33 138
seanhalle@33 139 PR_int__free( info );
seanhalle@33 140 }
seanhalle@33 141
seanhalle@33 142
seanhalle@33 143 /*The function has a fixed prototype: takes a void * returns void
seanhalle@33 144 * So, the function has to internally cast void * to whatever data struc..
seanhalle@33 145 */
seanhalle@33 146 void
seanhalle@33 147 forAllInDynArrayDo2( void *array, DynArrayFnPtr fnPtr )
seanhalle@33 148 { PrivDynArrayInfo *info = giveInfoFor( array );
seanhalle@33 149 int32 idx, sizeOfElem;
seanhalle@33 150 void *addrOfElem;
seanhalle@33 151
seanhalle@33 152 sizeOfElem = info->sizeOfElem;
seanhalle@33 153 for( idx = 0; idx < info->numInArray; idx++ )
seanhalle@33 154 { addrOfElem = ((int8 *)array) + idx * sizeOfElem;
seanhalle@33 155 (*fnPtr)( addrOfElem );
seanhalle@33 156 }
seanhalle@33 157 }
seanhalle@33 158