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
|
#include "vector.h"
VECTOR_IMPL(voidp, (void))
VECTOR_IMPL(char, (void))
VECTOR_IMPL(charp, (void))
VECTOR_IMPL(ccharp, (void))
static void stringp_del(string_t **s) { return string_del(*s); }
VECTOR_IMPL(string, stringp_del)
VECTOR(voidp) *vector_new_impl(void) {
VECTOR(voidp) *ret = malloc(sizeof(*ret));
if (!ret) return NULL;
ret->vsize = ret->vcap = 0; ret->content_v = NULL;
return ret;
}
VECTOR(voidp) *vector_new_cap_impl(size_t elem_size, size_t cap) {
if (!cap) return vector_new_impl();
VECTOR(voidp) *ret = malloc(sizeof(*ret));
if (!ret) return NULL;
cap = (cap < VECTOR_MIN_CAP) ? VECTOR_MIN_CAP : cap * 2;
ret->content_v = malloc(cap * elem_size);
if (!ret->content_v) {
free(ret);
return NULL;
}
ret->vcap = cap;
ret->vsize = 0;
return ret;
}
int vector_reserve_impl(VECTOR(voidp) *v, size_t elem_size, size_t cap) {
size_t new_cap = (cap < VECTOR_MIN_CAP) ? VECTOR_MIN_CAP : cap;
if (new_cap <= v->vcap) return 1;
void *new_content_v = realloc(v->content_v, elem_size * new_cap);
if (!new_content_v) return 0;
v->content_v = new_content_v;
v->vcap = new_cap;
return 1;
}
int vector_trim_impl(VECTOR(voidp) *v, size_t elem_size) {
if (v->vsize == v->vcap) return 1;
if (v->vsize) {
void *new_content_v = realloc(v->content_v, elem_size * v->vsize);
if (!new_content_v) return 0;
v->content_v = new_content_v;
v->vcap = v->vsize;
return 1;
} else {
free(v->content_v);
v->content_v = NULL;
v->vcap = 0;
return 1;
}
}
void vector_common_pop_impl(VECTOR(voidp) *v, size_t elem_size) {
if (--v->vsize < v->vcap / 4) {
size_t new_cap = (v->vcap / 2 < VECTOR_MIN_CAP) ? VECTOR_MIN_CAP : v->vcap / 2;
if (new_cap == v->vcap) return;
void *new_content_v = realloc(v->content_v, elem_size * new_cap);
if (!new_content_v) return; // We don't really care if the realloc fails, we just need to not update anything
v->content_v = new_content_v;
v->vcap = new_cap;
}
}
void vector_common_popn_impl(VECTOR(voidp) *v, size_t n, size_t elem_size) {
if (n > v->vsize) n = v->vsize;
v->vsize -= n;
if (v->vsize < v->vcap / 4) {
size_t new_cap = v->vcap / 2;
while (v->vsize < new_cap / 4) new_cap /= 2;
new_cap = (new_cap < VECTOR_MIN_CAP) ? VECTOR_MIN_CAP : new_cap;
if (new_cap == v->vcap) return;
void *new_content_v = realloc(v->content_v, elem_size * new_cap);
if (!new_content_v) return; // We don't really care if the realloc fails, we just need to not update anything
v->content_v = new_content_v;
v->vcap = new_cap;
}
}
void vector_common_clear_impl(VECTOR(voidp) *v) {
if (!v->content_v) return;
free(v->content_v);
v->vsize = v->vcap = 0; v->content_v = NULL;
}
int vector_push_vec_impl(VECTOR(voidp) *v1, VECTOR(voidp) *v2, size_t start, size_t len, size_t elem_size) {
if (start >= v2->vsize) return 1;
if (start + len > v2->vsize) len = v2->vsize - start;
if (!len) return 1;
if (v1->vsize + len > v1->vcap) {
size_t new_cap = (v1->vcap < VECTOR_MIN_CAP) ? VECTOR_MIN_CAP : v1->vcap * 2;
while (v1->vsize + len > new_cap) {
new_cap = new_cap * 2;
}
void *new_content_v = realloc(v1->content_v, elem_size * new_cap);
if (!new_content_v) return 0;
v1->content_v = new_content_v;
v1->vcap = new_cap;
}
memcpy((char*)v1->content_v + elem_size * v1->vsize, (char*)v2->content_v + elem_size * start, elem_size * len);
v1->vsize += len;
return 1;
}
|