1 utarray: dynamic array macros for C
2 ===================================
3 Troy D. Hanson <tdh@tkhanson.net>
6 Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].
10 A set of general-purpose dynamic array macros for C structures are included with
11 uthash in `utarray.h`. To use these macros in your own C program, just
12 copy `utarray.h` into your source directory and use it in your programs.
16 The dynamic array supports basic operations such as push, pop, and erase on the
17 array elements. These array elements can be any simple datatype or structure.
18 The array <<operations,operations>> are based loosely on the C++ STL vector methods.
20 Internally the dynamic array contains a contiguous memory region into which
21 the elements are copied. This buffer is grown as needed using `realloc` to
22 accommodate all the data that is pushed into it.
26 To download the `utarray.h` header file,
27 follow the links on https://github.com/troydhanson/uthash to clone uthash or get a zip file,
28 then look in the src/ sub-directory.
32 This software is made available under the
33 link:license.html[revised BSD license].
34 It is free and open source.
38 The 'utarray' macros have been tested on:
42 * Windows, using Visual Studio 2008 and Visual Studio 2010
50 The array itself has the data type `UT_array`, regardless of the type of
51 elements to be stored in it. It is declared like,
57 The next step is to create the array using `utarray_new`. Later when you're
58 done with the array, `utarray_free` will free it and all its elements.
62 The central features of the utarray involve putting elements into it, taking
63 them out, and iterating over them. There are several <<operations,operations>>
64 to pick from that deal with either single elements or ranges of elements at a
65 time. In the examples below we will use only the push operation to insert
71 Support for dynamic arrays of integers or strings is especially easy. These are
72 best shown by example:
76 This example makes a utarray of integers, pushes 0-9 into it, then prints it.
80 -------------------------------------------------------------------------------
88 utarray_new(nums,&ut_int_icd);
89 for(i=0; i < 10; i++) utarray_push_back(nums,&i);
91 for(p=(int*)utarray_front(nums);
93 p=(int*)utarray_next(nums,p)) {
101 -------------------------------------------------------------------------------
103 The second argument to `utarray_push_back` is always a 'pointer' to the type
104 (so a literal cannot be used). So for integers, it is an `int*`.
108 In this example we make a utarray of strings, push two strings into it, print
112 -------------------------------------------------------------------------------
120 utarray_new(strs,&ut_str_icd);
122 s = "hello"; utarray_push_back(strs, &s);
123 s = "world"; utarray_push_back(strs, &s);
125 while ( (p=(char**)utarray_next(strs,p))) {
133 -------------------------------------------------------------------------------
135 In this example, since the element is a `char*`, we pass a pointer to it
136 (`char**`) as the second argument to `utarray_push_back`. Note that "push" makes
137 a copy of the source string and pushes that copy into the array.
142 Arrays be made of any type of element, not just integers and strings. The
143 elements can be basic types or structures. Unless you're dealing with integers
144 and strings (which use pre-defined `ut_int_icd` and `ut_str_icd`), you'll need
145 to define a `UT_icd` helper structure. This structure contains everything that
146 utarray needs to initialize, copy or destruct elements.
155 The three function pointers `init`, `copy`, and `dtor` have these prototypes:
157 typedef void (ctor_f)(void *dst, const void *src);
158 typedef void (dtor_f)(void *elt);
159 typedef void (init_f)(void *elt);
161 The `sz` is just the size of the element being stored in the array.
163 The `init` function will be invoked whenever utarray needs to initialize an
164 empty element. This only happens as a byproduct of `utarray_resize` or
165 `utarray_extend_back`. If `init` is `NULL`, it defaults to zero filling the
166 new element using memset.
168 The `copy` function is used whenever an element is copied into the array.
169 It is invoked during `utarray_push_back`, `utarray_insert`, `utarray_inserta`,
170 or `utarray_concat`. If `copy` is `NULL`, it defaults to a bitwise copy using
173 The `dtor` function is used to clean up an element that is being removed from
174 the array. It may be invoked due to `utarray_resize`, `utarray_pop_back`,
175 `utarray_erase`, `utarray_clear`, `utarray_done` or `utarray_free`. If the
176 elements need no cleanup upon destruction, `dtor` may be `NULL`.
181 The next example uses `UT_icd` with all its defaults to make a utarray of
182 `long` elements. This example pushes two longs, prints them, and frees the
186 -------------------------------------------------------------------------------
190 UT_icd long_icd = {sizeof(long), NULL, NULL, NULL };
195 utarray_new(nums, &long_icd);
197 l=1; utarray_push_back(nums, &l);
198 l=2; utarray_push_back(nums, &l);
201 while( (p=(long*)utarray_next(nums,p))) printf("%ld\n", *p);
206 -------------------------------------------------------------------------------
211 Structures can be used as utarray elements. If the structure requires no
212 special effort to initialize, copy or destruct, we can use `UT_icd` with all
213 its defaults. This example shows a structure that consists of two integers. Here
214 we push two values, print them and free the array.
217 -------------------------------------------------------------------------------
226 UT_icd intpair_icd = {sizeof(intpair_t), NULL, NULL, NULL};
232 utarray_new(pairs,&intpair_icd);
234 ip.a=1; ip.b=2; utarray_push_back(pairs, &ip);
235 ip.a=10; ip.b=20; utarray_push_back(pairs, &ip);
237 for(p=(intpair_t*)utarray_front(pairs);
239 p=(intpair_t*)utarray_next(pairs,p)) {
240 printf("%d %d\n", p->a, p->b);
246 -------------------------------------------------------------------------------
248 The real utility of `UT_icd` is apparent when the elements of the utarray are
249 structures that require special work to initialize, copy or destruct.
251 For example, when a structure contains pointers to related memory areas that
252 need to be copied when the structure is copied (and freed when the structure is
253 freed), we can use custom `init`, `copy`, and `dtor` members in the `UT_icd`.
255 Here we take an example of a structure that contains an integer and a string.
256 When this element is copied (such as when an element is pushed into the array),
257 we want to "deep copy" the `s` pointer (so the original element and the new
258 element point to their own copies of `s`). When an element is destructed, we
259 want to "deep free" its copy of `s`. Lastly, this example is written to work
260 even if `s` has the value `NULL`.
263 -------------------------------------------------------------------------------
273 void intchar_copy(void *_dst, const void *_src) {
274 intchar_t *dst = (intchar_t*)_dst, *src = (intchar_t*)_src;
276 dst->s = src->s ? strdup(src->s) : NULL;
279 void intchar_dtor(void *_elt) {
280 intchar_t *elt = (intchar_t*)_elt;
281 if (elt->s) free(elt->s);
284 UT_icd intchar_icd = {sizeof(intchar_t), NULL, intchar_copy, intchar_dtor};
289 utarray_new(intchars, &intchar_icd);
291 ic.a=1; ic.s="hello"; utarray_push_back(intchars, &ic);
292 ic.a=2; ic.s="world"; utarray_push_back(intchars, &ic);
295 while( (p=(intchar_t*)utarray_next(intchars,p))) {
296 printf("%d %s\n", p->a, (p->s ? p->s : "null"));
299 utarray_free(intchars);
303 -------------------------------------------------------------------------------
308 This table lists all the utarray operations. These are loosely based on the C++
314 [width="100%",cols="50<m,40<",grid="none",options="none"]
315 |===============================================================================
316 | utarray_new(UT_array *a, UT_icd *icd)| allocate a new array
317 | utarray_free(UT_array *a) | free an allocated array
318 | utarray_init(UT_array *a,UT_icd *icd)| init an array (non-alloc)
319 | utarray_done(UT_array *a) | dispose of an array (non-allocd)
320 | utarray_reserve(UT_array *a,int n) | ensure space available for 'n' more elements
321 | utarray_push_back(UT_array *a,void *p) | push element p onto a
322 | utarray_pop_back(UT_array *a) | pop last element from a
323 | utarray_extend_back(UT_array *a) | push empty element onto a
324 | utarray_len(UT_array *a) | get length of a
325 | utarray_eltptr(UT_array *a,int j) | get pointer of element from index
326 | utarray_eltidx(UT_array *a,void *e) | get index of element from pointer
327 | utarray_insert(UT_array *a,void *p, int j) | insert element p to index j
328 | utarray_inserta(UT_array *a,UT_array *w, int j) | insert array w into array a at index j
329 | utarray_resize(UT_array *dst,int num) | extend or shrink array to num elements
330 | utarray_concat(UT_array *dst,UT_array *src) | copy src to end of dst array
331 | utarray_erase(UT_array *a,int pos,int len) | remove len elements from a[pos]..a[pos+len-1]
332 | utarray_clear(UT_array *a) | clear all elements from a, setting its length to zero
333 | utarray_sort(UT_array *a,cmpfcn *cmp) | sort elements of a using comparison function
334 | utarray_find(UT_array *a,void *v, cmpfcn *cmp) | find element v in utarray (must be sorted)
335 | utarray_front(UT_array *a) | get first element of a
336 | utarray_next(UT_array *a,void *e) | get element of a following e (front if e is NULL)
337 | utarray_prev(UT_array *a,void *e) | get element of a before e (back if e is NULL)
338 | utarray_back(UT_array *a) | get last element of a
339 |===============================================================================
344 1. `utarray_new` and `utarray_free` are used to allocate a new array and free it,
345 while `utarray_init` and `utarray_done` can be used if the UT_array is already
346 allocated and just needs to be initialized or have its internal resources
348 2. `utarray_reserve` takes the "delta" of elements to reserve (not the total
349 desired capacity of the array-- this differs from the C++ STL "reserve" notion)
350 3. `utarray_sort` expects a comparison function having the usual `strcmp` -like
351 convention where it accepts two elements (a and b) and returns a negative
352 value if a precedes b, 0 if a and b sort equally, and positive if b precedes a.
353 This is an example of a comparison function:
355 int intsort(const void *a, const void *b) {
356 int _a = *(const int *)a;
357 int _b = *(const int *)b;
358 return (_a < _b) ? -1 : (_a > _b);
361 4. `utarray_find` uses a binary search to locate an element having a certain value
362 according to the given comparison function. The utarray must be first sorted
363 using the same comparison function. An example of using `utarray_find` with
364 a utarray of strings is included in `tests/test61.c`.
366 5. A 'pointer' to a particular element (obtained using `utarray_eltptr` or
367 `utarray_front`, `utarray_next`, `utarray_prev`, `utarray_back`) becomes invalid whenever
368 another element is inserted into the utarray. This is because the internal
369 memory management may need to `realloc` the element storage to a new address.
370 For this reason, it's usually better to refer to an element by its integer
371 'index' in code whose duration may include element insertion.
373 // vim: set nowrap syntax=asciidoc: