2 * UCW Library -- A simple growing array of an arbitrary type
4 * (c) 2010--2014 Martin Mares <mj@ucw.cz>
10 #ifdef CONFIG_UCW_CLEAN_ABI
11 #define gary_allocator_default ucw_gary_allocator_default
12 #define gary_allocator_zeroed ucw_gary_allocator_zeroed
13 #define gary_fix ucw_gary_fix
14 #define gary_init ucw_gary_init
15 #define gary_push_helper ucw_gary_push_helper
16 #define gary_set_size ucw_gary_set_size
23 struct gary_allocator *allocator;
26 struct gary_allocator {
27 void * (*alloc)(struct gary_allocator *alloc, size_t size);
28 void * (*realloc)(struct gary_allocator *alloc, void *ptr, size_t old_size, size_t new_size);
29 void (*free)(struct gary_allocator *alloc, void *ptr);
33 extern struct gary_allocator gary_allocator_default;
34 extern struct gary_allocator gary_allocator_zeroed;
36 #define GARY_HDR_SIZE ALIGN_TO(sizeof(struct gary_hdr), CPU_STRUCT_ALIGN)
37 #define GARY_HDR(ptr) ((struct gary_hdr *)((byte*)(ptr) - GARY_HDR_SIZE))
38 #define GARY_BODY(ptr) ((byte *)(ptr) + GARY_HDR_SIZE)
40 #define GARY_INIT(ptr, n) (ptr) = gary_init(sizeof(*(ptr)), (n), &gary_allocator_default)
41 #define GARY_INIT_ZERO(ptr, n) (ptr) = gary_init(sizeof(*(ptr)), (n), &gary_allocator_zeroed)
42 #define GARY_INIT_ALLOC(ptr, n, a) (ptr) = gary_init(sizeof(*(ptr)), (n), (a))
43 #define GARY_INIT_SPACE(ptr, n) do { GARY_INIT(ptr, n); (GARY_HDR(ptr))->num_elts = 0; } while (0)
44 #define GARY_INIT_SPACE_ZERO(ptr, n) do { GARY_INIT_ZERO(ptr, n); (GARY_HDR(ptr))->num_elts = 0; } while (0)
45 #define GARY_INIT_SPACE_ALLOC(ptr, n, a) do { GARY_INIT_ALLOC(ptr, n, a); (GARY_HDR(ptr))->num_elts = 0; } while (0)
46 #define GARY_FREE(ptr) gary_free(ptr)
47 #define GARY_SIZE(ptr) (GARY_HDR(ptr)->num_elts)
48 #define GARY_RESIZE(ptr, n) ((ptr) = gary_set_size((ptr), (n)))
49 #define GARY_INIT_OR_RESIZE(ptr, n) (ptr) = (ptr) ? gary_set_size((ptr), (n)) : gary_init(sizeof(*(ptr)), (n), 0)
51 #define GARY_PUSH_MULTI(ptr, n) ({ \
52 struct gary_hdr *_h = GARY_HDR(ptr); \
53 typeof(*(ptr)) *_c = &(ptr)[_h->num_elts]; \
56 if (_h->num_elts > _h->have_space) \
57 (ptr) = gary_push_helper((ptr), _n, (byte **) &_c); \
59 #define GARY_PUSH(ptr) GARY_PUSH_MULTI(ptr, 1)
61 #define GARY_POP_MULTI(ptr, n) GARY_HDR(ptr)->num_elts -= (n)
62 #define GARY_POP(ptr) GARY_POP_MULTI(ptr, 1)
63 #define GARY_FIX(ptr) (ptr) = gary_fix((ptr))
65 /* Internal functions */
66 void *gary_init(size_t elt_size, size_t num_elts, struct gary_allocator *allocator);
67 void *gary_set_size(void *array, size_t n);
68 void *gary_push_helper(void *array, size_t n, byte **cptr);
69 void *gary_fix(void *array);
71 static inline void gary_free(void *ptr)
75 struct gary_hdr *h = GARY_HDR(ptr);
76 h->allocator->free(h->allocator, h);