vis: improve <C-n> in visual mode
[vis.git] / array.c
blobc68279f7d038e3338e4b11010f0f547bcaaf5443
1 #include <stdlib.h>
2 #include <string.h>
3 #include <errno.h>
5 #include "array.h"
6 #include "util.h"
8 #define ARRAY_SIZE 16
10 void array_init(Array *arr) {
11 array_init_sized(arr, sizeof(void*));
14 void array_init_from(Array *arr, Array *from) {
15 array_init_sized(arr, from->elem_size);
18 void array_init_sized(Array *arr, size_t elem_size) {
19 memset(arr, 0, sizeof *arr);
20 arr->elem_size = elem_size;
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;
34 return true;
37 void array_release(Array *arr) {
38 if (!arr)
39 return;
40 free(arr->items);
41 array_init_sized(arr, arr->elem_size);
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);
52 void array_clear(Array *arr) {
53 arr->len = 0;
54 if (arr->items)
55 memset(arr->items, 0, arr->count * arr->elem_size);
58 void *array_get(Array *arr, size_t idx) {
59 if (idx >= arr->len) {
60 errno = EINVAL;
61 return NULL;
63 return arr->items + (idx * arr->elem_size);
66 void *array_get_ptr(Array *arr, size_t idx) {
67 if (arr->elem_size != sizeof(void*)) {
68 errno = ENOTSUP;
69 return NULL;
71 void **ptr = array_get(arr, idx);
72 return ptr ? *ptr : NULL;
75 bool array_set(Array *arr, size_t idx, void *item) {
76 if (idx >= arr->len) {
77 errno = EINVAL;
78 return false;
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;
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;
92 return array_set(arr, idx, &item);
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;
102 return true;
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;
112 return true;
115 bool array_remove(Array *arr, size_t idx) {
116 if (idx >= arr->len) {
117 errno = EINVAL;
118 return false;
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;
127 size_t array_length(Array *arr) {
128 return arr->len;
131 size_t array_capacity(Array *arr) {
132 return arr->count;
135 bool array_truncate(Array *arr, size_t len) {
136 if (len <= arr->len) {
137 arr->len = len;
138 return true;
140 return false;
143 bool array_resize(Array *arr, size_t len) {
144 if (len <= arr->count) {
145 arr->len = len;
146 return true;
148 return false;
151 void array_sort(Array *arr, int (*compar)(const void*, const void*)) {
152 qsort(arr->items, arr->len, arr->elem_size, compar);
155 bool array_push(Array *arr, void *item) {
156 return array_add(arr, item);
159 void *array_pop(Array *arr) {
160 void *item = array_peek(arr);
161 if (!item)
162 return NULL;
163 arr->len--;
164 return item;
167 void *array_peek(Array *arr) {
168 if (arr->len == 0)
169 return NULL;
170 return array_get(arr, arr->len - 1);