Mercurial > cgi-bin > hgwebdir.cgi > VMS > C_Libraries > DynArray
view 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 source
1 /*
2 * Copyright 2010 OpenSourceCodeStewardshipFoundation
3 *
4 * Licensed under BSD
5 */
9 #include <stdio.h>
10 #include <malloc.h>
12 #include "DynArray.h"
14 //== declarations
15 #define giveInfoFor( array ) &(((PrivDynArrayInfo*)array)[-1])
16 //==
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;
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 }
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
50 numInArray = info->numInArray;
51 sizeOfArray = info->sizeOfArray;
53 if( numInArray >= sizeOfArray )
54 {
55 array = increaseSizeOfDynArrayTo2( array, sizeOfArray * 2 );
56 info = giveInfoFor( array );
57 }
59 array[ numInArray ] = value;
60 info->numInArray++;
62 return numInArray; //index of last elem is one less than num in array
63 }
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 );
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 }
86 /*Allows highest index to remain higher than index give*/
87 void
88 makeHighestDynArrayIndexBeAtLeast2( void **array, int32 index)
89 { PrivDynArrayInfo *info = giveInfoFor( array );
91 if( index < info->numInArray ) return; //num added diff than size
92 else makeNumInArrayBe2( array, index );
93 }
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;
105 oldsizeOfArray = oldInfo->sizeOfArray;
106 if( newSize <= oldsizeOfArray ) return;
108 newInfo = PR_int__malloc( newSize * oldInfo->sizeOfElem + sizeof(PrivDynArrayInfo) );
109 newArray = &(newInfo[1]);
111 numBytesToCopy = oldInfo->numInArray * oldInfo->sizeOfElem + sizeof(PrivDynArrayInfo);
112 memcpy( newInfo, oldInfo, numBytesToCopy ); //copies info + array contents
114 *(newInfo->addrOfPtrToArray) = newArray; //change contents of array var
115 newInfo->sizeOfArray = newSize;
117 PR_int__free( oldInfo );
119 return newArray;
120 }
123 /* Frees the array, plus the info
124 */
125 void
126 freeDynArrayDeep2( void *array, FreeFnPtr freeFnPtr )
127 { PrivDynArrayInfo *info = giveInfoFor( array );
129 forAllInDynArrayDo2( array, freeFnPtr );
130 PR_int__free( info );
131 }
133 /* Only frees the info
134 */
135 void
136 freeDynArrayFlat2( void *array )
137 { PrivDynArrayInfo *info = giveInfoFor( array );
139 PR_int__free( info );
140 }
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;
152 sizeOfElem = info->sizeOfElem;
153 for( idx = 0; idx < info->numInArray; idx++ )
154 { addrOfElem = ((int8 *)array) + idx * sizeOfElem;
155 (*fnPtr)( addrOfElem );
156 }
157 }
