-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvec.h
More file actions
120 lines (119 loc) · 8.46 KB
/
vec.h
File metadata and controls
120 lines (119 loc) · 8.46 KB
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
#pragma once
#define NEW_VEC_TYPE(type, name, init_capacity) \
typedef struct name { \
type* data; \
size_t count; \
size_t capacity; \
size_t min_cap; \
} name; \
static inline void vec_append_##name(name* v, type x) { \
if (v->count >= v->capacity) { \
if (v->capacity == 0) v->capacity = v->min_cap; \
v->capacity *= 2; \
type* tmp = realloc(v->data, v->capacity * sizeof(*v->data)); \
if (!tmp) { \
perror("realloc"); \
exit(EXIT_FAILURE); \
} \
v->data = tmp; \
} \
v->data[v->count++] = x; \
} \
static inline void vec_udelete_##name( \
name* v, size_t i) { /* O(1), swaps with last */ \
if (i >= v->count) return; \
v->data[i] = v->data[v->count - 1]; \
v->count--; \
} \
static inline void vec_delete_##name( \
name* v, size_t i) { /* O(n), preserves order */ \
if (i >= v->count) return; \
for (size_t j = i; j + 1 < v->count; j++) { \
v->data[j] = v->data[j + 1]; /* shift elements left */ \
} \
v->count--; \
} \
static inline void vec_insert_##name(name* v, size_t i, type x) { \
if (i > v->count) return; \
if (v->count >= v->capacity) { \
if (v->capacity == 0) v->capacity = v->min_cap; \
v->capacity *= 2; \
type* tmp = realloc(v->data, v->capacity * sizeof(*v->data)); \
if (!tmp) { \
perror("realloc"); \
exit(EXIT_FAILURE); \
} \
v->data = tmp; \
} \
\
for (size_t j = v->count; j > i; j--) { \
v->data[j] = v->data[j - 1]; \
} \
\
v->data[i] = x; \
v->count++; \
} \
static inline void vec_shrink_##name(name* v) { \
if (v->count < v->capacity / 3 && v->capacity > v->min_cap) { \
v->capacity /= 2; \
type* tmp = realloc(v->data, v->capacity * sizeof(*v->data)); \
if (!tmp) { \
perror("realloc"); \
exit(EXIT_FAILURE); \
} \
v->data = tmp; \
} \
} \
static inline type vec_at_##name(name* v, size_t i) { \
if (i >= v->count) { \
fprintf(stderr, "vec_at: index %zu out of bounds (count=%zu)\n", \
i, v->count); \
exit(EXIT_FAILURE); \
} \
return v->data[i]; \
} \
static inline type vec_at_or_default_##name(name* v, size_t i, type d) { \
if (i >= v->count) return d; \
return v->data[i]; \
} \
static inline type vec_front_##name(name* v) { \
if (v->count == 0) { \
fprintf(stderr, "vec_front: empty vector\n"); \
exit(EXIT_FAILURE); \
} \
return v->data[0]; \
} \
static inline type vec_back_##name(name* v) { \
if (v->count == 0) { \
fprintf(stderr, "vec_back: empty vector\n"); \
exit(EXIT_FAILURE); \
} \
return v->data[v->count - 1]; \
} \
static inline ssize_t vec_find_##name(name* v, type x) { \
for (size_t i = 0; i < v->count; i++) \
if (v->data[i] == x) return (ssize_t)i; \
return -1; \
} \
static inline unsigned int vec_contains_##name(name* v, type x) { \
return vec_find_##name(v, x) >= 0; \
} \
static inline size_t vec_size_##name(name* v) { return v->count; } \
static inline size_t vec_capacity_##name(name* v) { return v->capacity; } \
static inline size_t vec_minimum_capacity_##name(name* v) { \
return v->min_cap; \
} \
static inline void vec_free_##name(name* v) { \
free(v->data); \
v->data = NULL; \
v->count = 0; \
v->capacity = 0; \
} \
static inline void vec_clear_##name(name* v) { v->count = 0; } \
static inline void vec_init_##name(name* v) { \
v->data = NULL; \
v->count = 0; \
v->capacity = 0; \
v->min_cap = init_capacity; \
if (v->min_cap <= 0) v->min_cap = 1; \
}