-
Notifications
You must be signed in to change notification settings - Fork 0
/
vector.h
127 lines (111 loc) · 3.46 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
#ifndef VECTOR_H
#define VECTOR_H
#include <stddef.h>
#include "std.h"
#include "cstdint.h"
#include "platform.h"
#if TL_CPP
extern "C" {
#endif
#define tl_vector_new(v, t, n) do { \
size_t n_ = (n); \
tl_vector* v_ = &(v); \
v_->cap = n_; \
v_->size = 0; \
if(n_ > SIZE_MAX/sizeof(t)) \
v_->impl = NULL; \
else \
v_->impl = memalloc(sizeof(t)*(n_)); \
} while(0)
#define tl_vector_new_empty(v) do { \
tl_vector* v_ = &(v); \
v_->cap = 0; \
v_->size = 0; \
v_->impl = NULL; \
} while(0)
#define tl_vector_pushback(v, t, e) do { \
tl_vector* p_v_ = &(v); \
size_t s_ = tl_vector_size(*p_v_); \
if(s_ >= p_v_->cap) tl_vector_enlarge(*p_v_, t, 1); \
((t*)p_v_->impl)[s_++] = (e); \
p_v_->size = s_; \
} while(0)
#define tl_vector_foreach(v, t, var, body) do { \
tl_vector* fv_ = &(v); \
t* var = (t*)fv_->impl; \
t* e_ = ((t*)var + fv_->size); \
for(; var != e_; ++var) \
body \
} while(0)
#define tl_vector_filtereach(v, t, var, body) do { \
tl_vector* fi_v_##var = &(v); \
size_t idx_ = 0; \
for(; idx_ < fi_v_##var->size; ++idx_) { \
int remove = 0; \
t* var = (t*)fi_v_##var->impl + idx_; \
body \
if(remove) tl_vector_remove_reorder(*fi_v_##var, t, idx_); \
else ++idx_; \
} \
} while(0)
#define tl_vector_remove_reorder(v, t, idx) do { \
tl_vector* rr_v_ = &(v); \
t* base_ = (t*)rr_v_->impl; \
size_t s_ = tl_vector_size(*rr_v_); \
size_t rr_idx_ = (idx); \
assert(rr_idx_ < s_); \
base_[rr_idx_] = base_[s_ - 1]; \
--rr_v_->size; \
} while(0)
#define tl_vector_reserve(v, t, newcap) do { \
tl_vector* e_v_ = &(v); \
void* new_impl_; \
size_t newcap_ = (newcap); \
if(newcap_ > e_v_->cap) { \
if(newcap_ > SIZE_MAX/sizeof(t) \
|| !(new_impl_ = memrealloc(e_v_->impl, sizeof(t)*newcap_, sizeof(t)*e_v_->cap))) { \
memfree(e_v_->impl); new_impl_ = NULL; \
} \
e_v_->impl = new_impl_; \
e_v_->cap = newcap_; \
} \
} while(0)
#define tl_vector_enlarge(v, t, extra) do { \
tl_vector* e_v_ = &(v); \
void* new_impl_; \
size_t newcap_ = e_v_->size * 2 + (extra); \
if(newcap_ > SIZE_MAX/sizeof(t) \
|| !(new_impl_ = memrealloc(e_v_->impl, sizeof(t)*newcap_, sizeof(t)*e_v_->cap))) { \
memfree(e_v_->impl); new_impl_ = NULL; \
} \
e_v_->impl = new_impl_; \
e_v_->cap = newcap_; \
} while(0)
#define tl_vector_idx(v, t, i) ((t*)(v).impl + (i))
#define tl_vector_el(v, t, i) (*tl_vector_idx(v,t,i))
#define tl_vector_size(v) ((v).size)
#define tl_vector_post_enlarge(v, t, n) ((v).size += (n))
#define tl_vector_free(v) free((v).impl)
typedef struct tl_vector {
size_t cap;
size_t size;
void* impl;
} tl_vector;
#define tl_def_vector(name, t) \
typedef struct name { \
tl_vector v; \
} name; \
TL_INLINE void name##_init_empty(name* V) { tl_vector_new_empty(V->v); } \
TL_INLINE void name##_init(name* V, size_t n) { tl_vector_new(V->v, t, n); } \
TL_INLINE t name##_el(name* V, size_t i) { return tl_vector_el(V->v, t, i); } \
TL_INLINE t* name##_idx(name* V, size_t i) { return tl_vector_idx(V->v, t, i); } \
TL_INLINE size_t name##_size(name* V) { return tl_vector_size(V->v); } \
TL_INLINE void name##_destroy(name* V) { tl_vector_free(V->v); } \
TL_INLINE void name##_pushback(name* V, t e) { tl_vector_pushback(V->v, t, e); } \
TL_INLINE void name##_enlarge(name* V, size_t extra) { tl_vector_enlarge(V->v, t, extra); } \
TL_INLINE void name##_post_enlarge(name* V, size_t extra) { tl_vector_post_enlarge(V->v, t, extra); } \
TL_INLINE tl_vector* name##_super(name* V) { return &V->v; }
#if TL_CPP
} // extern "C"
#endif
#endif // VECTOR_H