1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
#ifndef LI_VECTOR_H
#define LI_VECTOR_H
#include "first.h"
#include "buffer.h" /* force_assert() */
static inline size_t vector_align_size(size_t s) {
size_t a = (s + 15) & ~(size_t)15uL;
return (a < s) ? s : a;
}
void vector_free(void *data);
__attribute_malloc__
void *vector_malloc(size_t sz);
__attribute_returns_nonnull__
void *vector_realloc(void *data, size_t elem_size, size_t size, size_t used);
#define DEFINE_TYPED_VECTOR(name, entry, release) \
typedef struct vector_ ## name { \
entry* data; \
size_t used; \
size_t size; \
} vector_ ## name; \
static inline void vector_ ## name ## _init(vector_ ## name *v) { \
v->data = NULL; \
v->used = v->size = 0; \
} \
__attribute_malloc__ \
__attribute_returns_nonnull__ \
static inline vector_ ## name *vector_ ## name ## _alloc() { \
vector_ ## name *v = vector_malloc(sizeof(*v)); \
force_assert(NULL != v); \
vector_ ## name ## _init(v); \
return v; \
} \
static inline void vector_ ## name ## _clear(vector_ ## name *v) { \
if (release) for (size_t i = 0; i < v->used; ++i) release(v->data[i]); \
vector_free(v->data); \
vector_ ## name ## _init(v); \
} \
static inline void vector_ ## name ## _free(vector_ ## name *v) { \
if (NULL != v) { \
vector_ ## name ## _clear(v); \
vector_free(v); \
} \
} \
static inline void vector_ ## name ## _reserve(vector_ ## name *v, size_t p) { \
if (v->size - v->used < p) { \
force_assert(v->used < SIZE_MAX - p); \
v->size = vector_align_size(v->used + p); \
v->data = vector_realloc(v->data, sizeof(entry), v->size, v->used); \
} \
} \
static inline void vector_ ## name ## _push(vector_ ## name *v, entry e) { \
vector_ ## name ## _reserve(v, 1); \
v->data[v->used++] = e; \
} \
static inline entry vector_ ## name ## _pop(vector_ ## name *v) { \
force_assert(v->used > 0); \
return v->data[--v->used]; \
} \
struct vector_ ## name /* expect trailing semicolon */ \
/* end of DEFINE_TYPED_VECTOR */
#define DEFINE_TYPED_VECTOR_NO_RELEASE(name, entry) \
DEFINE_TYPED_VECTOR(name, entry, ((void(*)(entry)) NULL)) \
/* end of DEFINE_TYPED_VECTOR_NO_RELEASE */
#endif
|