-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvector.h
190 lines (150 loc) · 6 KB
/
vector.h
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#if !defined(VEC_H)
#define VEC_H
#include <stddef.h>
#include <stdlib.h>
#if !defined(VEC_INIT_CAP)
#define VEC_INIT_CAP 8
#endif
#if !defined(VEC_GROWTH_FACTOR)
#define VEC_GROWTH_FACTOR 2
#endif
#define VEC(T) \
struct { \
T* data; \
T* tmp; \
size_t length; \
size_t capacity; \
unsigned char state; \
}
#define VEC_DEF(name, T) \
typedef struct name { \
T* data; \
T* tmp; \
size_t length; \
size_t capacity; \
unsigned char state; \
} name
#define VEC_SUCCESS 0
#define VEC_OVERFLOW 1
#define VEC_OOM 2
#define VEC_CHECK_MUL_OVERFLOW_(op1, op2) ((op1) <= ((size_t)-1 / (op2)))
#define VEC_CHECK_SIZE_(vec, cap) \
VEC_CHECK_MUL_OVERFLOW_(cap, sizeof((vec).data[0]))
#define VEC_CHECK_ADD_OVERFLOW_(op1, op2) ((op1) <= ((size_t)-1 - (op2)))
#ifndef vec_malloc
#define vec_malloc(size) malloc(size)
#endif
#ifndef vec_realloc
#define vec_realloc(p, size) realloc(p, size)
#endif
#ifndef vec_free
#define vec_free(p) free(p)
#endif
#define VEC_INIT_N_(vec, cap) \
(((vec).data = vec_malloc((cap) * sizeof((vec).data[0]))) \
? ((vec).length = 0, (vec).capacity = (cap), \
(vec).state = VEC_SUCCESS) \
: ((vec).state = VEC_OOM))
#define VEC_INIT_N_S(vec, cap) \
(VEC_CHECK_SIZE_((vec), (cap)) ? VEC_INIT_N_((vec), (cap)) \
: ((vec).state = VEC_OVERFLOW))
#if !defined(VEC_NO_CHECKS)
#define VEC_INIT_N(vec, cap) VEC_INIT_N_S(vec, cap)
#else
#define VEC_INIT_N(vec, cap) VEC_INIT_N_(vec, cap)
#endif
#define VEC_INIT(vec) VEC_INIT_N((vec), VEC_INIT_CAP)
#define VEC_RESIZE_(vec, new_cap) \
(((vec).tmp = vec_realloc((vec).data, (new_cap) * sizeof((vec).data[0]))) \
? ((vec).data = (vec).tmp, (vec).capacity = (new_cap), \
(vec).state = VEC_SUCCESS) \
: ((vec).state = VEC_OOM))
#define VEC_RESIZE_S(vec, new_cap) \
(VEC_CHECK_SIZE_((vec), (new_cap)) ? VEC_RESIZE_((vec), (new_cap)) \
: ((vec).state = VEC_OVERFLOW))
#if !defined(VEC_NO_CHECKS)
#define VEC_RESIZE(vec, new_cap) VEC_RESIZE_S(vec, new_cap)
#else
#define VEC_RESIZE(vec, new_cap) VEC_RESIZE_(vec, new_cap)
#endif
#define VEC_GROW_IF_NEEDED_(vec, gfactor) \
((vec).length >= (vec).capacity \
? VEC_RESIZE((vec), (vec).capacity * (gfactor)) \
: ((vec).state = VEC_SUCCESS))
#define VEC_GROW_IF_NEEDED_S(vec, gfactor) \
(VEC_CHECK_MUL_OVERFLOW_((vec).capacity, (gfactor)) \
? VEC_GROW_IF_NEEDED_((vec), (gfactor)) \
: ((vec).state = VEC_OVERFLOW))
#if !defined(VEC_NO_CHECKS)
#define VEC_GROW_IF_NEEDED(vec, gfactor) VEC_GROW_IF_NEEDED_S(vec, gfactor)
#else
#define VEC_GROW_IF_NEEDED(vec, gfactor) VEC_GROW_IF_NEEDED_(vec, gfactor)
#endif
#define VEC_PUSH_G_(vec, gfactor, item) \
(VEC_GROW_IF_NEEDED((vec), (gfactor)) == VEC_SUCCESS \
? ((vec).data[(vec).length] = (item), (vec).length++, VEC_SUCCESS) \
: (vec).state)
#define VEC_PUSH_G_S(vec, gfactor, item) \
(VEC_CHECK_ADD_OVERFLOW_(((vec).length), 1) \
? VEC_PUSH_G_(vec, gfactor, item) \
: ((vec).state = VEC_OVERFLOW))
#if !defined(VEC_NO_CHECKS)
#define VEC_PUSH_G(vec, gfactor, item) VEC_PUSH_G_S(vec, gfactor, item)
#else
#define VEC_PUSH_G(vec, gfactor, item) VEC_PUSH_G_(vec, gfactor, item)
#endif
#if !defined(VEC_NO_CHECKS)
#define VEC_PUSH(vec, item) VEC_PUSH_G_S(vec, VEC_GROWTH_FACTOR, item)
#else
#define VEC_PUSH(vec, item) VEC_PUSH_G_(vec, VEC_GROWTH_FACTOR, item)
#endif
#define VEC_SHRINK_IF_NEEDED(vec, gfactor) \
((vec).capacity >= (gfactor)*2 && \
(vec).length <= (vec).capacity / ((gfactor)*2) \
? VEC_RESIZE((vec), (vec).capacity / (gfactor)) \
: ((vec).state = VEC_SUCCESS))
#define VEC_POP_G_(vec, gfactor) \
(VEC_SHRINK_IF_NEEDED((vec), (gfactor)) == VEC_SUCCESS \
? (&(vec).data[--(vec).length], VEC_SUCCESS) \
: (vec).state)
#define VEC_POP_G_S(vec, gfactor) \
((vec).length ? VEC_POP_G_(vec, gfactor) : NULL)
#if !defined(VEC_NO_CHECKS)
#define VEC_POP_G(vec, gfactor) VEC_POP_G_S(vec, gfactor)
#else
#define VEC_POP_G(vec, gfactor) VEC_POP_G_(vec, gfactor)
#endif
#define VEC_POP_(vec) (&(vec).data[--(vec).length])
#define VEC_POP_S(vec) ((vec).length ? VEC_POP_(vec) : NULL)
#if defined(VEC_SHRINK)
#define VEC_POP(vec) VEC_POP_G((vec), VEC_GROWTH_FACTOR)
#else
/*
Popping items safely with VEC_POP_S versus VEC_POP_ require different usage
patterns (see below) unlike the other VEC_*_S vs VEC_*_ functions which have
identical interfaces so I define VEC_POP() as VEC_POP_S() always regardless of
the VEC_NO_CHECKS macro
// when VEC_NO_CHECKS is not defined
while((item = VEC_POP(vec))) {
// ...
}
// otherwise, to pop all elements safely we need to store the vector
length first since VEC_POP (aka VEC_POP_ ) in this case have no way of reporting
that the vector is empty size_t vec_len = vec.length; for(size_t j = 0; j <
vec_len; j++) { item = VEC_POP(vec);
}
*/
#define VEC_POP(vec) VEC_POP_S(vec)
#endif
#define VEC_AT_(vec, i) (&(vec).data[(i)])
#define VEC_AT_S(vec, i) ((vec.length) > (i) ? VEC_AT_(vec, i) : NULL)
#if !defined(VEC_NO_CHECKS)
#define VEC_AT(vec, i) VEC_AT_S(vec, i)
#else
#define VEC_AT(vec, i) VEC_AT_(vec, i)
#endif
#define VEC_IS_EMPTY(vec) (!(vec).length)
#define VEC_FREE(vec) \
(vec_free((vec).data), (vec).data = NULL, (vec).capacity = 0, \
(vec).length = 0, (vec).state = VEC_SUCCESS)
#endif