RetroArch
dynarray.h
Go to the documentation of this file.
1 /*
2  * A header-only typesafe dynamic array implementation for plain C,
3  * kinda like C++ std::vector. This code is compatible with C++, but should
4  * only be used with POD (plain old data) types, as it uses memcpy() etc
5  * instead of copy/move construction/assignment.
6  * It requires a new type (created with the DA_TYPEDEF(ELEMENT_TYPE, ARRAY_TYPE_NAME)
7  * macro) for each kind of element you want to put in a dynamic array; however
8  * the "functions" to manipulate the array are actually macros and the same
9  * for all element types.
10  * The array elements are accessed via dynArr.p[i] or da_get(dynArr, i)
11  * - the latter checks whether i is a valid index and asserts if not.
12  *
13  * One thing to keep in mind is that, because of using macros, the arguments to
14  * the "functions" are usually evaluated more than once, so you should avoid
15  * putting things with side effect (like function-calls with side effects or i++)
16  * into them. Notable exceptions are the value arguments (v) of da_push()
17  * and da_insert(), so it's still ok to do da_push(arr, fun_with_sideffects());
18  * or da_insert(a, 3, x++);
19  *
20  * The function-like da_* macros are short aliases of dg_dynarr_* macros.
21  * If the short names clash with anything in your code or other headers
22  * you are using, you can, before #including this header, do
23  * #define DG_DYNARR_NO_SHORTNAMES
24  * and use the long dg_dynarr_* forms of the macros instead.
25  *
26  * Using this library in your project:
27  * Put this file somewhere in your project.
28  * In *one* of your .c/.cpp files, do
29  * #define DG_DYNARR_IMPLEMENTATION
30  * #include "DG_dynarr.h"
31  * to create the implementation of this library in that file.
32  * You can just #include "DG_dynarr.h" (without the #define) in other source
33  * files to use it there.
34  *
35  * See below this comment block for a usage example.
36  *
37  * You can #define your own allocators, assertion and the amount of runtime
38  * checking of indexes, see CONFIGURATION section in the code for more information.
39  *
40  *
41  * This is heavily inspired by Sean Barrett's stretchy_buffer.h
42  * ( see: https://github.com/nothings/stb/blob/master/stretchy_buffer.h )
43  * However I wanted to have a struct that holds the array pointer and the length
44  * and capacity, so that struct always remains at the same address while the
45  * array memory might be reallocated.
46  * I can live with arr.p[i] instead of arr[i], but I like how he managed to use
47  * macros to create an API that doesn't force the user to specify the stored
48  * type over and over again, so I stole some of his tricks :-)
49  *
50  * This has been tested with GCC 4.8 and clang 3.8 (-std=gnu89, -std=c99 and as C++;
51  * -std=c89 works if you convert the C++-style comments to C comments) and
52  * Microsoft Visual Studio 6 and 2010 (32bit) and 2013 (32bit and 64bit).
53  * I guess it works with all (recentish) C++ compilers and C compilers supporting
54  * C99 or even C89 + C++ comments (otherwise converting the comments should help).
55  *
56  * (C) 2016 Daniel Gibson
57  *
58  * LICENSE
59  * This software is dual-licensed to the public domain and under the following
60  * license: you are granted a perpetual, irrevocable license to copy, modify,
61  * publish, and distribute this file as you see fit.
62  * No warranty implied; use at your own risk.
63  *
64  * So you can do whatever you want with this code, including copying it
65  * (or parts of it) into your own source.
66  * No need to mention me or this "license" in your code or docs, even though
67  * it would be appreciated, of course.
68  */
69 #if 0 /* Usage Example: */
70  #define DG_DYNARR_IMPLEMENTATION /* this define is only needed in *one* .c/.cpp file! */
71  #include "DG_dynarr.h"
72 
73  DA_TYPEDEF(int, MyIntArrType); /* creates MyIntArrType - a dynamic array for ints */
74 
75  void printIntArr(MyIntArrType* arr, const char* name)
76  {
77  /* note that arr is a pointer here, so use *arr in the da_*() functions. */
78  printf("%s = {", name);
79  if(da_count(*arr) > 0)
80  printf(" %d", arr->p[0]);
81  for(int i=1; i<da_count(*arr); ++i)
82  printf(", %d", arr->p[i]);
83  printf(" }\n");
84  }
85 
86  void myFunction()
87  {
88  MyIntArrType a1 = {0};
89  /* make sure to zero out the struct
90  * instead of = {0}; you could also call da_init(a1);
91  */
92 
93  da_push(a1, 42);
94  assert(da_count(a1) == 1 && a1.p[0] == 42);
95 
96  int* addedElements = da_addn_uninit(a1, 3);
97  assert(da_count(a1) == 4);
98  for(size_t i=0; i<3; ++i)
99  addedElements[i] = i+5;
100 
101  printIntArr(&a1, "a1"); /* "a1 = { 42, 5, 6, 7 }" */
102 
103  MyIntArrType a2;
104  da_init(a2);
105 
106  da_addn(a2, a1.p, da_count(a1)); /* copy all elements from a1 to a2 */
107  assert(da_count(a2) == 4);
108 
109  da_insert(a2, 1, 11);
110  printIntArr(&a2, "a2"); /* "a2 = { 42, 11, 5, 6, 7 }" */
111 
112  da_delete(a2, 2);
113  printIntArr(&a2, "a2"); /* "a2 = { 42, 11, 6, 7 }" */
114 
115  da_deletefast(a2, 0);
116  printIntArr(&a2, "a2"); /* "a2 = { 7, 11, 6 }" */
117 
118  da_push(a1, 3);
119  printIntArr(&a1, "a1"); /* "a1 = { 42, 5, 6, 7, 3 }" */
120 
121  int x=da_pop(a1);
122  printf("x = %d\n", x); /* "x = 3" */
123  printIntArr(&a1, "a1"); /* "a1 = { 42, 5, 6, 7 }" */
124 
125  da_free(a1); /* make sure not to leak memory! */
126  da_free(a2);
127  }
128 #endif /* 0 (usage example) */
129 
130 #ifndef DG__DYNARR_H
131 #define DG__DYNARR_H
132 
133 /* ######### CONFIGURATION #########
134  *
135  * following: some #defines that you can tweak to your liking
136  *
137  * you can reduce some overhead by defining DG_DYNARR_INDEX_CHECK_LEVEL to 2, 1 or 0
138  */
139 #ifndef DG_DYNARR_INDEX_CHECK_LEVEL
140 
141  /* 0: (almost) no index checking
142  * 1: macros "returning" something return a.p[0] or NULL if the index was invalid
143  * 2: assertions in all macros taking indexes that make sure they're valid
144  * 3: 1 and 2
145  */
146  #define DG_DYNARR_INDEX_CHECK_LEVEL 3
147 
148 #endif /* DG_DYNARR_INDEX_CHECK_LEVEL */
149 
150 /* you can #define your own DG_DYNARR_ASSERT(condition, msgstring)
151  * that will be used for all assertions in this code.
152  */
153 #ifndef DG_DYNARR_ASSERT
154  #include <assert.h>
155  #define DG_DYNARR_ASSERT(cond, msg) assert((cond) && msg)
156 #endif
157 
158 /* you can #define DG_DYNARR_OUT_OF_MEMORY to some code that will be executed
159  * if allocating memory fails
160  * it's needed only before the #define DG_DYNARR_IMPLEMENTATION #include of
161  * this header, so the following is here only for reference and commented out
162  */
163 /*
164  #ifndef DG_DYNARR_OUT_OF_MEMORY
165  #define DG_DYNARR_OUT_OF_MEMORY DG_DYNARR_ASSERT(0, "Out of Memory!");
166  #endif
167 */
168 
169 /* By default, C's malloc(), realloc() and free() is used to allocate/free heap memory
170  * (see beginning of "#ifdef DG_DYNARR_IMPLEMENTATION" block below).
171  * You can #define DG_DYNARR_MALLOC, DG_DYNARR_REALLOC and DG_DYNARR_FREE yourself
172  * to provide alternative implementations like Win32 Heap(Re)Alloc/HeapFree
173  * it's needed only before the #define DG_DYNARR_IMPLEMENTATION #include of
174  * this header, so the following is here only for reference and commented out
175  */
176 /*
177  #define DG_DYNARR_MALLOC(elemSize, numElems) malloc(elemSize*numElems)
178 
179  // oldNumElems is not used for C's realloc, but maybe you need it for
180  // your allocator to copy the old elements over
181  #define DG_DYNARR_REALLOC(ptr, elemSize, oldNumElems, newCapacity) \
182  realloc(ptr, elemSize*newCapacity);
183 
184  #define DG_DYNARR_FREE(ptr) free(ptr)
185 */
186 
187 /* if you want to prepend something to the non inline (DG_DYNARR_INLINE) functions,
188  * like "__declspec(dllexport)" or whatever, #define DG_DYNARR_DEF
189  */
190 #ifndef DG_DYNARR_DEF
191  /* by defaults it's empty. */
192  #define DG_DYNARR_DEF
193 #endif
194 
195 /* some functions are inline, in case your compiler doesn't like "static inline"
196  * but wants "__inline__" or something instead, #define DG_DYNARR_INLINE accordingly.
197  */
198 #ifndef DG_DYNARR_INLINE
199  #define DG_DYNARR_INLINE static INLINE
200 #endif
201 
202 /* ############### Short da_* aliases for the long names ############### */
203 
204 #ifndef DG_DYNARR_NO_SHORTNAMES
205 
206 /* this macro is used to create an array type (struct) for elements of TYPE
207  * use like DA_TYPEDEF(int, MyIntArrType); MyIntArrType ia = {0}; da_push(ia, 42); ...
208  */
209 #define DA_TYPEDEF(TYPE, NewArrayTypeName) \
210  DG_DYNARR_TYPEDEF(TYPE, NewArrayTypeName)
211 
212 /* makes sure the array is initialized and can be used.
213  * either do YourArray arr = {0}; or YourArray arr; da_init(arr);
214  */
215 #define da_init(a) \
216  dg_dynarr_init(a)
217 
218 /* This allows you to provide an external buffer that'll be used as long as it's big enough
219  * once you add more elements than buf can hold, fresh memory will be allocated on the heap
220  * Use like:
221  * DA_TYPEDEF(double, MyDoubleArrType);
222  * MyDoubleArrType arr;
223  * double buf[8];
224  * dg_dynarr_init_external(arr, buf, 8);
225  * dg_dynarr_push(arr, 1.23);
226  * ...
227  */
228 #define da_init_external(a, buf, buf_cap) \
229  dg_dynarr_init_external(a, buf, buf_cap)
230 
231 /* use this to free the memory allocated by dg_dynarr once you don't need the array anymore
232  * Note: it is safe to add new elements to the array after da_free()
233  * it will allocate new memory, just like it would directly after da_init()
234  */
235 #define da_free(a) \
236  dg_dynarr_free(a)
237 
238 
239 /* add an element to the array (appended at the end) */
240 #define da_push(a, v) \
241  dg_dynarr_push(a, v)
242 
243 /* add an element to the array (appended at the end)
244  * does the same as push, just for consistency with addn (like insert and insertn)
245  */
246 #define da_add(a, v) \
247  dg_dynarr_add(a, v)
248 
249 /* append n elements to a and initialize them from array vals, doesn't return anything
250  * ! vals (and all other args) are evaluated multiple times !
251  */
252 #define da_addn(a, vals, n) \
253  dg_dynarr_addn(a, vals, n)
254 
255 /* add n elements to the end of the array and zeroes them with memset()
256  * returns pointer to first added element, NULL if out of memory (array is empty then)
257  */
258 #define da_addn_zeroed(a, n) \
259  dg_dynarr_addn_zeroed(a, n)
260 
261 /* add n elements to the end of the array, will remain uninitialized
262  * returns pointer to first added element, NULL if out of memory (array is empty then)
263  */
264 #define da_addn_uninit(a, n) \
265  dg_dynarr_addn_uninit(a, n)
266 
267 
268 /* insert a single value v at index idx */
269 #define da_insert(a, idx, v) \
270  dg_dynarr_insert(a, idx, v)
271 
272 /* insert n elements into a at idx, initialize them from array vals
273  * doesn't return anything
274  * ! vals (and all other args) is evaluated multiple times !
275  */
276 #define da_insertn(a, idx, vals, n) \
277  dg_dynarr_insertn(a, idx, vals, n)
278 
279 /* insert n elements into a at idx and zeroe them with memset()
280  * returns pointer to first inserted element or NULL if out of memory
281  */
282 #define da_insertn_zeroed(a, idx, n) \
283  dg_dynarr_insertn_zeroed(a, idx, n)
284 
285 /* insert n uninitialized elements into a at idx;
286  * returns pointer to first inserted element or NULL if out of memory
287  */
288 #define da_insertn_uninit(a, idx, n) \
289  dg_dynarr_insertn_uninit(a, idx, n)
290 
291 /* set a single value v at index idx - like "a.p[idx] = v;" but with checks (unless disabled) */
292 #define da_set(a, idx, v) \
293  dg_dynarr_set(a, idx, v)
294 
295 /* overwrite n elements of a, starting at idx, with values from array vals
296  * doesn't return anything
297  * ! vals (and all other args) is evaluated multiple times !
298  */
299 #define da_setn(a, idx, vals, n) \
300  dg_dynarr_setn(a, idx, vals, n)
301 
302 /* delete the element at idx, moving all following elements (=> keeps order) */
303 #define da_delete(a, idx) \
304  dg_dynarr_delete(a, idx)
305 
306 /* delete n elements starting at idx, moving all following elements (=> keeps order) */
307 #define da_deleten(a, idx, n) \
308  dg_dynarr_deleten(a, idx, n)
309 
310 /* delete the element at idx, move the last element there (=> doesn't keep order) */
311 #define da_deletefast(a, idx) \
312  dg_dynarr_deletefast(a, idx)
313 
314 /* delete n elements starting at idx, move the last n elements there (=> doesn't keep order) */
315 #define da_deletenfast(a, idx, n) \
316  dg_dynarr_deletenfast(a, idx, n)
317 
318 /* removes all elements from the array, but does not free the buffer
319  * (if you want to free the buffer too, just use da_free())
320  */
321 #define da_clear(a) \
322  dg_dynarr_clear(a)
323 
324 /* sets the logical number of elements in the array
325  * if cnt > dg_dynarr_count(a), the logical count will be increased accordingly
326  * and the new elements will be uninitialized
327  */
328 #define da_setcount(a, cnt) \
329  dg_dynarr_setcount(a, cnt)
330 
331 /* make sure the array can store cap elements without reallocating
332  * logical count remains unchanged
333  */
334 #define da_reserve(a, cap) \
335  dg_dynarr_reserve(a, cap)
336 
337 /* this makes sure a only uses as much memory as for its elements
338  * => maybe useful if a used to contain a huge amount of elements,
339  * but you deleted most of them and want to free some memory
340  * Note however that this implies an allocation and copying the remaining
341  * elements, so only do this if it frees enough memory to be worthwhile!
342  */
343 #define da_shrink_to_fit(a) \
344  dg_dynarr_shrink_to_fit(a)
345 
346 
347 /* removes and returns the last element of the array */
348 #define da_pop(a) \
349  dg_dynarr_pop(a)
350 
351 /* returns the last element of the array */
352 #define da_last(a) \
353  dg_dynarr_last(a)
354 
355 /* returns the pointer *to* the last element of the array
356  * (in contrast to dg_dynarr_end() which returns a pointer *after* the last element)
357  * returns NULL if array is empty
358  */
359 #define da_lastptr(a) \
360  dg_dynarr_lastptr(a)
361 
362 /* get element at index idx (like a.p[idx]), but with checks
363  * (unless you disabled them with #define DG_DYNARR_INDEX_CHECK_LEVEL 0)
364  */
365 #define da_get(a, idx) \
366  dg_dynarr_get(a,idx)
367 
368 /* get pointer to element at index idx (like &a.p[idx]), but with checks
369  * and it returns NULL if idx is invalid
370  */
371 #define da_getptr(a, idx) \
372  dg_dynarr_getptr(a, idx)
373 
374 /* returns a pointer to the first element of the array
375  * (together with dg_dynarr_end() you can do C++-style iterating)
376  */
377 #define da_begin(a) \
378  dg_dynarr_begin(a)
379 
380 /* returns a pointer to the past-the-end element of the array
381  * Allows C++-style iterating, in case you're into that kind of thing:
382  * for(T *it=da_begin(a), *end=da_end(a); it!=end; ++it) foo(*it);
383  * (see da_lastptr() to get a pointer *to* the last element)
384  */
385 #define da_end(a) \
386  dg_dynarr_end(a)
387 
388 
389 /* returns (logical) number of elements currently in the array */
390 #define da_count(a) \
391  dg_dynarr_count(a)
392 
393 /* get the current reserved capacity of the array */
394 #define da_capacity(a) \
395  dg_dynarr_capacity(a)
396 
397 /* returns 1 if the array is empty, else 0 */
398 #define da_empty(a) \
399  dg_dynarr_empty(a)
400 
401 /* returns 1 if the last (re)allocation when inserting failed (Out Of Memory)
402  * or if the array has never allocated any memory yet, else 0
403  * deleting the contents when growing fails instead of keeping old may seem
404  * a bit uncool, but it's simple and OOM should rarely happen on modern systems
405  * anyway - after all you need to deplete both RAM and swap/pagefile.sys
406  */
407 #define da_oom(a) \
408  dg_dynarr_oom(a)
409 
410 /* sort a using the given qsort()-comparator cmp
411  * (just a slim wrapper around qsort())
412  */
413 #define da_sort(a, cmp) \
414  dg_dynarr_sort(a, cmp)
415 
416 #endif /* DG_DYNARR_NO_SHORTNAMES */
417 
418 /* ######### Implementation of the actual macros (using the long names) ##########
419  *
420  * use like DG_DYNARR_TYPEDEF(int, MyIntArrType); MyIntArrType ia = {0}; dg_dynarr_push(ia, 42); ...
421  */
422 #define DG_DYNARR_TYPEDEF(TYPE, NewArrayTypeName) \
423  typedef struct { TYPE* p; dg__dynarr_md md; } NewArrayTypeName;
424 
425 /* makes sure the array is initialized and can be used.
426  * either do YourArray arr = {0}; or YourArray arr; dg_dynarr_init(arr);
427  */
428 #define dg_dynarr_init(a) \
429  dg__dynarr_init((void**)&(a).p, &(a).md, NULL, 0)
430 
431 /* this allows you to provide an external buffer that'll be used as long as it's big enough
432  * once you add more elements than buf can hold, fresh memory will be allocated on the heap
433  */
434 #define dg_dynarr_init_external(a, buf, buf_cap) \
435  dg__dynarr_init((void**)&(a).p, &(a).md, (buf), (buf_cap))
436 
437 /* use this to free the memory allocated by dg_dynarr
438  * Note: it is safe to add new elements to the array after dg_dynarr_free()
439  * it will allocate new memory, just like it would directly after dg_dynarr_init()
440  */
441 #define dg_dynarr_free(a) \
442  dg__dynarr_free((void**)&(a).p, &(a).md)
443 
444 
445 /* add an element to the array (appended at the end) */
446 #define dg_dynarr_push(a, v) \
447  (dg__dynarr_maybegrowadd(dg__dynarr_unp(a), 1) ? (((a).p[(a).md.cnt++] = (v)),0) : 0)
448 
449 /* add an element to the array (appended at the end)
450  * does the same as push, just for consistency with addn (like insert and insertn)
451  */
452 #define dg_dynarr_add(a, v) \
453  dg_dynarr_push((a), (v))
454 
455 /* append n elements to a and initialize them from array vals, doesn't return anything
456  * ! vals (and all other args) are evaluated multiple times !
457  */
458 #define dg_dynarr_addn(a, vals, n) do { \
459  DG_DYNARR_ASSERT((vals)!=NULL, "Don't pass NULL als vals to dg_dynarr_addn!"); \
460  if((vals)!=NULL && dg__dynarr_add(dg__dynarr_unp(a), n, 0)) { \
461  size_t i_=(a).md.cnt-(n), v_=0; \
462  while(i_<(a).md.cnt) (a).p[i_++]=(vals)[v_++]; \
463  } } DG__DYNARR_WHILE0
464 
465 /* add n elements to the end of the array and zeroe them with memset()
466  * returns pointer to first added element, NULL if out of memory (array is empty then)
467  */
468 #define dg_dynarr_addn_zeroed(a, n) \
469  (dg__dynarr_add(dg__dynarr_unp(a), (n), 1) ? &(a).p[(a).md.cnt-(size_t)(n)] : NULL)
470 
471 /* add n elements to the end of the array, which are uninitialized
472  * returns pointer to first added element, NULL if out of memory (array is empty then)
473  */
474 #define dg_dynarr_addn_uninit(a, n) \
475  (dg__dynarr_add(dg__dynarr_unp(a), (n), 0) ? &(a).p[(a).md.cnt-(size_t)(n)] : NULL)
476 
477 /* insert a single value v at index idx */
478 #define dg_dynarr_insert(a, idx, v) \
479  (dg__dynarr_checkidxle((a),(idx)), \
480  dg__dynarr_insert(dg__dynarr_unp(a), (idx), 1, 0), \
481  (a).p[dg__dynarr_idx((a).md, (idx))] = (v))
482 
483 /* insert n elements into a at idx, initialize them from array vals
484  * doesn't return anything
485  * ! vals (and all other args) is evaluated multiple times !
486  */
487 #define dg_dynarr_insertn(a, idx, vals, n) do { \
488  DG_DYNARR_ASSERT((vals)!=NULL, "Don't pass NULL as vals to dg_dynarr_insertn!"); \
489  dg__dynarr_checkidxle((a),(idx)); \
490  if((vals)!=NULL && dg__dynarr_insert(dg__dynarr_unp(a), (idx), (n), 0)){ \
491  size_t i_=(idx), v_=0, e_=(idx)+(n); \
492  while(i_ < e_) (a).p[i_++] = (vals)[v_++]; \
493  }} DG__DYNARR_WHILE0
494 
495 /* insert n elements into a at idx and zeroe them with memset()
496  * returns pointer to first inserted element or NULL if out of memory
497  */
498 #define dg_dynarr_insertn_zeroed(a, idx, n) \
499  (dg__dynarr_checkidxle((a),(idx)), \
500  dg__dynarr_insert(dg__dynarr_unp(a), (idx), (n), 1) \
501  ? &(a).p[dg__dynarr_idx((a).md, (idx))] : NULL)
502 
503 /* insert n uninitialized elements into a at idx;
504  * returns pointer to first inserted element or NULL if out of memory
505  */
506 #define dg_dynarr_insertn_uninit(a, idx, n) \
507  (dg__dynarr_checkidxle((a),(idx)), \
508  dg__dynarr_insert(dg__dynarr_unp(a), idx, n, 0) \
509  ? &(a).p[dg__dynarr_idx((a).md, (idx))] : NULL)
510 
511 /* set a single value v at index idx - like "a.p[idx] = v;" but with checks (unless disabled) */
512 #define dg_dynarr_set(a, idx, v) \
513  (dg__dynarr_checkidx((a),(idx)), \
514  (a).p[dg__dynarr_idx((a).md, (idx))] = (v))
515 
516 /* overwrite n elements of a, starting at idx, with values from array vals
517  * doesn't return anything
518  * ! vals (and all other args) is evaluated multiple times !
519  */
520 #define dg_dynarr_setn(a, idx, vals, n) do { \
521  DG_DYNARR_ASSERT((vals)!=NULL, "Don't pass NULL as vals to dg_dynarr_setn!"); \
522  size_t idx_=(idx); size_t end_=idx_+(size_t)n; \
523  dg__dynarr_checkidx((a),idx_); dg__dynarr_checkidx((a),end_-1); \
524  if((vals)!=NULL && idx_ < (a).md.cnt && end_ <= (a).md.cnt) { \
525  size_t v_=0; \
526  while(idx_ < end_) (a).p[idx_++] = (vals)[v_++]; \
527  }} DG__DYNARR_WHILE0
528 
529 /* delete the element at idx, moving all following elements (=> keeps order) */
530 #define dg_dynarr_delete(a, idx) \
531  (dg__dynarr_checkidx((a),(idx)), dg__dynarr_delete(dg__dynarr_unp(a), (idx), 1))
532 
533 /* delete n elements starting at idx, moving all following elements (=> keeps order) */
534 #define dg_dynarr_deleten(a, idx, n) \
535  (dg__dynarr_checkidx((a),(idx)), dg__dynarr_delete(dg__dynarr_unp(a), (idx), (n)))
536  /* TODO: check whether idx+n < count? */
537 
538 /* delete the element at idx, move the last element there (=> doesn't keep order) */
539 #define dg_dynarr_deletefast(a, idx) \
540  (dg__dynarr_checkidx((a),(idx)), dg__dynarr_deletefast(dg__dynarr_unp(a), (idx), 1))
541 
542 /* delete n elements starting at idx, move the last n elements there (=> doesn't keep order) */
543 #define dg_dynarr_deletenfast(a, idx, n) \
544  (dg__dynarr_checkidx((a),(idx)), dg__dynarr_deletefast(dg__dynarr_unp(a), idx, n))
545  /* TODO: check whether idx+n < count? */
546 
547 /* removes all elements from the array, but does not free the buffer
548  * (if you want to free the buffer too, just use dg_dynarr_free())
549  */
550 #define dg_dynarr_clear(a) \
551  ((a).md.cnt=0)
552 
553 /* sets the logical number of elements in the array
554  * if cnt > dg_dynarr_count(a), the logical count will be increased accordingly
555  * and the new elements will be uninitialized
556  */
557 #define dg_dynarr_setcount(a, n) \
558  (dg__dynarr_maybegrow(dg__dynarr_unp(a), (n)) ? ((a).md.cnt = (n)) : 0)
559 
560 /* make sure the array can store cap elements without reallocating
561  * logical count remains unchanged
562  */
563 #define dg_dynarr_reserve(a, cap) \
564  dg__dynarr_maybegrow(dg__dynarr_unp(a), (cap))
565 
566 /* this makes sure a only uses as much memory as for its elements
567  * => maybe useful if a used to contain a huge amount of elements,
568  * but you deleted most of them and want to free some memory
569  * Note however that this implies an allocation and copying the remaining
570  * elements, so only do this if it frees enough memory to be worthwhile!
571  */
572 #define dg_dynarr_shrink_to_fit(a) \
573  dg__dynarr_shrink_to_fit(dg__dynarr_unp(a))
574 
575 #if (DG_DYNARR_INDEX_CHECK_LEVEL == 1) || (DG_DYNARR_INDEX_CHECK_LEVEL == 3)
576 
577  /* removes and returns the last element of the array */
578  #define dg_dynarr_pop(a) \
579  (dg__dynarr_check_notempty((a), "Don't pop an empty array!"), \
580  (a).p[((a).md.cnt > 0) ? (--(a).md.cnt) : 0])
581 
582  /* returns the last element of the array */
583  #define dg_dynarr_last(a) \
584  (dg__dynarr_check_notempty((a), "Don't call da_last() on an empty array!"), \
585  (a).p[((a).md.cnt > 0) ? ((a).md.cnt-1) : 0])
586 
587 #elif (DG_DYNARR_INDEX_CHECK_LEVEL == 0) || (DG_DYNARR_INDEX_CHECK_LEVEL == 2)
588 
589  /* removes and returns the last element of the array */
590  #define dg_dynarr_pop(a) \
591  (dg__dynarr_check_notempty((a), "Don't pop an empty array!"), \
592  (a).p[--(a).md.cnt])
593 
594  /* returns the last element of the array */
595  #define dg_dynarr_last(a) \
596  (dg__dynarr_check_notempty((a), "Don't call da_last() on an empty array!"), \
597  (a).p[(a).md.cnt-1])
598 
599 #else /* invalid DG_DYNARR_INDEX_CHECK_LEVEL */
600  #error Invalid index check level DG_DYNARR_INDEX_CHECK_LEVEL (must be 0-3) !
601 #endif /* DG_DYNARR_INDEX_CHECK_LEVEL */
602 
603 /* returns the pointer *to* the last element of the array
604  * (in contrast to dg_dynarr_end() which returns a pointer *after* the last element)
605  * returns NULL if array is empty
606  */
607 #define dg_dynarr_lastptr(a) \
608  (((a).md.cnt > 0) ? ((a).p + (a).md.cnt - 1) : NULL)
609 
610 /* get element at index idx (like a.p[idx]), but with checks
611  * (unless you disabled them with #define DG_DYNARR_INDEX_CHECK_LEVEL 0)
612  */
613 #define dg_dynarr_get(a, idx) \
614  (dg__dynarr_checkidx((a),(idx)), (a).p[dg__dynarr_idx((a).md, (idx))])
615 
616 /* get pointer to element at index idx (like &a.p[idx]), but with checks
617  * (unless you disabled them with #define DG_DYNARR_INDEX_CHECK_LEVEL 0)
618  * if index-checks are disabled, it returns NULL on invalid index (else it asserts() before returning)
619  */
620 #define dg_dynarr_getptr(a, idx) \
621  (dg__dynarr_checkidx((a),(idx)), \
622  ((size_t)(idx) < (a).md.cnt) ? ((a).p+(size_t)(idx)) : NULL)
623 
624 /* returns a pointer to the first element of the array
625  * (together with dg_dynarr_end() you can do C++-style iterating)
626  */
627 #define dg_dynarr_begin(a) \
628  ((a).p)
629 
630 /* returns a pointer to the past-the-end element of the array
631  * Allows C++-style iterating, in case you're into that kind of thing:
632  * for(T *it=dg_dynarr_begin(a), *end=dg_dynarr_end(a); it!=end; ++it) foo(*it);
633  * (see dg_dynarr_lastptr() to get a pointer *to* the last element)
634  */
635 #define dg_dynarr_end(a) \
636  ((a).p + (a).md.cnt)
637 
638 /* returns (logical) number of elements currently in the array */
639 #define dg_dynarr_count(a) \
640  ((a).md.cnt)
641 
642 /* get the current reserved capacity of the array */
643 #define dg_dynarr_capacity(a) \
644  ((a).md.cap & DG__DYNARR_SIZE_T_ALL_BUT_MSB)
645 
646 /* returns 1 if the array is empty, else 0 */
647 #define dg_dynarr_empty(a) \
648  ((a).md.cnt == 0)
649 
650 /* returns 1 if the last (re)allocation when inserting failed (Out Of Memory)
651  * or if the array has never allocated any memory yet, else 0
652  * deleting the contents when growing fails instead of keeping old may seem
653  * a bit uncool, but it's simple and OOM should rarely happen on modern systems
654  * anyway - after all you need to deplete both RAM and swap/pagefile.sys
655  * or deplete the address space, which /might/ happen with 32bit applications
656  * but probably not with 64bit (at least in the foreseeable future)
657  */
658 #define dg_dynarr_oom(a) \
659  ((a).md.cap == 0)
660 
661 /* sort a using the given qsort()-comparator cmp
662  * (just a slim wrapper around qsort())
663  */
664 #define dg_dynarr_sort(a, cmp) \
665  qsort((a).p, (a).md.cnt, sizeof((a).p[0]), (cmp))
666 
667 /* ######### Implementation-Details that are not part of the API ########## */
668 
669 #include <stdlib.h> /* size_t, malloc(), free(), realloc() */
670 #include <string.h> /* memset(), memcpy(), memmove() */
671 
672 #ifdef __cplusplus
673 extern "C" {
674 #endif
675 
676 typedef struct {
677  size_t cnt; /* logical number of elements */
678  size_t cap; /* cap & DG__DYNARR_SIZE_T_ALL_BUT_MSB is actual capacity (in elements, *not* bytes!) */
679  /* if(cap & DG__DYNARR_SIZE_T_MSB) the current memory is not allocated by dg_dynarr,
680  * but was set with dg_dynarr_init_external()
681  * that's handy to give an array a base-element storage on the stack, for example
682  * TODO: alternatively, we could introduce a flag field to this struct and use that,
683  * so we don't have to calculate & everytime cap is needed
684  */
685 } dg__dynarr_md;
686 
687 /* I used to have the following in an enum, but MSVC assumes enums are always 32bit ints */
688 static const size_t DG__DYNARR_SIZE_T_MSB = ((size_t)1) << (sizeof(size_t)*8 - 1);
689 static const size_t DG__DYNARR_SIZE_T_ALL_BUT_MSB = (((size_t)1) << (sizeof(size_t)*8 - 1))-1;
690 
691 /* "unpack" the elements of an array struct for use with helper functions
692  * (to void** arr, dg__dynarr_md* md, size_t itemsize)
693  */
694 #define dg__dynarr_unp(a) \
695  (void**)&(a).p, &(a).md, sizeof((a).p[0])
696 
697 /* MSVC warns about "conditional expression is constant" when using the
698  * do { ... } while(0) idiom in macros..
699  */
700 #ifdef _MSC_VER
701  #if _MSC_VER >= 1400 // MSVC 2005 and newer
702  /* people claim MSVC 2005 and newer support __pragma, even though it's only documented
703  * for 2008+ (https://msdn.microsoft.com/en-us/library/d9x1s805%28v=vs.90%29.aspx)
704  * the following workaround is based on
705  * http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/
706  */
707  #define DG__DYNARR_WHILE0 \
708  __pragma(warning(push)) \
709  __pragma(warning(disable:4127)) \
710  while(0) \
711  __pragma(warning(pop))
712  #else /* older MSVC versions don't support __pragma - I heard this helps for them */
713  #define DG__DYNARR_WHILE0 while(0,0)
714  #endif
715 
716 #else /* other compilers */
717 
718  #define DG__DYNARR_WHILE0 while(0)
719 
720 #endif /* _MSC_VER */
721 
722 #if (DG_DYNARR_INDEX_CHECK_LEVEL == 2) || (DG_DYNARR_INDEX_CHECK_LEVEL == 3)
723 
724  #define dg__dynarr_checkidx(a,i) \
725  DG_DYNARR_ASSERT((size_t)i < a.md.cnt, "index out of bounds!")
726 
727  /* special case for insert operations: == cnt is also ok, insert will append then */
728  #define dg__dynarr_checkidxle(a,i) \
729  DG_DYNARR_ASSERT((size_t)i <= a.md.cnt, "index out of bounds!")
730 
731  #define dg__dynarr_check_notempty(a, msg) \
732  DG_DYNARR_ASSERT(a.md.cnt > 0, msg)
733 
734 #elif (DG_DYNARR_INDEX_CHECK_LEVEL == 0) || (DG_DYNARR_INDEX_CHECK_LEVEL == 1)
735 
736  /* no assertions that check if index is valid */
737  #define dg__dynarr_checkidx(a,i) (void)0
738  #define dg__dynarr_checkidxle(a,i) (void)0
739 
740  #define dg__dynarr_check_notempty(a, msg) (void)0
741 
742 #else /* invalid DG_DYNARR_INDEX_CHECK_LEVEL */
743  #error Invalid index check level DG_DYNARR_INDEX_CHECK_LEVEL (must be 0-3) !
744 #endif /* DG_DYNARR_INDEX_CHECK_LEVEL */
745 
746 #if (DG_DYNARR_INDEX_CHECK_LEVEL == 1) || (DG_DYNARR_INDEX_CHECK_LEVEL == 3)
747 
748  /* the given index, if valid, else 0 */
749  #define dg__dynarr_idx(md,i) \
750  (((size_t)(i) < md.cnt) ? (size_t)(i) : 0)
751 
752 #elif (DG_DYNARR_INDEX_CHECK_LEVEL == 0) || (DG_DYNARR_INDEX_CHECK_LEVEL == 2)
753 
754  /* don't check and default to 0 if invalid, but just use the given value */
755  #define dg__dynarr_idx(md,i) (size_t)(i)
756 
757 #else /* invalid DG_DYNARR_INDEX_CHECK_LEVEL */
758  #error Invalid index check level DG_DYNARR_INDEX_CHECK_LEVEL (must be 0-3) !
759 #endif /* DG_DYNARR_INDEX_CHECK_LEVEL */
760 
761 /* the functions allocating/freeing memory are not implemented inline, but
762  * in the #ifdef DG_DYNARR_IMPLEMENTATION section
763  * one reason is that dg__dynarr_grow has the most code in it, the other is
764  * that windows has weird per-dll heaps so free() or realloc() should be
765  * called from code in the same dll that allocated the memory - these kind
766  * of wrapper functions that end up compiled into the exe or *one* dll
767  * (instead of inline functions compiled into everything) should ensure that.
768  */
769 
770 DG_DYNARR_DEF void
772 
773 DG_DYNARR_DEF void
774 dg__dynarr_shrink_to_fit(void** arr, dg__dynarr_md* md, size_t itemsize);
775 
776 /* grow array to have enough space for at least min_needed elements
777  * if it fails (OOM), the array will be deleted, a.p will be NULL, a.md.cap and a.md.cnt will be 0
778  * and the functions returns 0; else (on success) it returns 1
779  */
780 DG_DYNARR_DEF int
781 dg__dynarr_grow(void** arr, dg__dynarr_md* md, size_t itemsize, size_t min_needed);
782 
783 /* the following functions are implemented inline, because they're quite short
784  * and mosty implemented in functions so the macros don't get too ugly
785  */
786 
787 DG_DYNARR_INLINE void
788 dg__dynarr_init(void** p, dg__dynarr_md* md, void* buf, size_t buf_cap)
789 {
790  *p = buf;
791  md->cnt = 0;
792  if(buf == NULL) md->cap = 0;
793  else md->cap = (DG__DYNARR_SIZE_T_MSB | buf_cap);
794 }
795 
797 dg__dynarr_maybegrow(void** arr, dg__dynarr_md* md, size_t itemsize, size_t min_needed)
798 {
799  if((md->cap & DG__DYNARR_SIZE_T_ALL_BUT_MSB) >= min_needed) return 1;
800  else return dg__dynarr_grow(arr, md, itemsize, min_needed);
801 }
802 
804 dg__dynarr_maybegrowadd(void** arr, dg__dynarr_md* md, size_t itemsize, size_t num_add)
805 {
806  size_t min_needed = md->cnt+num_add;
807  if((md->cap & DG__DYNARR_SIZE_T_ALL_BUT_MSB) >= min_needed) return 1;
808  else return dg__dynarr_grow(arr, md, itemsize, min_needed);
809 }
810 
812 dg__dynarr_insert(void** arr, dg__dynarr_md* md, size_t itemsize, size_t idx, size_t n, int init0)
813 {
814  /* allow idx == md->cnt to append */
815  size_t oldCount = md->cnt;
816  size_t newCount = oldCount+n;
817  if(idx <= oldCount && dg__dynarr_maybegrow(arr, md, itemsize, newCount))
818  {
819  unsigned char* p = (unsigned char*)*arr; /* *arr might have changed in dg__dynarr_grow()! */
820  /* move all existing items after a[idx] to a[idx+n] */
821  if(idx < oldCount) memmove(p+(idx+n)*itemsize, p+idx*itemsize, itemsize*(oldCount - idx));
822 
823  /* if the memory is supposed to be zeroed, do that */
824  if(init0) memset(p+idx*itemsize, 0, n*itemsize);
825 
826  md->cnt = newCount;
827  return 1;
828  }
829  return 0;
830 }
831 
833 dg__dynarr_add(void** arr, dg__dynarr_md* md, size_t itemsize, size_t n, int init0)
834 {
835  size_t cnt = md->cnt;
836  if(dg__dynarr_maybegrow(arr, md, itemsize, cnt+n))
837  {
838  unsigned char* p = (unsigned char*)*arr; /* *arr might have changed in dg__dynarr_grow()! */
839  /* if the memory is supposed to be zeroed, do that */
840  if(init0) memset(p+cnt*itemsize, 0, n*itemsize);
841 
842  md->cnt += n;
843  return 1;
844  }
845  return 0;
846 }
847 
848 DG_DYNARR_INLINE void
849 dg__dynarr_delete(void** arr, dg__dynarr_md* md, size_t itemsize, size_t idx, size_t n)
850 {
851  size_t cnt = md->cnt;
852  if(idx < cnt)
853  {
854  if(idx+n >= cnt) md->cnt = idx; /* removing last element(s) => just reduce count */
855  else
856  {
857  unsigned char* p = (unsigned char*)*arr;
858  /* move all items following a[idx+n] to a[idx] */
859  memmove(p+itemsize*idx, p+itemsize*(idx+n), itemsize*(cnt - (idx+n)));
860  md->cnt -= n;
861  }
862  }
863 }
864 
865 DG_DYNARR_INLINE void
866 dg__dynarr_deletefast(void** arr, dg__dynarr_md* md, size_t itemsize, size_t idx, size_t n)
867 {
868  size_t cnt = md->cnt;
869  if(idx < cnt)
870  {
871  if(idx+n >= cnt) md->cnt = idx; /* removing last element(s) => just reduce count */
872  else
873  {
874  unsigned char* p = (unsigned char*)*arr;
875  /* copy the last n items to a[idx] - but handle the case that
876  * the array has less than n elements left after the deleted elements
877  */
878  size_t numItemsAfterDeleted = cnt - (idx+n);
879  size_t m = (n < numItemsAfterDeleted) ? n : numItemsAfterDeleted;
880  memcpy(p+itemsize*idx, p+itemsize*(cnt - m), itemsize*m);
881  md->cnt -= n;
882  }
883  }
884 }
885 
886 #ifdef __cplusplus
887 } /* extern "C" */
888 #endif
889 
890 #endif /* DG__DYNARR_H */
891 
892 /* ############## Implementation of non-inline functions ############## */
893 
894 #ifdef DG_DYNARR_IMPLEMENTATION
895 
896 /* by default, C's malloc(), realloc() and free() is used to allocate/free heap memory.
897  * you can #define DG_DYNARR_MALLOC, DG_DYNARR_REALLOC and DG_DYNARR_FREE
898  * to provide alternative implementations like Win32 Heap(Re)Alloc/HeapFree
899  */
900 #ifndef DG_DYNARR_MALLOC
901  #define DG_DYNARR_MALLOC(elemSize, numElems) malloc(elemSize*numElems)
902 
903  /* oldNumElems is not used here, but maybe you need it for your allocator
904  * to copy the old elements over
905  */
906  #define DG_DYNARR_REALLOC(ptr, elemSize, oldNumElems, newCapacity) \
907  realloc(ptr, elemSize*newCapacity);
908 
909  #define DG_DYNARR_FREE(ptr) free(ptr)
910 #endif
911 
912 /* you can #define DG_DYNARR_OUT_OF_MEMORY to some code that will be executed
913  * if allocating memory fails
914  */
915 #ifndef DG_DYNARR_OUT_OF_MEMORY
916  #define DG_DYNARR_OUT_OF_MEMORY DG_DYNARR_ASSERT(0, "Out of Memory!");
917 #endif
918 
919 #ifdef __cplusplus
920 extern "C" {
921 #endif
922 
923 DG_DYNARR_DEF void
925 {
926  /* only free memory if it doesn't point to external memory */
927  if(!(md->cap & DG__DYNARR_SIZE_T_MSB))
928  {
929  DG_DYNARR_FREE(*p);
930  *p = NULL;
931  md->cap = 0;
932  }
933  md->cnt = 0;
934 }
935 
936 DG_DYNARR_DEF int
937 dg__dynarr_grow(void** arr, dg__dynarr_md* md, size_t itemsize, size_t min_needed)
938 {
939  size_t cap = md->cap & DG__DYNARR_SIZE_T_ALL_BUT_MSB;
940 
941  DG_DYNARR_ASSERT(min_needed > cap, "dg__dynarr_grow() should only be called if storage actually needs to grow!");
942 
943  if(min_needed < DG__DYNARR_SIZE_T_MSB)
944  {
945  size_t newcap = (cap > 4) ? (2*cap) : 8; /* allocate for at least 8 elements */
946  /* make sure not to set DG__DYNARR_SIZE_T_MSB (unlikely anyway) */
947  if(newcap >= DG__DYNARR_SIZE_T_MSB) newcap = DG__DYNARR_SIZE_T_MSB-1;
948  if(min_needed > newcap) newcap = min_needed;
949 
950  /* the memory was allocated externally, don't free it, just copy contents */
951  if(md->cap & DG__DYNARR_SIZE_T_MSB)
952  {
953  void* p = DG_DYNARR_MALLOC(itemsize, newcap);
954  if(p != NULL) memcpy(p, *arr, itemsize*md->cnt);
955  *arr = p;
956  }
957  else
958  {
959  void* p = DG_DYNARR_REALLOC(*arr, itemsize, md->cnt, newcap);
960  if(p == NULL) DG_DYNARR_FREE(*arr); /* realloc failed, at least don't leak memory */
961  *arr = p;
962  }
963 
964  /* TODO: handle OOM by setting highest bit of count and keeping old data? */
965 
966  if(*arr) md->cap = newcap;
967  else
968  {
969  md->cap = 0;
970  md->cnt = 0;
971 
972  DG_DYNARR_OUT_OF_MEMORY ;
973 
974  return 0;
975  }
976  return 1;
977  }
978  DG_DYNARR_ASSERT(min_needed < DG__DYNARR_SIZE_T_MSB, "Arrays must stay below SIZE_T_MAX/2 elements!");
979  return 0;
980 }
981 
982 DG_DYNARR_DEF void
983 dg__dynarr_shrink_to_fit(void** arr, dg__dynarr_md* md, size_t itemsize)
984 {
985  /* only do this if we allocated the memory ourselves */
986  if(!(md->cap & DG__DYNARR_SIZE_T_MSB))
987  {
988  size_t cnt = md->cnt;
989  if(cnt == 0) dg__dynarr_free(arr, md);
990  else if((md->cap & DG__DYNARR_SIZE_T_ALL_BUT_MSB) > cnt)
991  {
992  void* p = DG_DYNARR_MALLOC(itemsize, cnt);
993  if(p != NULL)
994  {
995  memcpy(p, *arr, cnt*itemsize);
996  md->cap = cnt;
997  DG_DYNARR_FREE(*arr);
998  *arr = p;
999  }
1000  }
1001  }
1002 }
1003 
1004 #ifdef __cplusplus
1005 } /* extern "C" */
1006 #endif
1007 
1008 #endif /* DG_DYNARR_IMPLEMENTATION */
GLuint const GLchar * name
Definition: glext.h:6671
DG_DYNARR_INLINE int dg__dynarr_add(void **arr, dg__dynarr_md *md, size_t itemsize, size_t n, int init0)
Definition: dynarray.h:833
DG_DYNARR_INLINE int dg__dynarr_insert(void **arr, dg__dynarr_md *md, size_t itemsize, size_t idx, size_t n, int init0)
Definition: dynarray.h:812
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:8418
static const size_t DG__DYNARR_SIZE_T_MSB
Definition: dynarray.h:688
#define md
Definition: compat-1.3.h:1980
DG_DYNARR_INLINE int dg__dynarr_maybegrow(void **arr, dg__dynarr_md *md, size_t itemsize, size_t min_needed)
Definition: dynarray.h:797
#define da_free(a)
Definition: dynarray.h:235
#define da_pop(a)
Definition: dynarray.h:348
DG_DYNARR_DEF void dg__dynarr_free(void **p, dg__dynarr_md *md)
Definition: dynarray.h:676
#define NULL
Pointer to 0.
Definition: gctypes.h:65
#define DA_TYPEDEF(TYPE, NewArrayTypeName)
Definition: dynarray.h:209
DG_DYNARR_DEF void dg__dynarr_shrink_to_fit(void **arr, dg__dynarr_md *md, size_t itemsize)
#define DG_DYNARR_ASSERT(cond, msg)
Definition: dynarray.h:155
#define da_insert(a, idx, v)
Definition: dynarray.h:269
DG_DYNARR_DEF int dg__dynarr_grow(void **arr, dg__dynarr_md *md, size_t itemsize, size_t min_needed)
static const size_t DG__DYNARR_SIZE_T_ALL_BUT_MSB
Definition: dynarray.h:689
#define da_deletefast(a, idx)
Definition: dynarray.h:311
GLint GLint GLint GLint GLint x
Definition: glext.h:6295
f32 a2
Definition: gx_regdef.h:5096
DG_DYNARR_INLINE void dg__dynarr_init(void **p, dg__dynarr_md *md, void *buf, size_t buf_cap)
Definition: dynarray.h:788
size_t cap
Definition: dynarray.h:678
GLfloat GLfloat p
Definition: glext.h:9809
DG_DYNARR_INLINE int dg__dynarr_maybegrowadd(void **arr, dg__dynarr_md *md, size_t itemsize, size_t num_add)
Definition: dynarray.h:804
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 idx
Definition: pixman-arm-neon-asm.h:96
DG_DYNARR_INLINE void dg__dynarr_delete(void **arr, dg__dynarr_md *md, size_t itemsize, size_t idx, size_t n)
Definition: dynarray.h:849
f32 a1
Definition: gx_regdef.h:5095
GLenum cap
Definition: glext.h:10546
#define da_delete(a, idx)
Definition: dynarray.h:303
#define da_push(a, v)
Definition: dynarray.h:240
#define DG_DYNARR_INLINE
Definition: dynarray.h:199
DG_DYNARR_INLINE void dg__dynarr_deletefast(void **arr, dg__dynarr_md *md, size_t itemsize, size_t idx, size_t n)
Definition: dynarray.h:866
size_t cnt
Definition: dynarray.h:677
#define da_addn_uninit(a, n)
Definition: dynarray.h:264
#define da_addn(a, vals, n)
Definition: dynarray.h:252
void * memset(void *b, int c, size_t len)
Definition: string.c:7
#define da_count(a)
Definition: dynarray.h:390
GLdouble n
Definition: glext.h:8396
const GLfloat * m
Definition: glext.h:11755
#define DG_DYNARR_DEF
Definition: dynarray.h:192
#define da_init(a)
Definition: dynarray.h:215
void * memcpy(void *dst, const void *src, size_t len)
Definition: string.c:26