diff options
Diffstat (limited to 'src/bytecode/darray.h')
-rw-r--r-- | src/bytecode/darray.h | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/bytecode/darray.h b/src/bytecode/darray.h new file mode 100644 index 0000000..db6234d --- /dev/null +++ b/src/bytecode/darray.h | |||
@@ -0,0 +1,78 @@ | |||
1 | #ifndef BDL_DARRAY_H | ||
2 | #define BDL_DARRAY_H | ||
3 | |||
4 | #include <string.h> | ||
5 | |||
6 | typedef struct ArrayHeader { | ||
7 | size_t size; | ||
8 | size_t cap; | ||
9 | } ArrayHeader; | ||
10 | |||
11 | // Header/Size/capacity accessors. | ||
12 | #define array_head(ARR) ((ArrayHeader *)((char *)(ARR) - sizeof(ArrayHeader))) | ||
13 | #define array_size(ARR) ((ARR) ? array_head(ARR)->size : 0) | ||
14 | #define array_cap(ARR) ((ARR) ? array_head(ARR)->cap : 0) | ||
15 | |||
16 | // Initialize a dynamic array ARR with N elements. The initialization doesn't | ||
17 | // zero out the data, so thread carefully.. | ||
18 | #define array_init(ARR,N) ((ARR) = _array_reserve(N, sizeof(*(ARR)))) | ||
19 | |||
20 | // Push a given element T to the dynamic array ARR. | ||
21 | #define array_push(ARR, T) \ | ||
22 | ((ARR) = _array_maybe_grow(ARR, sizeof(T)), \ | ||
23 | (ARR)[array_head(ARR)->size++] = (T)) | ||
24 | |||
25 | // Return the last element of the array. Can be used to build stacks. | ||
26 | #define array_pop(ARR) (ARR)[--array_head(ARR)->size] | ||
27 | |||
28 | // Insert N bytes from the SRC array into the ARR dynamic array. | ||
29 | #define array_insert(ARR, SRC, N) \ | ||
30 | ((ARR) = _array_insert(ARR, SRC, N, sizeof(*(ARR)))) | ||
31 | |||
32 | // Free the memory from the original allocated position. | ||
33 | #define array_free(ARR) ((ARR) ? free(array_head(ARR)), (ARR) = NULL : 0) | ||
34 | |||
35 | static inline void * | ||
36 | _array_reserve(size_t num_elem, size_t type_size) { | ||
37 | char *p = malloc(num_elem * type_size + sizeof(ArrayHeader)); | ||
38 | p += sizeof(ArrayHeader); | ||
39 | array_head(p)->size = 0; | ||
40 | array_head(p)->cap = num_elem; | ||
41 | return p; | ||
42 | } | ||
43 | |||
44 | static inline void * | ||
45 | _array_maybe_grow(void *arr, size_t type_size) { | ||
46 | ArrayHeader *head = array_head(arr); | ||
47 | if (head->cap == head->size) { | ||
48 | if (head->cap == 0) { | ||
49 | head->cap++; | ||
50 | } else { | ||
51 | head->cap *= 2; | ||
52 | } | ||
53 | head = realloc(head, head->cap * type_size + sizeof(ArrayHeader)); | ||
54 | } | ||
55 | arr = (char *)head + sizeof(ArrayHeader); | ||
56 | return arr; | ||
57 | } | ||
58 | |||
59 | static inline | ||
60 | char * _array_insert(char *arr, const char *src, size_t n_bytes, size_t type_size) { | ||
61 | ArrayHeader *head = array_head(arr); | ||
62 | size_t new_size = n_bytes + head->size; | ||
63 | if (new_size >= head->cap * type_size) { | ||
64 | if (head->cap == 0) { | ||
65 | head->cap = 1; | ||
66 | } | ||
67 | while (new_size >= head->cap * type_size) { | ||
68 | head->cap *= 2; | ||
69 | } | ||
70 | head = realloc(head, head->cap * type_size + sizeof(ArrayHeader)); | ||
71 | } | ||
72 | arr = (char *)head + sizeof(ArrayHeader); | ||
73 | memcpy((arr + head->size), src, n_bytes); | ||
74 | head->size = new_size; | ||
75 | return arr; | ||
76 | } | ||
77 | |||
78 | #endif // BDL_DARRAY_H | ||