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
|
#ifndef BDL_DARRAY_H
#define BDL_DARRAY_H
#include <string.h>
typedef struct ArrayHeader {
size_t size;
size_t cap;
} ArrayHeader;
// Header/Size/capacity accessors.
#define array_head(ARR) ((ArrayHeader *)((char *)(ARR) - sizeof(ArrayHeader)))
#define array_size(ARR) ((ARR) ? array_head(ARR)->size : 0)
#define array_cap(ARR) ((ARR) ? array_head(ARR)->cap : 0)
// Initialize a dynamic array ARR with N elements. The initialization doesn't
// zero out the data, so thread carefully..
#define array_init(ARR,N) ((ARR) = _array_reserve(N, sizeof(*(ARR))))
// Push a given element T to the dynamic array ARR.
#define array_push(ARR, T) \
((ARR) = _array_maybe_grow(ARR, sizeof(T)), \
(ARR)[array_head(ARR)->size++] = (T))
// Return the last element of the array. Can be used to build stacks.
#define array_pop(ARR) (ARR)[--array_head(ARR)->size]
// Insert N bytes from the SRC array into the ARR dynamic array.
#define array_insert(ARR, SRC, N) \
((ARR) = _array_insert(ARR, SRC, N, sizeof(*(ARR))))
// Free the memory from the original allocated position.
#define array_free(ARR) ((ARR) ? free(array_head(ARR)), (ARR) = NULL : 0)
static inline void *
_array_reserve(size_t num_elem, size_t type_size) {
char *p = malloc(num_elem * type_size + sizeof(ArrayHeader));
p += sizeof(ArrayHeader);
array_head(p)->size = 0;
array_head(p)->cap = num_elem;
return p;
}
static inline void *
_array_maybe_grow(void *arr, size_t type_size) {
ArrayHeader *head = array_head(arr);
if (head->cap == head->size) {
if (head->cap == 0) {
head->cap++;
} else {
head->cap *= 2;
}
head = realloc(head, head->cap * type_size + sizeof(ArrayHeader));
}
arr = (char *)head + sizeof(ArrayHeader);
return arr;
}
static inline
char * _array_insert(char *arr, const char *src, size_t n_bytes, size_t type_size) {
ArrayHeader *head = array_head(arr);
size_t new_size = n_bytes + head->size;
if (new_size >= head->cap * type_size) {
if (head->cap == 0) {
head->cap = 1;
}
while (new_size >= head->cap * type_size) {
head->cap *= 2;
}
head = realloc(head, head->cap * type_size + sizeof(ArrayHeader));
}
arr = (char *)head + sizeof(ArrayHeader);
memcpy((arr + head->size), src, n_bytes);
head->size = new_size;
return arr;
}
#endif // BDL_DARRAY_H
|