OpenMoHAA 0.82.1
Loading...
Searching...
No Matches
darray.h
1#ifndef _DARRAY_H
2#define _DARRAY_H
3
4/* File: darray.h
5 * --------------
6 * Defines the interface for the DynamicArray ADT.
7 * The DArray allows the client to store any number of elements of any desired
8 * base type and is appropriate for a wide variety of storage problems. It
9 * supports efficient element access, and appending/inserting/deleting elements
10 * as well as optional sorting and searching. In all cases, the DArray imposes
11 * no upper bound on the number of elements and deals with all its own memory
12 * management. The client specifies the size (in bytes) of the elements that
13 * will be stored in the array when it is created. Thereafter the client and
14 * the DArray can refer to elements via (void*) ptrs.
15 */
16
17#ifdef __cplusplus
18extern "C" {
19#endif
20
21/* Type: DArray
22 * ----------------
23 * Defines the DArray type itself. The client can declare variables of type
24 * DArray, but these variables must be initialized with the result of ArrayNew.
25 * The DArray is implemented with pointers, so all client copies in variables
26 * or parameters will be "shallow" -- they will all actually point to the
27 * same DArray structure. Only calls to ArrayNew create new arrays.
28 * The struct declaration below is "incomplete"- the implementation
29 * details are literally not visible in the client .h file.
30 */
31typedef struct DArrayImplementation *DArray;
32
33
34/* ArrayCompareFn
35 * --------------
36 * ArrayCompareFn is a pointer to a client-supplied function which the
37 * DArray uses to sort or search the elements. The comparator takes two
38 * (const void*) pointers (these will point to elements) and returns an int.
39 * The comparator should indicate the ordering of the two elements
40 * using the same convention as the strcmp library function:
41 * If elem1 is "less than" elem2, return a negative number.
42 * If elem1 is "greater than" elem2, return a positive number.
43 * If the two elements are "equal", return 0.
44 */
45typedef int (*ArrayCompareFn)(const void *elem1, const void *elem2);
46
47
48/* ArrayMapFn
49 * ----------
50 * ArrayMapFn defines the space of functions that can be used to map over
51 * the elements in a DArray. A map function is called with a pointer to
52 * the element and a client data pointer passed in from the original
53 * caller.
54 */
55typedef void (*ArrayMapFn)(void *elem, void *clientData);
56
57/* ArrayMapFn2
58 * ----------_
59 * Same as ArrayMapFn, but can return 0 to stop the mapping.
60 * Used by ArrayMap2
61 */
62typedef int (*ArrayMapFn2)(void *elem, void *clientData);
63
64 /* ArrayElementFreeFn
65 * ------------------
66 * ArrayElementFreeFn defines the space of functions that can be used as the
67 * clean-up function for an element as it is deleted from the array
68 * or when the entire array of elements is freed. The cleanup function is
69 * called with a pointer to an element about to be deleted.
70 */
71typedef void (*ArrayElementFreeFn)(void *elem);
72
73
74/* ArrayNew
75 * --------
76 * Creates a new DArray and returns it. There are zero elements in the array.
77 * to start. The elemSize parameter specifies the number of bytes that a single
78 * element of this array should take up. For example, if you want to store
79 * elements of type Binky, you would pass sizeof(Binky) as this parameter.
80 * An assert is raised if the size is not greater than zero.
81 *
82 * The numElemsToAllocate parameter specifies the initial allocated length
83 * of the array, as well as the dynamic reallocation increment for when the
84 * array grows. Rather than growing the array one element at a time as
85 * elements are added (which is rather inefficient), you will grow the array
86 * in chunks of numElemsToAllocate size. The "allocated length" is the number
87 * of elements that have been allocated, the "logical length" is the number of
88 * those slots actually being currently used.
89 *
90 * A new array is initially allocated to the size of numElemsToAllocate, the
91 * logical length is zero. As elements are added, those allocated slots fill
92 * up and when the initial allocation is all used, grow the array by another
93 * numElemsToAllocate elements. You will continue growing the array in chunks
94 * like this as needed. Thus the allocated length will always be a multiple
95 * of numElemsToAllocate. Don't worry about using realloc to shrink the array
96 * allocation if many elements are deleted from the array. It turns out that
97 * many implementations of realloc don't even pay attention to such a request
98 * so there is little point in asking. Just leave the array over-allocated.
99 *
100 * The numElemsToAllocate is the client's opportunity to tune the resizing
101 * behavior for their particular needs. If constructing large arrays,
102 * specifying a large allocation chunk size will result in fewer resizing
103 * operations. If using small arrays, a small allocation chunk size will
104 * result in less space going unused. If the client passes 0 for
105 * numElemsToAllocate, the implementation will use the default value of 8.
106 *
107 * The elemFreeFn is the function that will be called on an element that
108 * is about to be deleted (using ArrayDeleteAt) or on each element in the
109 * array when the entire array is being freed (using ArrayFree). This function
110 * is your chance to do any deallocation/cleanup required for the element
111 * (such as freeing any pointers contained in the element). The client can pass
112 * NULL for the cleanupFn if the elements don't require any handling on free.
113 */
114DArray ArrayNew(int elemSize, int numElemsToAllocate,
115 ArrayElementFreeFn elemFreeFn);
116
117
118
119 /* ArrayFree
120 * ----------
121 * Frees up all the memory for the array and elements. It DOES NOT
122 * automatically free memory owned by pointers embedded in the elements.
123 * This would require knowledge of the structure of the elements which the
124 * DArray does not have. However, it will iterate over the elements calling
125 * the elementFreeFn earlier supplied to ArrayNew and therefore, the client,
126 * who knows what the elements are, can do the appropriate deallocation of any
127 * embedded pointers through that function. After calling this, the value of
128 * what array is pointing to is undefined.
129 */
130void ArrayFree(DArray array);
131
132
133/* ArrayLength
134 * -----------
135 * Returns the logical length of the array, i.e. the number of elements
136 * currently in the array. Must run in constant time.
137 */
138int ArrayLength(const DArray array);
139
140
141/* ArrayNth
142 * --------
143 * Returns a pointer to the element numbered n in the specified array.
144 * Numbering begins with 0. An assert is raised if n is less than 0 or greater
145 * than the logical length minus 1. Note this function returns a pointer into
146 * the DArray's element storage, so the pointer should be used with care.
147 * This function must operate in constant time.
148 *
149 * We could have written the DArray without this sort of access, but it
150 * is useful and efficient to offer it, although the client needs to be
151 * careful when using it. In particular, a pointer returned by ArrayNth
152 * becomes invalid after any calls which involve insertion, deletion or
153 * sorting the array, as all of these may rearrange the element storage.
154 */
155void *ArrayNth(DArray array, int n);
156
157
158/* ArrayAppend
159 * -----------
160 * Adds a new element to the end of the specified array. The element is
161 * passed by address, the element contents are copied from the memory pointed
162 * to by newElem. Note that right after this call, the new element will be
163 * the last in the array; i.e. its element number will be the logical length
164 * minus 1. This function must run in constant time (neglecting
165 * the memory reallocation time which may be required occasionally).
166 */
167void ArrayAppend(DArray array, const void *newElem);
168
169/* ArrayInsertAt
170 * -------------
171 * Inserts a new element into the array, placing it at the position n.
172 * An assert is raised if n is less than 0 or greater than the logical length.
173 * The array elements after position n will be shifted over to make room. The
174 * element is passed by address, the new element's contents are copied from
175 * the memory pointed to by newElem. This function runs in linear time.
176 */
177void ArrayInsertAt(DArray array, const void *newElem, int n);
178
179/* ArrayInsertSorted
180 * -------------
181 * Inserts a new element into the array, placing it at the position indicated by
182 * a binary search of the array using comparator.
183 * The array MUST be sorted prior to calling InsertSorted.
184 * Note that if you only ever call InsertSorted, the array will always be sorted.
185 */
186void ArrayInsertSorted(DArray array, const void *newElem, ArrayCompareFn comparator);
187
188 /* ArrayDeleteAt
189 * -------------
190 * Deletes the element numbered n from the array. Before being removed,
191 * the elemFreeFn that was supplied to ArrayNew will be called on the element.
192 * An assert is raised if n is less than 0 or greater than the logical length
193 * minus one. All the elements after position n will be shifted over to fill
194 * the gap. This function runs in linear time. It does not shrink the
195 * allocated size of the array when an element is deleted, the array just
196 * stays over-allocated.
197 */
198void ArrayDeleteAt(DArray array, int n);
199
200 /* ArrayDeleteAt
201 * -------------
202 * Removes the element numbered n from the array. The element will not be freed
203 * before being removed. All the elements after position n will be shifted over to fill
204 * the gap. This function runs in linear time. It does not shrink the
205 * allocated size of the array when an element is deleted, the array just
206 * stays over-allocated.
207 */
208void ArrayRemoveAt(DArray array, int n);
209
210/* ArrayReplaceAt
211 * -------------
212 * Overwrites the element numbered n from the array with a new value. Before
213 * being overwritten, the elemFreeFn that was supplied to ArrayNew is called
214 * on the old element. Then that position in the array will get a new value by
215 * copying the new element's contents from the memory pointed to by newElem.
216 * An assert is raised if n is less than 0 or greater than the logical length
217 * minus one. None of the other elements are affected or rearranged by this
218 * operation and the size of the array remains constant. This function must
219 * operate in constant time.
220 */
221void ArrayReplaceAt(DArray array, const void *newElem, int n);
222
223
224/* ArraySort
225 * ---------
226 * Sorts the specified array into ascending order according to the supplied
227 * comparator. The numbering of the elements will change to reflect the
228 * new ordering. An assert is raised if the comparator is NULL.
229 */
230void ArraySort(DArray array, ArrayCompareFn comparator);
231
232
233#define NOT_FOUND -1 // returned when a search fails to find the key
234
235/* ArraySearch
236 * -----------
237 * Searches the specified array for an element whose contents match
238 * the element passed as the key. Uses the comparator argument to test
239 * for equality. The "fromIndex" parameter controls where the search
240 * starts looking from. If the client desires to search the entire array,
241 * they should pass 0 as the fromIndex. The function will search from
242 * there to the end of the array. The "isSorted" parameter allows the client
243 * to specify that the array is already in sorted order, and thus it uses a
244 * faster binary search. If isSorted is false, a simple linear search is
245 * used. If a match is found, the position of the matching element is returned
246 * else the function returns NOT_FOUND. Calling this function does not
247 * re-arrange or change contents of DArray or modify the key in any way.
248 * An assert is raised if fromIndex is less than 0 or greater than
249 * the logical length (although searching from logical length will never
250 * find anything, allowing this case means you can search an entirely empty
251 * array from 0 without getting an assert). An assert is raised if the
252 * comparator is NULL.
253 */
254int ArraySearch(DArray array, const void *key, ArrayCompareFn comparator,
255 int fromIndex, int isSorted);
256
257
258/* ArrayMap
259 * -----------
260 * Iterates through each element in the array in order (from element 0 to
261 * element n-1) and calls the function fn for that element. The function is
262 * called with the address of the array element and the clientData pointer.
263 * The clientData value allows the client to pass extra state information to
264 * the client-supplied function, if necessary. If no client data is required,
265 * this argument should be NULL. An assert is raised if map function is NULL.
266 */
267void ArrayMap(DArray array, ArrayMapFn fn, void *clientData);
268
269/* ArrayMapBackwards
270 * -----------
271 * Same as ArrayMap, but goes through the array from end to front. This
272 * makes it safe to free elements during the mapping.
273 */
274void ArrayMapBackwards(DArray array, ArrayMapFn fn, void *clientData);
275
276/* ArrayMap2
277 * -----------
278 * Same as ArrayMap, but allows the mapping to be stopped by returning 0
279 * from the mapping function. If the mapping was stopped, the element
280 * it was stopped at will be returned. If it wasn't stopped, then NULL
281 * will be returned.
282 */
283void * ArrayMap2(DArray array, ArrayMapFn2 fn, void *clientData);
284
285/* ArrayMapBackwards2
286 * ------------
287 * Goes through the array backwards, and allows you to stop the mapping.
288 */
289void * ArrayMapBackwards2(DArray array, ArrayMapFn2 fn, void *clientData);
290
291/* ArrayClear
292 * -----------
293 * Deletes all elements in the array, but without freeing the array.
294 */
295void ArrayClear(DArray array);
296
297#ifdef __cplusplus
298}
299#endif
300
301#endif //_DARRAY_
Definition darray.c:38