Mercurial > cgi-bin > hgwebdir.cgi > VMS > C_Libraries > DynArray
changeset 33:3ed337b6a04f Dev_prolog_vers
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 | 958dcb7754ca |
| children | |
| files | DynArray2.c DynArray3.c DynArray3.h __brch__Dev_prolog_vers __brch__Renamed_VMS_to_PR |
| diffstat | 5 files changed, 472 insertions(+), 4 deletions(-) [+] |
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 +
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/DynArray3.c Fri Jul 19 12:27:43 2013 -0700 2.3 @@ -0,0 +1,213 @@ 2.4 +/* 2.5 + * Copyright 2010 OpenSourceCodeStewardshipFoundation 2.6 + * 2.7 + * Licensed under BSD 2.8 + */ 2.9 + 2.10 + 2.11 + 2.12 +#include <stdio.h> 2.13 + 2.14 +#include "DynArray.h" 2.15 + 2.16 +//== declarations 2.17 +void 2.18 +increaseSizeOfDynArrayTo_Ext( PtrToPrivDynArray *info, int32 newSize ); 2.19 +//== 2.20 + 2.21 +PtrToPrivDynArray * 2.22 +makePrivDynArrayInfoFrom( void ***addrOfPtrToArray, int32 sizeOfArray ) 2.23 + { PtrToPrivDynArray *info; 2.24 + 2.25 + info = PR_int__malloc( sizeof(PtrToPrivDynArray) ); 2.26 + 2.27 + info->addrOfPtrToArray = addrOfPtrToArray; 2.28 + info->sizeOfArray = sizeOfArray; 2.29 + info->numInArray = 0; 2.30 + return info; 2.31 + } 2.32 + 2.33 +PtrToPrivDynArray * 2.34 +makePrivDynArrayOfSize( void ***addrOfPtrToArray, int32 sizeOfArray ) 2.35 + { PtrToPrivDynArray *info; 2.36 + 2.37 + info = PR_int__malloc( sizeof(PtrToPrivDynArray) ); 2.38 + 2.39 + info->addrOfPtrToArray = addrOfPtrToArray; 2.40 + 2.41 + *(addrOfPtrToArray) = PR_int__malloc( sizeOfArray * sizeof(void *) ); 2.42 + info->sizeOfArray = sizeOfArray; 2.43 + info->numInArray = 0; 2.44 + return info; 2.45 + } 2.46 + 2.47 +PtrToPrivDynArray * 2.48 +makePrivDynArrayOfSize_Ext( void ***addrOfPtrToArray, int32 sizeOfArray ) 2.49 + { PtrToPrivDynArray *info; 2.50 + 2.51 + info = malloc( sizeof(PtrToPrivDynArray) ); 2.52 + 2.53 + info->addrOfPtrToArray = addrOfPtrToArray; 2.54 + 2.55 + *(addrOfPtrToArray) = malloc( sizeOfArray * sizeof(void *) ); 2.56 + info->sizeOfArray = sizeOfArray; 2.57 + info->numInArray = 0; 2.58 + } 2.59 + 2.60 + 2.61 +/*A dynamic array is same as any other array, but add a DynArrayInfo next 2.62 + * to it. Accesses and updates of array indexes are done normally, it's 2.63 + * only when add a new element into array that use the extra info. 2.64 + * An add can cause the pointer to the normal array to change.. so must 2.65 + * be protected to single VP at a time. 2.66 + * 2.67 + *Only need to use this Fn when need a new index, higher than any previous 2.68 + */ 2.69 +int32 2.70 +addToDynArray( void *value, PtrToPrivDynArray *info ) 2.71 + { int32 numInArray, sizeOfArray; 2.72 + void **array; 2.73 + 2.74 + numInArray = info->numInArray; 2.75 + sizeOfArray = info->sizeOfArray; 2.76 + 2.77 + if( numInArray >= sizeOfArray ) 2.78 + { 2.79 + increaseSizeOfDynArrayTo( info, sizeOfArray * 2 ); 2.80 + } 2.81 + 2.82 + array = *(info->addrOfPtrToArray); 2.83 + array[ numInArray ] = value; 2.84 + info->numInArray++; 2.85 + 2.86 + return numInArray; //pre-incr value is the index put value into 2.87 + } 2.88 +int32 2.89 +addToDynArray_Ext( void *value, PtrToPrivDynArray *ptrToArray ) 2.90 + { int32 numInArray, sizeOfArray; 2.91 + void **array; 2.92 + 2.93 + numInArray = ptrToArray->numInArray; 2.94 + sizeOfArray = ptrToArray->sizeOfArray; 2.95 + 2.96 + if( numInArray >= sizeOfArray ) 2.97 + { 2.98 + increaseSizeOfDynArrayTo_Ext( ptrToArray, sizeOfArray * 2 ); 2.99 + } 2.100 + 2.101 + array = *(ptrToArray->addrOfPtrToArray); 2.102 + array[ numInArray ] = value; 2.103 + ptrToArray->numInArray++; 2.104 + 2.105 + return numInArray; //pre-incr value is the index put value into 2.106 + } 2.107 + 2.108 + 2.109 +/*Use this when know how many things going to add in -- then can do this 2.110 + * once and use as normal array afterwards. If later add another chunk, 2.111 + * do this again. Note, this makes new size be just big enough to hold 2.112 + * highest index, so will do a linear number of copies if use only this. 2.113 + *To cut down on number of copies, can use the increaseSizeTo Fn to 2.114 + * exponentially increase size.. 2.115 + */ 2.116 +void 2.117 +makeHighestDynArrayIndexBe( PtrToPrivDynArray *info, int32 highestIndex ) 2.118 + { 2.119 + if( info->sizeOfArray <= highestIndex ) 2.120 + { 2.121 + increaseSizeOfDynArrayTo( info, highestIndex + 1 ); 2.122 + } 2.123 + info->numInArray = highestIndex + 1; 2.124 + } 2.125 + 2.126 +void 2.127 +makeHighestDynArrayIndexBeAtLeast(PtrToPrivDynArray *info, int32 index) 2.128 + { 2.129 + if( index < info->numInArray ) return; 2.130 + else makeHighestDynArrayIndexBe( info, index ); 2.131 + } 2.132 + 2.133 + 2.134 +/*Only use this if certain new size is bigger than current size 2.135 + */ 2.136 +void 2.137 +increaseSizeOfDynArrayTo( PtrToPrivDynArray *info, int32 newSize ) 2.138 + { int32 oldSizeOfArray, i; 2.139 + void **newArray, **oldArray; 2.140 + 2.141 + oldSizeOfArray = info->sizeOfArray; 2.142 + if( newSize <= oldSizeOfArray ) return; 2.143 + 2.144 + oldArray = *(info->addrOfPtrToArray); 2.145 + newArray = PR_int__malloc( newSize * sizeof(void *) ); 2.146 + 2.147 + for( i = 0; i < oldSizeOfArray; i++ ) 2.148 + { 2.149 + newArray[i] = oldArray[i]; 2.150 + } 2.151 + *(info->addrOfPtrToArray) = newArray; //change location of array-ptr 2.152 + info->sizeOfArray = newSize; 2.153 + 2.154 + PR_int__free( oldArray ); 2.155 + } 2.156 + 2.157 +/*Can't mix PR_int__malloc locations with external malloc locations -- so use 2.158 + * this version inside PR, which will perform normal malloc in the core 2.159 + * loop -- hopefully avoiding the annoying system-stack bugs.. 2.160 + */ 2.161 +void 2.162 +increaseSizeOfDynArrayTo_Ext( PtrToPrivDynArray *info, int32 newSize ) 2.163 + { int32 oldSizeOfArray, i; 2.164 + void **newArray, **oldArray; 2.165 + 2.166 + oldSizeOfArray = info->sizeOfArray; 2.167 + if( newSize <= oldSizeOfArray ) return; 2.168 + 2.169 + oldArray = *(info->addrOfPtrToArray); 2.170 + newArray = malloc( newSize * sizeof(void *) ); 2.171 + 2.172 + for( i = 0; i < oldSizeOfArray; i++ ) 2.173 + { 2.174 + newArray[i] = oldArray[i]; 2.175 + } 2.176 + *(info->addrOfPtrToArray) = newArray; //change location of array-ptr 2.177 + info->sizeOfArray = newSize; 2.178 + 2.179 + free( oldArray ); 2.180 + } 2.181 + 2.182 + 2.183 +/* Frees the array, plus the info 2.184 + */ 2.185 +void 2.186 +freeDynArrayDeep( PtrToPrivDynArray *info, FreeFnPtr freeFnPtr ) 2.187 + { 2.188 + forAllInDynArrayDo( info, freeFnPtr ); 2.189 + PR_int__free( *(info->addrOfPtrToArray) ); 2.190 + PR_int__free( info ); 2.191 + } 2.192 + 2.193 +/* Only frees the info 2.194 + */ 2.195 +void 2.196 +freeDynArrayFlat( PtrToPrivDynArray *info ) 2.197 + { 2.198 + PR_int__free( info ); 2.199 + } 2.200 + 2.201 + 2.202 +/*The function has a fixed prototype: takes a void * returns void 2.203 + * So, the function has to internally cast void * to whatever data struc.. 2.204 + */ 2.205 +void 2.206 +forAllInDynArrayDo( PtrToPrivDynArray *info, DynArrayFnPtr fnPtr ) 2.207 + { int32 idx; 2.208 + void **array; 2.209 + 2.210 + array = *(info->addrOfPtrToArray); 2.211 + for( idx = 0; idx < info->numInArray; idx++ ) 2.212 + { 2.213 + (*fnPtr)(array[idx]); 2.214 + } 2.215 + } 2.216 +
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/DynArray3.h Fri Jul 19 12:27:43 2013 -0700 3.3 @@ -0,0 +1,97 @@ 3.4 +/* 3.5 + * File: Vector.h 3.6 + * Author: Me 3.7 + * 3.8 + * Created on May 14, 2010, 3:08 PM 3.9 + */ 3.10 + 3.11 +#ifndef _DYNARRAY_H 3.12 +#define _DYNARRAY_H 3.13 + 3.14 +#include "PR_impl/PR_primitive_data_types.h" 3.15 +#include "PR_impl/Services_Offered_by_PR/Memory_Handling/vmalloc.h" 3.16 + 3.17 + 3.18 +/*WARNING: Passing a DynArray as a param is dangerous if add to the DynArray 3.19 + * inside the function called! After adding or other operation that might 3.20 + * change the size, must re-read the addr of the chunk of memory that is the 3.21 + * array, via the DynArrayInfo. 3.22 + *Here's why: An array variable is a location, either on the stack 3.23 + * or in a field of a struct, whose contents is an addr. That addr is of the 3.24 + * first location of a chunk of locations. The DynArray works by changing 3.25 + * the chunk of locations, then modifying the contents of the original 3.26 + * array variable. It overwrites the addr of the old chunk of locations 3.27 + * with the addr of the new chunk. 3.28 + *But when the array variable is passed as a parameter, such as 3.29 + * in this: "foo( myDynArray )", then there are now two locations that hold 3.30 + * the addr of the same chunk of locations. So when a call is made that 3.31 + * adds to the DynArray, and inside the DynArray expands, it only updates 3.32 + * the original location with the new addr. Hence, the function will begin 3.33 + * overwriting memory past the end of the old chunk, because it still has 3.34 + * the pointer to the old chunk of locations. 3.35 + * 3.36 + *A dynamic array is accessed same as any other array. However, must use 3.37 + * dyn array calls, defined in here, in order to add or increase the size. 3.38 + * Must re-read the original array variable after any size-changing calls. 3.39 + *To pass a DynArray as a parameter to a function, can only pass the 3.40 + * DynArrayInfo, then inside the function, to read the addr of the first 3.41 + * location in the chunk of locations that is the array, do this: 3.42 + * "localArrayCopy = *(myDynArrayInfo->addrOfPtrToArray). After that, can 3.43 + * treat localArrayCopy as a normal array, as long as don't make any calls 3.44 + * that add or otherwise could increase the size of the array. If do make 3.45 + * such a call, then re-copy the array via the above. Can then use the 3.46 + * copy up until another add to the array. 3.47 + * 3.48 + */ 3.49 +typedef struct 3.50 + { 3.51 + void ***addrOfPtrToArray; //addr of array of ptrs == triple * 3.52 + int32 numInArray; 3.53 + int32 sizeOfArray; 3.54 + } 3.55 +PrivDynArrayInfo; 3.56 + 3.57 + 3.58 +typedef struct 3.59 + { 3.60 + void **ptrToLocations; //must be in first position 3.61 + int32 numInArray; 3.62 + int32 sizeOfArray; 3.63 + } 3.64 +PrivDynArray; 3.65 + 3.66 + 3.67 +PrivDynArrayInfo * 3.68 +makePrivDynArrayOfSize( int32 sizeOfArray ); 3.69 + 3.70 +PrivDynArrayInfo * 3.71 +makePrivDynArrayOfSize_Ext( int32 sizeOfArray ); 3.72 + 3.73 +int32 3.74 +addToDynArray( void *value, void *array ); 3.75 + 3.76 +void 3.77 +makeHighestDynArrayIndexBe( void *array, int32 highestIndex ); 3.78 + 3.79 +void 3.80 +makeHighestDynArrayIndexBeAtLeast( void *array, int32 highestIndex); 3.81 + 3.82 +void 3.83 +increaseSizeOfDynArrayTo( void *array, int32 newSize ); 3.84 + 3.85 +typedef void (*FreeFnPtr) ( void * ); //fn has to cast void * to whatever 3.86 + 3.87 +void 3.88 +freeDynArrayDeep( void *array, FreeFnPtr freeFnPtr ); 3.89 + 3.90 +void 3.91 +freeDynArrayFlat( void *array ); 3.92 + 3.93 + 3.94 +typedef void (*DynArrayFnPtr) ( void * ); //fn has to cast void * 3.95 + 3.96 +void 3.97 +forAllInDynArrayDo( void *array, DynArrayFnPtr fnPtr ); 3.98 + 3.99 +#endif /* _DYNARRAY_H */ 3.100 +
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/__brch__Dev_prolog_vers Fri Jul 19 12:27:43 2013 -0700 4.3 @@ -0,0 +1,4 @@ 4.4 +This branch is for the project structure defined Jan 2012.. the #includes reflect this directory structure. 4.5 + 4.6 +More importantly, the MC_shared version of PR requires a separat malloc implemeted by PR code.. so this branch has modified the library to use the PR-specific malloc. 4.7 +
5.1 --- a/__brch__Renamed_VMS_to_PR Fri Mar 08 05:37:45 2013 -0800 5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 5.3 @@ -1,4 +0,0 @@ 5.4 -This branch is for the project structure defined Jan 2012.. the #includes reflect this directory structure. 5.5 - 5.6 -More importantly, the MC_shared version of PR requires a separat malloc implemeted by PR code.. so this branch has modified the library to use the PR-specific malloc. 5.7 -
