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
|
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
/*
* Lion's Standard (LS) ANSI C vector library.
*
* This is a vector library, i.e. a dynamically sized array.
* To get started, you have to declare your type:
*
* VEC(int)
*
* which creates a struct and the associated functions for a vec_int,
* meaning a vector of type `int`. The resulting struct is named `vec_int`
* and all associated functions are prefixed with that same name, for
* example `vec_int_init`, `vec_int_push`, etc.
*
* You can choose a name for long or complex types like this:
*
* VEC_NAMED(int*, intp)
*
* which results in vec_intp, vec_intp_push, etc. or
*
* VEC_NAMED(struct Car, car)
*
* which results in vec_car, vec_car_push, etc.
*
* The VEC and VEC_NAMED macros create both the declaration and implementation.
* If you'd like to split that, call
*
* VEC_DECL(int)
*
* to generate the declarations, and somewhere else
*
* VEC_IMPL(int)
*
* to generate the implementation. The same with VEC_NAMED_DECL
* and VEC_NAMED_IMPL.
*
* Full example:
*
* VEC(int)
*
* int main(void) {
* vec_int vec;
* vec_int_init(&vec);
* for (int i = 0; i < 10; ++i) {
* vec_int_push(&vec, i);
* }
* vec_int_clear(&vec);
* }
*
*/
#define LS_VEC_DECL(T, name) \
typedef struct name { \
size_t size; \
size_t capacity; \
T* data; \
} name; \
void name##_init(name* vec); \
void name##_clear(name* vec); \
int name##_reserve(name* vec, size_t count); \
int name##_push(name* vec, T value);
#define LS_VEC_IMPL(T, name) _ls_VEC_IMPL_DETAIL(T, name, )
#define LS_VEC_INLINE(T, name) \
typedef struct name { \
size_t size; \
size_t capacity; \
T* data; \
} name; \
_ls_VEC_IMPL_DETAIL(T, name, static)
#define _ls_VEC_IMPL_DETAIL(T, name, specifier) \
specifier void name##_init(name* vec) { memset(vec, 0, sizeof(*vec)); } \
specifier void name##_clear(name* vec) { \
if (vec->data) { \
free(vec->data); \
vec->data = NULL; \
} \
vec->size = 0; \
vec->capacity = 0; \
} \
specifier int name##_reserve(name* vec, size_t count) { \
if (vec->capacity < count) { \
T* new_data; \
size_t total; \
if (count == 0) { \
vec->capacity = 5; \
} else { \
size_t new_cap = (size_t)((float)vec->capacity * 1.6f + 1.0f); \
vec->capacity = new_cap > count ? new_cap : count; \
} \
total = vec->capacity * sizeof(T); \
if (vec->capacity != 0 && total / vec->capacity != sizeof(T)) \
return 0; /* integer overflow */ \
new_data = (T*)realloc(vec->data, total); \
if (!new_data) \
return 0; \
vec->data = new_data; \
} \
return 1; \
} \
specifier int name##_push(name* vec, T value) { \
if (!name##_reserve(vec, vec->size + 1)) { \
return 0; \
} \
vec->data[vec->size++] = value; \
return 1; \
}
|