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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "array.h"
#include "util.h"
#define ARRAY_SIZE 16
void array_init(Array *arr) {
array_init_sized(arr, sizeof(void*));
}
void array_init_from(Array *arr, const Array *from) {
array_init_sized(arr, from->elem_size);
}
void array_init_sized(Array *arr, size_t elem_size) {
memset(arr, 0, sizeof *arr);
arr->elem_size = elem_size;
}
bool array_reserve(Array *arr, size_t count) {
if (count < ARRAY_SIZE)
count = ARRAY_SIZE;
if (arr->count < count) {
count = MAX(count, arr->count*2);
char *items = realloc(arr->items, count * arr->elem_size);
if (!items)
return false;
arr->count = count;
arr->items = items;
}
return true;
}
void array_release(Array *arr) {
if (!arr)
return;
free(arr->items);
array_init_sized(arr, arr->elem_size);
}
void array_release_full(Array *arr) {
if (!arr)
return;
for (size_t i = 0; i < arr->len; i++)
free(array_get_ptr(arr, i));
array_release(arr);
}
void array_clear(Array *arr) {
arr->len = 0;
if (arr->items)
memset(arr->items, 0, arr->count * arr->elem_size);
}
void *array_get(const Array *arr, size_t idx) {
if (idx >= arr->len) {
errno = EINVAL;
return NULL;
}
return arr->items + (idx * arr->elem_size);
}
void *array_get_ptr(const Array *arr, size_t idx) {
if (arr->elem_size != sizeof(void*)) {
errno = ENOTSUP;
return NULL;
}
void **ptr = array_get(arr, idx);
return ptr ? *ptr : NULL;
}
bool array_set(Array *arr, size_t idx, void *item) {
if (idx >= arr->len) {
errno = EINVAL;
return false;
}
if (item)
memcpy(arr->items + (idx * arr->elem_size), item, arr->elem_size);
else
memset(arr->items + (idx * arr->elem_size), 0, arr->elem_size);
return true;
}
bool array_set_ptr(Array *arr, size_t idx, void *item) {
if (arr->elem_size != sizeof(void*)) {
errno = ENOTSUP;
return false;
}
return array_set(arr, idx, &item);
}
bool array_add(Array *arr, void *item) {
if (!array_reserve(arr, arr->len+1))
return false;
if (!array_set(arr, arr->len++, item)) {
arr->len--;
return false;
}
return true;
}
bool array_add_ptr(Array *arr, void *item) {
if (!array_reserve(arr, arr->len+1))
return false;
if (!array_set_ptr(arr, arr->len++, item)) {
arr->len--;
return false;
}
return true;
}
bool array_remove(Array *arr, size_t idx) {
if (idx >= arr->len) {
errno = EINVAL;
return false;
}
char *dest = arr->items + idx * arr->elem_size;
char *src = arr->items + (idx + 1) * arr->elem_size;
memmove(dest, src, (arr->len - idx - 1) * arr->elem_size);
arr->len--;
return true;
}
size_t array_length(const Array *arr) {
return arr->len;
}
size_t array_capacity(const Array *arr) {
return arr->count;
}
bool array_truncate(Array *arr, size_t len) {
if (len <= arr->len) {
arr->len = len;
return true;
}
return false;
}
bool array_resize(Array *arr, size_t len) {
if (len <= arr->count) {
arr->len = len;
return true;
}
return false;
}
void array_sort(Array *arr, int (*compar)(const void*, const void*)) {
if (arr->items)
qsort(arr->items, arr->len, arr->elem_size, compar);
}
bool array_push(Array *arr, void *item) {
return array_add(arr, item);
}
void *array_pop(Array *arr) {
void *item = array_peek(arr);
if (!item)
return NULL;
arr->len--;
return item;
}
void *array_peek(const Array *arr) {
if (arr->len == 0)
return NULL;
return array_get(arr, arr->len - 1);
}
|