summaryrefslogtreecommitdiff
path: root/src/gevector.h
blob: 881fb03f7226ae804927ba4fbb3e556c8c1c3421 (plain) (blame)
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
#ifndef LIBGE_GEVECTOR_H
#define LIBGE_GEVECTOR_H

#include <stdbool.h>
#include <stdlib.h>

#define GEVECTOR_DEF(t, n)                                                      \
	GEVECTOR_DEF_API(t, n)                                                  \
	GEVECTOR_DEF_IMPL(t, n)

#define GEVECTOR_DEF_API(t, n) GEVECTOR_DEF_API_HELPER(t, n, n##_t)
#define GEVECTOR_DEF_API_HELPER(t, n, n_t)                                      \
	typedef struct {                                                        \
		size_t len;                                                     \
		size_t __cap;                                                   \
		double __gfac;                                                  \
		t *__data;                                                      \
	} n_t;                                                                  \
	                                                                        \
	int    n##_new(n_t *, size_t, double);                                  \
	t      n##_get(n_t *, size_t);                                          \
	int    n##_insert(n_t *, t, size_t);                                    \
	int    n##_push(n_t *, t);                                              \
	t      n##_pop(n_t *);                                                  \
	void   n##_remove(n_t *, size_t);                                       \
	int    n##_resize(n_t *, size_t);                                       \
	size_t n##_len(n_t *);                                                  \
	void   n##_free(n_t *);

#define GEVECTOR_DEF_IMPL(t, n) GEVECTOR_DEF_IMPL_HELPER(t, n, n##_t)
#define GEVECTOR_DEF_IMPL_HELPER(t, n, n_t)                                     \
	int                                                                     \
	n##_new(n_t *vec, size_t cap, double gfac)                              \
	{                                                                       \
		*vec = (n_t) {                                                  \
			.len    = 0,                                            \
			.__gfac = gfac == 0 ? 1.5f : gfac,                      \
			.__cap  = cap == 0 ? 16 : cap,                          \
		};                                                              \
		vec->__data = malloc(vec->__cap * sizeof(t));                   \
		return vec->__data == NULL ? -1 : 0;                            \
	}                                                                       \
	                                                                        \
	t                                                                       \
	n##_get(n_t *vec, size_t i)                                             \
	{                                                                       \
		return vec->__data[i];                                          \
	}                                                                       \
	                                                                        \
	int                                                                     \
	n##_push(n_t *vec, t elem)                                              \
	{                                                                       \
		return n##_insert(vec, elem, vec->len);                         \
	}                                                                       \
                                                                                \
	t                                                                       \
	n##_pop(n_t *vec)                                                       \
	{                                                                       \
		return vec->__data[--vec->len];                                 \
	}                                                                       \
	                                                                        \
	int                                                                     \
	n##_insert(n_t *vec, t elem, size_t i)                                  \
	{                                                                       \
		if (vec->len == vec->__cap) {                                   \
			size_t ncap = (size_t) (vec->__cap * vec->__gfac);      \
			if (ncap == vec->__cap)                                 \
				ncap++;                                         \
			if (n##_resize(vec, ncap) == -1)                        \
				return -1;                                      \
		}                                                               \
		for (size_t j = vec->len; j > i; j--)                           \
			vec->__data[j] = vec->__data[j - 1];                    \
		vec->__data[i] = elem;                                          \
		vec->len++;                                                     \
		return 0;                                                       \
	}                                                                       \
	                                                                        \
	void                                                                    \
	n##_remove(n_t *vec, size_t i)                                          \
	{                                                                       \
		for (size_t j = i; j < vec->len - 1; j++)                       \
			vec->__data[j] = vec->__data[j + 1];                    \
		vec->len--;                                                     \
	}                                                                       \
	                                                                        \
	int                                                                     \
	n##_resize(n_t *vec, size_t ncap)                                       \
	{                                                                       \
		vec->__data = realloc(vec->__data, sizeof(t) * ncap);           \
		if (vec->__data == NULL)                                        \
			return -1;                                              \
		vec->__cap = ncap;                                              \
		return 0;                                                       \
	}                                                                       \
                                                                                \
	void                                                                    \
	n##_free(n_t *vec)                                                      \
	{                                                                       \
		free(vec->__data);                                              \
	}

#endif /* !LIBGE_GEVECTOR_H */