Mercurial > cgi-bin > hgwebdir.cgi > VMS > C_Libraries > DynArray
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/DynArray2.c Fri Jul 19 12:27:43 2013 -0700 1.3 @@ -0,0 +1,158 @@ 1.4 +/* 1.5 + * Copyright 2010 OpenSourceCodeStewardshipFoundation 1.6 + * 1.7 + * Licensed under BSD 1.8 + */ 1.9 + 1.10 + 1.11 + 1.12 +#include <stdio.h> 1.13 +#include <malloc.h> 1.14 + 1.15 +#include "DynArray.h" 1.16 + 1.17 +//== declarations 1.18 +#define giveInfoFor( array ) &(((PrivDynArrayInfo*)array)[-1]) 1.19 +//== 1.20 + 1.21 +/*This updates the contents of the array variable, by side-effect. There can 1.22 + * only ever be one variable that holds a pointer to the dyn array, and all 1.23 + * accesses must use that variable. An add can cause the contents of that 1.24 + * variable to change! (Meaning the position of the array has moved) 1.25 + */ 1.26 +void * 1.27 +makePrivDynArray2( void ***addrOfArrayVar, int32 numElemsToAllocate, int32 sizeOfElem ) 1.28 + { PrivDynArrayInfo *info; 1.29 + int32 bytesInArray = numElemsToAllocate * sizeOfElem; 1.30 + 1.31 + info = PR_int__malloc( sizeof(PrivDynArrayInfo) + bytesInArray ); 1.32 + info->addrOfPtrToArray = addrOfArrayVar; 1.33 + info->sizeOfArray = numElemsToAllocate; 1.34 + info->sizeOfElem = sizeOfElem; 1.35 + info->numInArray = 0; 1.36 + return &(info[1]); //skip over prolog -- info is prolog 1.37 + } 1.38 + 1.39 + 1.40 +/*A dynamic array is same as any other array, but add a DynArrayInfo next 1.41 + * to it. Accesses and updates of array indexes are done normally, it's 1.42 + * only when add a new element into array that use the extra info. 1.43 + * An add can cause the pointer to the normal array to change.. so must 1.44 + * be protected to single VP at a time. 1.45 + * 1.46 + *Only need to use this Fn when need a new index, higher than any previous 1.47 + */ 1.48 +int32 1.49 +addToDynArray2( void *value, void **array ) 1.50 + { int32 numInArray, sizeOfArray; 1.51 + PrivDynArrayInfo *info = giveInfoFor(array); //go backward to prolog 1.52 + 1.53 + numInArray = info->numInArray; 1.54 + sizeOfArray = info->sizeOfArray; 1.55 + 1.56 + if( numInArray >= sizeOfArray ) 1.57 + { 1.58 + array = increaseSizeOfDynArrayTo2( array, sizeOfArray * 2 ); 1.59 + info = giveInfoFor( array ); 1.60 + } 1.61 + 1.62 + array[ numInArray ] = value; 1.63 + info->numInArray++; 1.64 + 1.65 + return numInArray; //index of last elem is one less than num in array 1.66 + } 1.67 + 1.68 + 1.69 +/*Sets num in array to exactly value give 1.70 + *Use this when know how many things going to add in -- then can do this 1.71 + * once and use as normal array afterwards. If later add another chunk, 1.72 + * do this again. Note, this makes new size be just big enough to hold 1.73 + * highest index, so will do a linear number of copies if use only this. 1.74 + *To cut down on number of copies, can use the increaseSizeTo Fn to 1.75 + * exponentially increase size.. 1.76 + */ 1.77 +void 1.78 +makeNumInArrayBe2( void **array, int32 numInArray ) 1.79 + { PrivDynArrayInfo *info = giveInfoFor( array ); 1.80 + 1.81 + if( info->sizeOfArray <= numInArray ) 1.82 + { 1.83 + array = increaseSizeOfDynArrayTo2( array, numInArray ); 1.84 + info = giveInfoFor( array ); 1.85 + } 1.86 + info->numInArray = numInArray; //num is highest index plus 1 1.87 + } 1.88 + 1.89 +/*Allows highest index to remain higher than index give*/ 1.90 +void 1.91 +makeHighestDynArrayIndexBeAtLeast2( void **array, int32 index) 1.92 + { PrivDynArrayInfo *info = giveInfoFor( array ); 1.93 + 1.94 + if( index < info->numInArray ) return; //num added diff than size 1.95 + else makeNumInArrayBe2( array, index ); 1.96 + } 1.97 + 1.98 + 1.99 +/*Only use this if certain new size is bigger than current size 1.100 + */ 1.101 +void ** 1.102 +increaseSizeOfDynArrayTo2( void **oldArray, int32 newSize ) 1.103 + { int32 oldsizeOfArray, i, numBytesToCopy; 1.104 + void **newArray; 1.105 + PrivDynArrayInfo *oldInfo = giveInfoFor( oldArray ); 1.106 + PrivDynArrayInfo *newInfo; 1.107 + 1.108 + oldsizeOfArray = oldInfo->sizeOfArray; 1.109 + if( newSize <= oldsizeOfArray ) return; 1.110 + 1.111 + newInfo = PR_int__malloc( newSize * oldInfo->sizeOfElem + sizeof(PrivDynArrayInfo) ); 1.112 + newArray = &(newInfo[1]); 1.113 + 1.114 + numBytesToCopy = oldInfo->numInArray * oldInfo->sizeOfElem + sizeof(PrivDynArrayInfo); 1.115 + memcpy( newInfo, oldInfo, numBytesToCopy ); //copies info + array contents 1.116 + 1.117 + *(newInfo->addrOfPtrToArray) = newArray; //change contents of array var 1.118 + newInfo->sizeOfArray = newSize; 1.119 + 1.120 + PR_int__free( oldInfo ); 1.121 + 1.122 + return newArray; 1.123 + } 1.124 + 1.125 + 1.126 +/* Frees the array, plus the info 1.127 + */ 1.128 +void 1.129 +freeDynArrayDeep2( void *array, FreeFnPtr freeFnPtr ) 1.130 + { PrivDynArrayInfo *info = giveInfoFor( array ); 1.131 + 1.132 + forAllInDynArrayDo2( array, freeFnPtr ); 1.133 + PR_int__free( info ); 1.134 + } 1.135 + 1.136 +/* Only frees the info 1.137 + */ 1.138 +void 1.139 +freeDynArrayFlat2( void *array ) 1.140 + { PrivDynArrayInfo *info = giveInfoFor( array ); 1.141 + 1.142 + PR_int__free( info ); 1.143 + } 1.144 + 1.145 + 1.146 +/*The function has a fixed prototype: takes a void * returns void 1.147 + * So, the function has to internally cast void * to whatever data struc.. 1.148 + */ 1.149 +void 1.150 +forAllInDynArrayDo2( void *array, DynArrayFnPtr fnPtr ) 1.151 + { PrivDynArrayInfo *info = giveInfoFor( array ); 1.152 + int32 idx, sizeOfElem; 1.153 + void *addrOfElem; 1.154 + 1.155 + sizeOfElem = info->sizeOfElem; 1.156 + for( idx = 0; idx < info->numInArray; idx++ ) 1.157 + { addrOfElem = ((int8 *)array) + idx * sizeOfElem; 1.158 + (*fnPtr)( addrOfElem ); 1.159 + } 1.160 + } 1.161 +
