1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * Copyright by the Board of Trustees of the University of Illinois. *
4 * All rights reserved. *
5 * *
6 * This file is part of HDF. The full HDF copyright notice, including *
7 * terms governing use, modification, and redistribution, is contained in *
8 * the COPYING file, which can be found at the root of the source code *
9 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/. *
10 * If you do not have access to either file, you may request a copy from *
11 * help@hdfgroup.org. *
12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14 /* $Id$ */
15
16 /*
17 FILE
18 dynarray.c - Internal storage routines for handling "dynamic arrays"
19
20 REMARKS
21 Dynamic arrays are "standard" arrays which store objects in a straight-
22 forward linear array of objects (void *'s currently), but the "dynarray"
23 allows the size of the array to vary without excessive overhead.
24
25 DESIGN
26 Each dynarray is managed as a small structure to store the current size
27 of the dynarray and a pointer to the array of pointers to the objects
28 stored within the array.
29
30 BUGS/LIMITATIONS
31 No hashing or any other "folding" of the storage space is done, so the size
32 of the dynarray can get quite excessive in proportion to the # of elements
33 used if the elements used are "sparse" in the dynarray space.
34
35 These are strictly useable from C, adding a FORTRAN calling facility would
36 require some re-working of the routines.
37
38 LOCAL ROUTINES
39 None
40 EXPORTED ROUTINES
41 Element Functions:
42 DAget_elem - Get an element from a dynarray
43 DAset_elem - Set an element pointer for a dynarray
44 DAdel_elem - Delete an element from a dynarray
45 Dynarray Functions:
46 DAcreate_array - Create a dynarray
47 DAdestroy_array - Destroy a dynarray
48 DAsize_array - Get the current dynarray size
49
50 AUTHOR
51 Quincey Koziol
52
53 MODIFICATION HISTORY
54 1/7/96 - Starting writing specs & coding prototype
55 */
56
57 #define DYNARRAY_MASTER
58 #include "hdf.h"
59 #include "dynarray.h"
60
61
62 /* Private function prototypes */
63 /* <none yet> */
64
65 /******************************************************************************
66 NAME
67 DAcreate_array - Create a dynarray
68
69 DESCRIPTION
70 Create a dynarray for later use. This routine allocates the dynarray
71 structure and creates a dynarray with the specified minimum size.
72
73 RETURNS
74 Returns pointer to the dynarray created if successful and NULL otherwise
75
76 *******************************************************************************/
DAcreate_array(intn start_size,intn incr_mult)77 dynarr_p DAcreate_array(intn start_size, /* IN: Initial array size */
78 intn incr_mult /* IN: multiple to create additional elements in */
79 )
80 {
81 CONSTR(FUNC, "DAcreate_array"); /* for HERROR */
82 dynarr_t *new_arr=NULL; /* ptr to the new dynarray */
83 dynarr_p ret_value=NULL;
84
85 HEclear();
86 if(start_size<0 || incr_mult<=0)
87 HGOTO_ERROR(DFE_ARGS, NULL);
88
89 new_arr=(dynarr_t *)HDcalloc(1,sizeof(dynarr_t));
90 if(new_arr==NULL)
91 HGOTO_ERROR(DFE_NOSPACE, NULL);
92
93 new_arr->num_elems=start_size;
94 new_arr->incr_mult=incr_mult;
95 if(start_size>0)
96 { /* only allocate space if the initial size is positive */
97 new_arr->arr=(VOIDP *)HDcalloc(start_size,sizeof(VOIDP));
98 if(new_arr->arr==NULL)
99 HGOTO_ERROR(DFE_NOSPACE, NULL);
100 } /* end if */
101
102 ret_value=(dynarr_p)new_arr;
103
104 done:
105 if(ret_value == NULL)
106 { /* Error condition cleanup */
107 if(new_arr!=NULL)
108 {
109 if(new_arr->arr!=NULL)
110 HDfree(new_arr->arr);
111 HDfree(new_arr);
112 } /* end if */
113 } /* end if */
114
115 /* Normal function cleanup */
116 return ret_value;
117 } /* end DAcreate_array() */
118
119 /******************************************************************************
120 NAME
121 DAdestroy_array - Destroy a dynarray
122
123 DESCRIPTION
124 Destroy an existing dynarray from use. This routine de-allocates the
125 dynarray structure and deletes the current dynarray.
126
127 RETURNS
128 Returns SUCCEED if successful and FAIL otherwise
129
130 *******************************************************************************/
DAdestroy_array(dynarr_p arr,intn free_elem)131 intn DAdestroy_array(dynarr_p arr, /* IN: Array to destroy */
132 intn free_elem /* IN: whether to free each element */
133 )
134 {
135 CONSTR(FUNC, "DAdestroy_array"); /* for HERROR */
136 dynarr_t *dest_arr; /* ptr to the dynarray destroy*/
137 intn i;
138 intn ret_value=SUCCEED;
139
140 HEclear();
141 dest_arr=(dynarr_t *)arr;
142 if(dest_arr==NULL)
143 HGOTO_ERROR(DFE_ARGS, FAIL);
144
145 /* Chuck all the items stored in the array */
146 if(free_elem!=0)
147 for(i=0; i<arr->num_elems; i++)
148 {
149 if(arr->arr[i]!=NULL)
150 HDfree(arr->arr[i]);
151 } /* end for */
152
153 if(dest_arr->arr!=NULL)
154 HDfree(dest_arr->arr);
155 HDfree(dest_arr);
156
157 done:
158 if(ret_value == FAIL)
159 { /* Error condition cleanup */
160
161 } /* end if */
162
163 /* Normal function cleanup */
164 return ret_value;
165 } /* end DAdestroy_array() */
166
167 /******************************************************************************
168 NAME
169 DAdestroy_array - Get the current size of a dynarray
170
171 DESCRIPTION
172 Get the number of elements in use currently.
173
174 RETURNS
175 Returns # of dynarray elements if successful and FAIL otherwise
176
177 *******************************************************************************/
DAsize_array(dynarr_p arr)178 intn DAsize_array(dynarr_p arr /* IN: Array to get size of */
179 )
180 {
181 CONSTR(FUNC, "DAsize_array"); /* for HERROR */
182 dynarr_t *arr_ptr; /* ptr to the dynarray destroy*/
183 intn ret_value=SUCCEED;
184
185 HEclear();
186 arr_ptr=(dynarr_t *)arr;
187 if(arr_ptr==NULL)
188 HGOTO_ERROR(DFE_ARGS, FAIL);
189
190 ret_value=arr_ptr->num_elems;
191
192 done:
193 if(ret_value == FAIL)
194 { /* Error condition cleanup */
195
196 } /* end if */
197
198 /* Normal function cleanup */
199 return ret_value;
200 } /* end DAsize_array() */
201
202 /******************************************************************************
203 NAME
204 DAget_elem - Get an element from a dynarray
205
206 DESCRIPTION
207 Retrieve an element from a dynarray. If the element to be retrieved is
208 beyond the end of the currently allocated array elements, the array is
209 not extended, a NULL pointer is merely returned.
210
211 RETURNS
212 Returns object ptr if successful and NULL otherwise
213
214 *******************************************************************************/
DAget_elem(dynarr_p arr_ptr,intn elem)215 VOIDP DAget_elem(dynarr_p arr_ptr, /* IN: Array to access */
216 intn elem /* IN: Array element to retrieve */
217 )
218 {
219 CONSTR(FUNC, "DAget_elem"); /* for HERROR */
220 dynarr_t *arr; /* ptr to the dynarray */
221 VOIDP ret_value=NULL;
222
223 HEclear();
224 arr=(dynarr_t *)arr_ptr;
225 if(elem<0 || arr==NULL)
226 HGOTO_ERROR(DFE_ARGS, NULL);
227
228 if(elem>=arr->num_elems)
229 ret_value=NULL;
230 else
231 ret_value=arr->arr[elem];
232
233 done:
234 if(ret_value == NULL)
235 { /* Error condition cleanup */
236
237 } /* end if */
238
239 /* Normal function cleanup */
240 return ret_value;
241 } /* end DAget_elem() */
242
243 /******************************************************************************
244 NAME
245 DAset_elem - Set an element pointer for a dynarray
246
247 DESCRIPTION
248 Set an element pointer for a dynarray. If the element to be set is
249 beyond the end of the currently allocated array elements, the array is
250 extended by whatever multiple of the incr_mult is needed to expand the
251 # of array elements to include the array element to set.
252
253 RETURNS
254 Returns SUCCEED if successful and NULL otherwise
255
256 *******************************************************************************/
DAset_elem(dynarr_p arr_ptr,intn elem,VOIDP obj)257 intn DAset_elem(dynarr_p arr_ptr, /* IN: Array to access */
258 intn elem, /* IN: Array element to set */
259 VOIDP obj /* IN: Pointer to the object to store */
260 )
261 {
262 CONSTR(FUNC, "DAset_elem"); /* for HERROR */
263 dynarr_t *arr; /* ptr to the dynarray */
264 intn ret_value=SUCCEED;
265
266 HEclear();
267 arr=(dynarr_t *)arr_ptr;
268 if(elem<0 || arr==NULL)
269 HGOTO_ERROR(DFE_ARGS, FAIL);
270
271 if(elem>=arr->num_elems)
272 {
273 intn new_size; /* new number of elements in the array */
274
275 new_size=((elem/arr->incr_mult)+1)*arr->incr_mult;
276 if(arr->num_elems==0)
277 { /* array not currently allocated */
278 if((arr->arr=(VOIDP *)HDcalloc(new_size,sizeof(VOIDP)))==NULL)
279 HGOTO_ERROR(DFE_NOSPACE, FAIL);
280 } /* end if */
281 else
282 { /* extend the existing array */
283 VOIDP *new_arr; /* storage for the new array of ptrs */
284
285 if((new_arr=(VOIDP *)HDrealloc(arr->arr,new_size*sizeof(VOIDP)))==NULL)
286 HGOTO_ERROR(DFE_NOSPACE, FAIL);
287 HDmemset(&new_arr[arr->num_elems],0,sizeof(VOIDP)*(uintn)(new_size-arr->num_elems));
288 arr->arr=new_arr;
289 } /* end else */
290 arr->num_elems=new_size;
291 } /* end if */
292
293 /* Set the element value */
294 arr->arr[elem]=obj;
295
296 done:
297 if(ret_value == FAIL)
298 { /* Error condition cleanup */
299
300 } /* end if */
301
302 /* Normal function cleanup */
303 return ret_value;
304 } /* end DAset_elem() */
305
306 /*****************************************************************************
307 NAME
308 DAdel_elem - Delete an element from a dynarray
309
310 DESCRIPTION
311 Retrieve an element from a dynarray & delete it from the dynarray. If the
312 element to be retrieved is beyond the end of the currently allocated array
313 elements, the array is not extended, a NULL pointer is merely returned.
314
315 RETURNS
316 Returns object ptr if successful and NULL otherwise
317
318 *******************************************************************************/
DAdel_elem(dynarr_p arr_ptr,intn elem)319 VOIDP DAdel_elem(dynarr_p arr_ptr, /* IN: Array to access */
320 intn elem /* IN: Array element to retrieve */
321 )
322 {
323 CONSTR(FUNC, "DAdel_elem"); /* for HERROR */
324 dynarr_t *arr; /* ptr to the dynarray */
325 VOIDP ret_value=NULL;
326
327 HEclear();
328 arr=(dynarr_t *)arr_ptr;
329 if(elem<0 || arr==NULL)
330 HGOTO_ERROR(DFE_ARGS, NULL);
331
332 if(elem>=arr->num_elems)
333 ret_value=NULL;
334 else
335 {
336 ret_value=arr->arr[elem];
337 arr->arr[elem]=NULL;
338 } /* end else */
339
340 done:
341 if(ret_value == NULL)
342 { /* Error condition cleanup */
343
344 } /* end if */
345
346 /* Normal function cleanup */
347 return ret_value;
348 } /* end DAdel_elem() */
349
350