Mercurial > cgi-bin > hgwebdir.cgi > VMS > C_Libraries > DynArray
view DynArray.c @ 7:4506c08ed60d
added external, and "AtLeast"
| author | Me |
|---|---|
| date | Sat, 20 Nov 2010 08:21:49 +0100 |
| parents | f4b108f21041 |
| children | bc91986481e1 |
line source
1 /*
2 * Copyright 2010 OpenSourceCodeStewardshipFoundation
3 *
4 * Licensed under BSD
5 */
9 #include <stdio.h>
11 #include "DynArray.h"
15 PrivDynArrayInfo *
16 makePrivDynArrayInfoFrom( void ***addrOfPtrToArray, int32 sizeOfArray )
17 { PrivDynArrayInfo *info;
19 info = VMS__malloc( sizeof(PrivDynArrayInfo) );
21 info->addrOfPtrToArray = addrOfPtrToArray;
22 info->sizeOfArray = sizeOfArray;
23 info->numInArray = 0;
24 }
26 PrivDynArrayInfo *
27 makePrivDynArrayOfSize( void ***addrOfPtrToArray, int32 sizeOfArray )
28 { PrivDynArrayInfo *info;
30 info = VMS__malloc( sizeof(PrivDynArrayInfo) );
32 info->addrOfPtrToArray = addrOfPtrToArray;
34 *(addrOfPtrToArray) = VMS__malloc( sizeOfArray * sizeof(void *) );
35 info->sizeOfArray = sizeOfArray;
36 info->numInArray = 0;
37 }
39 PrivDynArrayInfo *
40 makePrivDynArrayOfSize_Ext( void ***addrOfPtrToArray, int32 sizeOfArray )
41 { PrivDynArrayInfo *info;
43 info = malloc( sizeof(PrivDynArrayInfo) );
45 info->addrOfPtrToArray = addrOfPtrToArray;
47 *(addrOfPtrToArray) = malloc( sizeOfArray * sizeof(void *) );
48 info->sizeOfArray = sizeOfArray;
49 info->numInArray = 0;
50 }
53 /*A dynamic array is same as any other array, but add a DynArrayInfo next
54 * to it. Accesses and updates of array indexes are done normally, it's
55 * only when add a new element into array that use the extra info.
56 * An add can cause the pointer to the normal array to change.. so must
57 * be protected to single VP at a time.
58 *
59 *Only need to use this Fn when need a new index, higher than any previous
60 */
61 int32
62 addToDynArray( void *value, PrivDynArrayInfo *info )
63 { int32 numInArray, sizeOfArray;
64 void **array;
66 numInArray = info->numInArray;
67 sizeOfArray = info->sizeOfArray;
69 if( numInArray >= sizeOfArray )
70 {
71 increaseSizeOfDynArrayTo( info, sizeOfArray * 2 );
72 }
74 array = *(info->addrOfPtrToArray);
75 array[ numInArray ] = value;
76 info->numInArray++;
78 return numInArray; //pre-incr value is the index put value into
79 }
80 int32
81 addToDynArray_Ext( void *value, PrivDynArrayInfo *info )
82 { int32 numInArray, sizeOfArray;
83 void **array;
85 numInArray = info->numInArray;
86 sizeOfArray = info->sizeOfArray;
88 if( numInArray >= sizeOfArray )
89 {
90 increaseSizeOfDynArrayTo_Ext( info, sizeOfArray * 2 );
91 }
93 array = *(info->addrOfPtrToArray);
94 array[ numInArray ] = value;
95 info->numInArray++;
97 return numInArray; //pre-incr value is the index put value into
98 }
101 /*Use this when know how many things going to add in -- then can do this
102 * once and use as normal array afterwards. If later add another chunk,
103 * do this again. Note, this makes new size be just big enough to hold
104 * highest index, so will do a linear number of copies if use only this.
105 *To cut down on number of copies, can use the increaseSizeTo Fn to
106 * exponentially increase size..
107 */
108 void
109 makeHighestDynArrayIndexBe( PrivDynArrayInfo *info, int32 highestIndex )
110 {
111 if( info->sizeOfArray <= highestIndex )
112 {
113 increaseSizeOfDynArrayTo( info, highestIndex + 1 );
114 }
115 info->numInArray = highestIndex + 1;
116 }
118 void
119 makeHighestDynArrayIndexBeAtLeast(PrivDynArrayInfo *info, int32 index)
120 {
121 if( index < info->numInArray ) return;
122 else makeHighestDynArrayIndexBe( info, index );
123 }
126 /*Only use this if certain new size is bigger than current size
127 */
128 void
129 increaseSizeOfDynArrayTo( PrivDynArrayInfo *info, int32 newSize )
130 { int32 oldSizeOfArray, i;
131 void **newArray, **oldArray;
133 oldSizeOfArray = info->sizeOfArray;
134 if( newSize <= oldSizeOfArray ) return;
136 oldArray = *(info->addrOfPtrToArray);
137 newArray = VMS__malloc( newSize * sizeof(void *) );
139 for( i = 0; i < oldSizeOfArray; i++ )
140 {
141 newArray[i] = oldArray[i];
142 }
143 *(info->addrOfPtrToArray) = newArray; //change location of array-ptr
144 info->sizeOfArray = newSize;
146 VMS__free( oldArray );
147 }
149 /*Can't mix VMS__malloc locations with external malloc locations -- so use
150 * this version inside VMS, which will perform normal malloc in the core
151 * loop -- hopefully avoiding the annoying system-stack bugs..
152 */
153 void
154 increaseSizeOfDynArrayTo_Ext( PrivDynArrayInfo *info, int32 newSize )
155 { int32 oldSizeOfArray, i;
156 void **newArray, **oldArray;
158 oldSizeOfArray = info->sizeOfArray;
159 if( newSize <= oldSizeOfArray ) return;
161 oldArray = *(info->addrOfPtrToArray);
162 newArray = malloc( newSize * sizeof(void *) );
164 for( i = 0; i < oldSizeOfArray; i++ )
165 {
166 newArray[i] = oldArray[i];
167 }
168 *(info->addrOfPtrToArray) = newArray; //change location of array-ptr
169 info->sizeOfArray = newSize;
171 free( oldArray );
172 }
175 /* Frees the array, plus the info
176 */
177 void
178 freeDynArrayDeep( PrivDynArrayInfo *info, FreeFnPtr freeFnPtr )
179 {
180 forAllInDynArrayDo( info, freeFnPtr );
181 VMS__free( *(info->addrOfPtrToArray) );
182 VMS__free( info );
183 }
185 /* Only frees the info
186 */
187 void
188 freeDynArrayFlat( PrivDynArrayInfo *info )
189 {
190 VMS__free( info );
191 }
194 /*The function has a fixed prototype: takes a void * returns void
195 * So, the function has to internally cast void * to whatever data struc..
196 */
197 void
198 forAllInDynArrayDo( PrivDynArrayInfo *info, DynArrayFnPtr fnPtr )
199 { int32 idx;
200 void **array;
202 array = *(info->addrOfPtrToArray);
203 for( idx = 0; idx < info->numInArray; idx++ )
204 {
205 (*fnPtr)(array[idx]);
206 }
207 }
