]> mj.ucw.cz Git - libucw.git/blob - ucw/gary.h
0da8f690fe95da61e96925d45b8cbeda194528b9
[libucw.git] / ucw / gary.h
1 /*
2  *      UCW Library -- A simple growing array of an arbitrary type
3  *
4  *      (c) 2010--2014 Martin Mares <mj@ucw.cz>
5  */
6
7 #ifndef _UCW_GARY_H
8 #define _UCW_GARY_H
9
10 #ifdef CONFIG_UCW_CLEAN_ABI
11 #define gary_fix ucw_gary_fix
12 #define gary_init ucw_gary_init
13 #define gary_push_helper ucw_gary_push_helper
14 #define gary_set_size ucw_gary_set_size
15 #endif
16
17 struct gary_hdr {
18   size_t num_elts;
19   size_t have_space;
20   size_t elt_size;
21   int zeroed;
22 };
23
24 #define GARY_HDR_SIZE ALIGN_TO(sizeof(struct gary_hdr), CPU_STRUCT_ALIGN)
25 #define GARY_HDR(ptr) ((struct gary_hdr *)((byte*)(ptr) - GARY_HDR_SIZE))
26 #define GARY_BODY(ptr) ((byte *)(ptr) + GARY_HDR_SIZE)
27
28 #define GARY_INIT(ptr, n) (ptr) = gary_init(sizeof(*(ptr)), (n), 0)
29 #define GARY_INIT_ZERO(ptr, n) (ptr) = gary_init(sizeof(*(ptr)), (n), 1)
30 #define GARY_INIT_SPACE(ptr, n) do { GARY_INIT(ptr, n); (GARY_HDR(ptr))->num_elts = 0; } while (0)
31 #define GARY_INIT_SPACE_ZERO(ptr, n) do { GARY_INIT_ZERO(ptr, n); (GARY_HDR(ptr))->num_elts = 0; } while (0)
32 #define GARY_FREE(ptr) do { if (ptr) xfree(GARY_HDR(ptr)); } while (0)
33 #define GARY_SIZE(ptr) (GARY_HDR(ptr)->num_elts)
34 #define GARY_RESIZE(ptr, n) ((ptr) = gary_set_size((ptr), (n)))
35 #define GARY_INIT_OR_RESIZE(ptr, n) (ptr) = (ptr) ? gary_set_size((ptr), (n)) : gary_init(sizeof(*(ptr)), (n), 0)
36
37 #define GARY_PUSH_MULTI(ptr, n) ({                                      \
38   struct gary_hdr *_h = GARY_HDR(ptr);                                  \
39   typeof(*(ptr)) *_c = &(ptr)[_h->num_elts];                            \
40   size_t _n = n;                                                        \
41   _h->num_elts += _n;                                                   \
42   if (_h->num_elts > _h->have_space)                                    \
43     (ptr) = gary_push_helper((ptr), _n, (byte **) &_c);                 \
44   _c; })
45 #define GARY_PUSH(ptr) GARY_PUSH_MULTI(ptr, 1)
46
47 #define GARY_POP_MULTI(ptr, n) GARY_HDR(ptr)->num_elts -= (n)
48 #define GARY_POP(ptr) GARY_POP_MULTI(ptr, 1)
49 #define GARY_FIX(ptr) (ptr) = gary_fix((ptr))
50
51 /* Internal functions */
52 void *gary_init(size_t elt_size, size_t num_elts, int zeroed);
53 void *gary_set_size(void *array, size_t n);
54 void *gary_push_helper(void *array, size_t n, byte **cptr);
55 void *gary_fix(void *array);
56
57 #endif