forked from vnmakarov/mir
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmir-varr.h
173 lines (158 loc) · 11 KB
/
mir-varr.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
/* This file is a part of MIR project.
Copyright (C) 2018-2020 Vladimir Makarov <[email protected]>.
*/
#ifndef MIR_VARR_H
#define MIR_VARR_H
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#if !defined(VARR_ENABLE_CHECKING) && !defined(NDEBUG)
#define VARR_ENABLE_CHECKING
#endif
#ifndef VARR_ENABLE_CHECKING
#define VARR_ASSERT(EXPR, OP, T) ((void) (EXPR))
#else
static inline void mir_var_assert_fail (const char *op, const char *var) {
fprintf (stderr, "wrong %s for %s", op, var);
assert (0);
}
#define VARR_ASSERT(EXPR, OP, T) (void) ((EXPR) ? 0 : (mir_var_assert_fail (OP, #T), 0))
#endif
#ifdef __GNUC__
#define MIR_VARR_UNUSED __attribute__ ((unused))
#define MIR_VARR_NO_RETURN __attribute__ ((noreturn))
#else
#define MIR_VARR_UNUSED
#define MIR_VARR_NO_RETURN
#endif
static inline void MIR_VARR_NO_RETURN mir_varr_error (const char *message) {
#ifdef MIR_VARR_ERROR
MIR_VARR_ERROR (message);
assert (0);
#else
fprintf (stderr, "%s\n", message);
#endif
exit (1);
}
/*---------------- Typed variable length arrays -----------------------------*/
#define VARR_CONCAT2(A, B) A##B
#define VARR_CONCAT3(A, B, C) A##B##C
#define VARR(T) VARR_CONCAT2 (VARR_, T)
#define VARR_OP(T, OP) VARR_CONCAT3 (VARR_, T, OP)
#define VARR_OP_DEF(T, OP) MIR_VARR_UNUSED VARR_OP (T, OP)
#define VARR_T(T) \
typedef struct VARR (T) { \
size_t els_num; \
size_t size; \
T *varr; \
} VARR (T)
#define VARR_DEFAULT_SIZE 64
/* Vector of pointer to object. */
#define DEF_VARR(T) \
VARR_T (T); \
\
static inline void VARR_OP_DEF (T, create) (VARR (T) * *varr, size_t size) { \
VARR (T) * va; \
if (size == 0) size = VARR_DEFAULT_SIZE; \
*varr = va = (VARR (T) *) malloc (sizeof (VARR (T))); \
if (va == NULL) mir_varr_error ("varr: no memory"); \
va->els_num = 0; \
va->size = size; \
va->varr = (T *) malloc (size * sizeof (T)); \
} \
\
static inline void VARR_OP_DEF (T, destroy) (VARR (T) * *varr) { \
VARR (T) *va = *varr; \
VARR_ASSERT (va && va->varr, "destroy", T); \
free (va->varr); \
free (va); \
*varr = NULL; \
} \
\
static inline size_t VARR_OP_DEF (T, length) (const VARR (T) * varr) { \
VARR_ASSERT (varr, "length", T); \
return varr->els_num; \
} \
\
static inline T *VARR_OP_DEF (T, addr) (const VARR (T) * varr) { \
VARR_ASSERT (varr, "addr", T); \
return &varr->varr[0]; \
} \
\
static inline T VARR_OP_DEF (T, last) (const VARR (T) * varr) { \
VARR_ASSERT (varr && varr->varr && varr->els_num, "last", T); \
return varr->varr[varr->els_num - 1]; \
} \
\
static inline T VARR_OP_DEF (T, get) (const VARR (T) * varr, unsigned ix) { \
VARR_ASSERT (varr && varr->varr && ix < varr->els_num, "get", T); \
return varr->varr[ix]; \
} \
\
static inline T VARR_OP_DEF (T, set) (const VARR (T) * varr, unsigned ix, T obj) { \
T old_obj; \
VARR_ASSERT (varr && varr->varr && ix < varr->els_num, "set", T); \
old_obj = varr->varr[ix]; \
varr->varr[ix] = obj; \
return old_obj; \
} \
\
static inline void VARR_OP_DEF (T, trunc) (VARR (T) * varr, size_t size) { \
VARR_ASSERT (varr && varr->varr && varr->els_num >= size, "trunc", T); \
varr->els_num = size; \
} \
\
static inline int VARR_OP_DEF (T, expand) (VARR (T) * varr, size_t size) { \
VARR_ASSERT (varr && varr->varr, "expand", T); \
if (varr->size < size) { \
size += size / 2; \
varr->varr = (T *) realloc (varr->varr, sizeof (T) * size); \
varr->size = size; \
return 1; \
} \
return 0; \
} \
\
static inline void VARR_OP_DEF (T, tailor) (VARR (T) * varr, size_t size) { \
VARR_ASSERT (varr && varr->varr, "tailor", T); \
if (varr->size != size) varr->varr = (T *) realloc (varr->varr, sizeof (T) * size); \
varr->els_num = varr->size = size; \
} \
\
static inline void VARR_OP_DEF (T, push) (VARR (T) * varr, T obj) { \
T *slot; \
VARR_OP (T, expand) (varr, varr->els_num + 1); \
slot = &varr->varr[varr->els_num++]; \
*slot = obj; \
} \
\
static inline void VARR_OP_DEF (T, push_arr) (VARR (T) * varr, const T *objs, size_t len) { \
size_t i; \
T *slot; \
VARR_OP (T, expand) (varr, varr->els_num + len); \
for (i = 0; i < len; i++) { \
slot = &varr->varr[varr->els_num++]; \
*slot = objs[i]; \
} \
} \
\
static inline T VARR_OP_DEF (T, pop) (VARR (T) * varr) { \
T obj; \
VARR_ASSERT (varr && varr->varr && varr->els_num, "pop", T); \
obj = varr->varr[--varr->els_num]; \
return obj; \
}
#define VARR_CREATE(T, V, L) (VARR_OP (T, create) (&(V), L))
#define VARR_DESTROY(T, V) (VARR_OP (T, destroy) (&(V)))
#define VARR_LENGTH(T, V) (VARR_OP (T, length) (V))
#define VARR_ADDR(T, V) (VARR_OP (T, addr) (V))
#define VARR_LAST(T, V) (VARR_OP (T, last) (V))
#define VARR_GET(T, V, I) (VARR_OP (T, get) (V, I))
#define VARR_SET(T, V, I, O) (VARR_OP (T, set) (V, I, O))
#define VARR_TRUNC(T, V, S) (VARR_OP (T, trunc) (V, S))
#define VARR_EXPAND(T, V, S) (VARR_OP (T, expand) (V, S))
#define VARR_TAILOR(T, V, S) (VARR_OP (T, tailor) (V, S))
#define VARR_PUSH(T, V, O) (VARR_OP (T, push) (V, O))
#define VARR_PUSH_ARR(T, V, A, L) (VARR_OP (T, push_arr) (V, A, L))
#define VARR_POP(T, V) (VARR_OP (T, pop) (V))
#endif /* #ifndef MIR_VARR_H */