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