vis
a vi-like editor based on Plan 9's structural regular expressions
git clone https://9o.is/git/vis.git
array.c
(3295B)
1 #include <stdlib.h>
2 #include <string.h>
3 #include <errno.h>
4
5 #include "array.h"
6 #include "util.h"
7
8 #define ARRAY_SIZE 16
9
10 void array_init(Array *arr) {
11 array_init_sized(arr, sizeof(void*));
12 }
13
14 void array_init_from(Array *arr, const Array *from) {
15 array_init_sized(arr, from->elem_size);
16 }
17
18 void array_init_sized(Array *arr, size_t elem_size) {
19 memset(arr, 0, sizeof *arr);
20 arr->elem_size = elem_size;
21 }
22
23 bool array_reserve(Array *arr, size_t count) {
24 if (count < ARRAY_SIZE)
25 count = ARRAY_SIZE;
26 if (arr->count < count) {
27 count = MAX(count, arr->count*2);
28 char *items = realloc(arr->items, count * arr->elem_size);
29 if (!items)
30 return false;
31 arr->count = count;
32 arr->items = items;
33 }
34 return true;
35 }
36
37 void array_release(Array *arr) {
38 if (!arr)
39 return;
40 free(arr->items);
41 array_init_sized(arr, arr->elem_size);
42 }
43
44 void array_release_full(Array *arr) {
45 if (!arr)
46 return;
47 for (size_t i = 0; i < arr->len; i++)
48 free(array_get_ptr(arr, i));
49 array_release(arr);
50 }
51
52 void array_clear(Array *arr) {
53 arr->len = 0;
54 if (arr->items)
55 memset(arr->items, 0, arr->count * arr->elem_size);
56 }
57
58 void *array_get(const Array *arr, size_t idx) {
59 if (idx >= arr->len) {
60 errno = EINVAL;
61 return NULL;
62 }
63 return arr->items + (idx * arr->elem_size);
64 }
65
66 void *array_get_ptr(const Array *arr, size_t idx) {
67 if (arr->elem_size != sizeof(void*)) {
68 errno = ENOTSUP;
69 return NULL;
70 }
71 void **ptr = array_get(arr, idx);
72 return ptr ? *ptr : NULL;
73 }
74
75 bool array_set(Array *arr, size_t idx, void *item) {
76 if (idx >= arr->len) {
77 errno = EINVAL;
78 return false;
79 }
80 if (item)
81 memcpy(arr->items + (idx * arr->elem_size), item, arr->elem_size);
82 else
83 memset(arr->items + (idx * arr->elem_size), 0, arr->elem_size);
84 return true;
85 }
86
87 bool array_set_ptr(Array *arr, size_t idx, void *item) {
88 if (arr->elem_size != sizeof(void*)) {
89 errno = ENOTSUP;
90 return false;
91 }
92 return array_set(arr, idx, &item);
93 }
94
95 bool array_add(Array *arr, void *item) {
96 if (!array_reserve(arr, arr->len+1))
97 return false;
98 if (!array_set(arr, arr->len++, item)) {
99 arr->len--;
100 return false;
101 }
102 return true;
103 }
104
105 bool array_add_ptr(Array *arr, void *item) {
106 if (!array_reserve(arr, arr->len+1))
107 return false;
108 if (!array_set_ptr(arr, arr->len++, item)) {
109 arr->len--;
110 return false;
111 }
112 return true;
113 }
114
115 bool array_remove(Array *arr, size_t idx) {
116 if (idx >= arr->len) {
117 errno = EINVAL;
118 return false;
119 }
120 char *dest = arr->items + idx * arr->elem_size;
121 char *src = arr->items + (idx + 1) * arr->elem_size;
122 memmove(dest, src, (arr->len - idx - 1) * arr->elem_size);
123 arr->len--;
124 return true;
125 }
126
127 bool array_truncate(Array *arr, size_t len) {
128 if (len <= arr->len) {
129 arr->len = len;
130 return true;
131 }
132 return false;
133 }
134
135 bool array_resize(Array *arr, size_t len) {
136 if (len <= arr->count) {
137 arr->len = len;
138 return true;
139 }
140 return false;
141 }
142
143 void array_sort(Array *arr, int (*compar)(const void*, const void*)) {
144 if (arr->items)
145 qsort(arr->items, arr->len, arr->elem_size, compar);
146 }
147
148 bool array_push(Array *arr, void *item) {
149 return array_add(arr, item);
150 }
151
152 void *array_pop(Array *arr) {
153 void *item = array_peek(arr);
154 if (!item)
155 return NULL;
156 arr->len--;
157 return item;
158 }
159
160 void *array_peek(const Array *arr) {
161 if (arr->len == 0)
162 return NULL;
163 return array_get(arr, arr->len - 1);
164 }