Mercurial > cgi-bin > hgwebdir.cgi > VMS > C_Libraries > DynArray
view DynArray.c @ 9:bc91986481e1
Merge of adding external, with bug-fix in makeDynArray
| author | Me |
|---|---|
| date | Sat, 20 Nov 2010 08:27:06 +0100 |
| parents | 4506c08ed60d 015aab562ace |
| children | 20f0996a8400 |
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 return info;
25 }
27 PrivDynArrayInfo *
28 makePrivDynArrayOfSize( void ***addrOfPtrToArray, int32 sizeOfArray )
29 { PrivDynArrayInfo *info;
31 info = VMS__malloc( sizeof(PrivDynArrayInfo) );
33 info->addrOfPtrToArray = addrOfPtrToArray;
35 *(addrOfPtrToArray) = VMS__malloc( sizeOfArray * sizeof(void *) );
36 info->sizeOfArray = sizeOfArray;
37 info->numInArray = 0;
38 return info;
39 }
41 PrivDynArrayInfo *
42 makePrivDynArrayOfSize_Ext( void ***addrOfPtrToArray, int32 sizeOfArray )
43 { PrivDynArrayInfo *info;
45 info = malloc( sizeof(PrivDynArrayInfo) );
47 info->addrOfPtrToArray = addrOfPtrToArray;
49 *(addrOfPtrToArray) = malloc( sizeOfArray * sizeof(void *) );
50 info->sizeOfArray = sizeOfArray;
51 info->numInArray = 0;
52 }
55 /*A dynamic array is same as any other array, but add a DynArrayInfo next
56 * to it. Accesses and updates of array indexes are done normally, it's
57 * only when add a new element into array that use the extra info.
58 * An add can cause the pointer to the normal array to change.. so must
59 * be protected to single VP at a time.
60 *
61 *Only need to use this Fn when need a new index, higher than any previous
62 */
63 int32
64 addToDynArray( void *value, PrivDynArrayInfo *info )
65 { int32 numInArray, sizeOfArray;
66 void **array;
68 numInArray = info->numInArray;
69 sizeOfArray = info->sizeOfArray;
71 if( numInArray >= sizeOfArray )
72 {
73 increaseSizeOfDynArrayTo( info, sizeOfArray * 2 );
74 }
76 array = *(info->addrOfPtrToArray);
77 array[ numInArray ] = value;
78 info->numInArray++;
80 return numInArray; //pre-incr value is the index put value into
81 }
82 int32
83 addToDynArray_Ext( void *value, PrivDynArrayInfo *info )
84 { int32 numInArray, sizeOfArray;
85 void **array;
87 numInArray = info->numInArray;
88 sizeOfArray = info->sizeOfArray;
90 if( numInArray >= sizeOfArray )
91 {
92 increaseSizeOfDynArrayTo_Ext( info, sizeOfArray * 2 );
93 }
95 array = *(info->addrOfPtrToArray);
96 array[ numInArray ] = value;
97 info->numInArray++;
99 return numInArray; //pre-incr value is the index put value into
100 }
103 /*Use this when know how many things going to add in -- then can do this
104 * once and use as normal array afterwards. If later add another chunk,
105 * do this again. Note, this makes new size be just big enough to hold
106 * highest index, so will do a linear number of copies if use only this.
107 *To cut down on number of copies, can use the increaseSizeTo Fn to
108 * exponentially increase size..
109 */
110 void
111 makeHighestDynArrayIndexBe( PrivDynArrayInfo *info, int32 highestIndex )
112 {
113 if( info->sizeOfArray <= highestIndex )
114 {
115 increaseSizeOfDynArrayTo( info, highestIndex + 1 );
116 }
117 info->numInArray = highestIndex + 1;
118 }
120 void
121 makeHighestDynArrayIndexBeAtLeast(PrivDynArrayInfo *info, int32 index)
122 {
123 if( index < info->numInArray ) return;
124 else makeHighestDynArrayIndexBe( info, index );
125 }
128 /*Only use this if certain new size is bigger than current size
129 */
130 void
131 increaseSizeOfDynArrayTo( PrivDynArrayInfo *info, int32 newSize )
132 { int32 oldSizeOfArray, i;
133 void **newArray, **oldArray;
135 oldSizeOfArray = info->sizeOfArray;
136 if( newSize <= oldSizeOfArray ) return;
138 oldArray = *(info->addrOfPtrToArray);
139 newArray = VMS__malloc( newSize * sizeof(void *) );
141 for( i = 0; i < oldSizeOfArray; i++ )
142 {
143 newArray[i] = oldArray[i];
144 }
145 *(info->addrOfPtrToArray) = newArray; //change location of array-ptr
146 info->sizeOfArray = newSize;
148 VMS__free( oldArray );
149 }
151 /*Can't mix VMS__malloc locations with external malloc locations -- so use
152 * this version inside VMS, which will perform normal malloc in the core
153 * loop -- hopefully avoiding the annoying system-stack bugs..
154 */
155 void
156 increaseSizeOfDynArrayTo_Ext( PrivDynArrayInfo *info, int32 newSize )
157 { int32 oldSizeOfArray, i;
158 void **newArray, **oldArray;
160 oldSizeOfArray = info->sizeOfArray;
161 if( newSize <= oldSizeOfArray ) return;
163 oldArray = *(info->addrOfPtrToArray);
164 newArray = malloc( newSize * sizeof(void *) );
166 for( i = 0; i < oldSizeOfArray; i++ )
167 {
168 newArray[i] = oldArray[i];
169 }
170 *(info->addrOfPtrToArray) = newArray; //change location of array-ptr
171 info->sizeOfArray = newSize;
173 free( oldArray );
174 }
177 /* Frees the array, plus the info
178 */
179 void
180 freeDynArrayDeep( PrivDynArrayInfo *info, FreeFnPtr freeFnPtr )
181 {
182 forAllInDynArrayDo( info, freeFnPtr );
183 VMS__free( *(info->addrOfPtrToArray) );
184 VMS__free( info );
185 }
187 /* Only frees the info
188 */
189 void
190 freeDynArrayFlat( PrivDynArrayInfo *info )
191 {
192 VMS__free( info );
193 }
196 /*The function has a fixed prototype: takes a void * returns void
197 * So, the function has to internally cast void * to whatever data struc..
198 */
199 void
200 forAllInDynArrayDo( PrivDynArrayInfo *info, DynArrayFnPtr fnPtr )
201 { int32 idx;
202 void **array;
204 array = *(info->addrOfPtrToArray);
205 for( idx = 0; idx < info->numInArray; idx++ )
206 {
207 (*fnPtr)(array[idx]);
208 }
209 }
