23 assert(list->
base !=
NULL || index == 0 || stride == 0);
25 const char *
const base = list->
base;
26 return base + index * stride;
31 assert(list->
base !=
NULL || index == 0 || stride == 0);
33 char *
const base = list->
base;
34 return base + index * stride;
39 assert(base !=
NULL || index == 0 || stride == 0);
41 const char *
const b = base;
42 return b + index * stride;
46 assert(base !=
NULL || index == 0 || stride == 0);
49 return b + index * stride;
52#define INDEX_TO(origin, index, stride) \
54 const list_t_ *: slot_from_const_list, \
55 list_t_ *: slot_from_list, \
56 const void *: slot_from_const_base, \
57 void *: slot_from_base)((origin), (index), (stride)))
73 void *
const slot =
INDEX_TO(list, new_slot, item_size);
94 void *
const slot =
INDEX_TO(list, list->
head, item_size);
102 assert(list !=
NULL);
110 assert(capacity > 0);
111 if (
SIZE_MAX / capacity < item_size) {
115 void *
const base = realloc(list->
base, capacity * item_size);
116 if (base ==
NULL && item_size > 0) {
123 const size_t new_bytes = (capacity - list->
capacity) * item_size;
125 memset(
new, 0, new_bytes);
146 const size_t new_head = capacity -
prefix;
148 void *
const target =
INDEX_TO(base, new_head, item_size);
150 const void *
const src =
INDEX_TO(base, list->
head, item_size);
151 if (
prefix * item_size > 0) {
154 memmove(target, src,
prefix * item_size);
159 list->
head = new_head;
168 assert(list !=
NULL);
200 void *
const slot =
INDEX_TO(list, new_slot, item_size);
203 memcpy(slot,
item, item_size);
211 assert(index < list.
size &&
"index out of bounds");
217 for (
size_t i = 0; i < list.
size; ++i) {
219 const void *candidate =
INDEX_TO(&list, slot, item_size);
220 if (item_size == 0 || memcmp(needle, candidate, item_size) == 0) {
229 assert(list !=
NULL);
230 assert(index < list->size);
233 for (
size_t i = index + 1; i < list->
size; ++i) {
235 void *
const dst =
INDEX_TO(list, dst_slot, item_size);
237 const void *
const src =
INDEX_TO(list, src_slot, item_size);
239 memcpy(dst, src, item_size);
243 void *truncated =
INDEX_TO(list, truncated_slot, item_size);
249 assert(list !=
NULL);
251 for (
size_t i = 0; i < list->
size; ++i) {
253 void *
const to_poison =
INDEX_TO(list, slot, item_size);
269 capacity, item_size, strerror(
err));
284 for (
size_t i = 0; i < list.
size; ++i) {
286 const void *
const src =
INDEX_TO(&list, slot, item_size);
290 memcpy(dst, src, item_size);
296 void *
const to_poison =
INDEX_TO(&ret, ret.
size, item_size);
297 const size_t to_poison_len = (ret.
capacity - ret.
size) * item_size;
325 assert(list !=
NULL);
333 while (list->
head != 0) {
337 for (
size_t i = 0; i < item_size; ++i) {
339 memcpy(&lowest, list->
base,
sizeof(lowest));
340 const size_t remainder = list->
capacity * item_size -
sizeof(lowest);
341 memmove(list->
base, (
char *)list->
base +
sizeof(lowest), remainder);
342 memcpy((
char *)list->
base + remainder, &lowest,
sizeof(lowest));
357 assert(list !=
NULL);
362 if (list->
size > 0 && item_size > 0) {
367static void exchange(
void *a,
void *b,
size_t size) {
374 for (
size_t i = 0; i < size; ++i) {
380 assert(list !=
NULL);
383 for (
size_t i = 0; i < list->
size / 2; ++i) {
386 void *
const x =
INDEX_TO(list, a, item_size);
387 void *
const y =
INDEX_TO(list, b, item_size);
393 assert(list !=
NULL);
404 assert(list !=
NULL);
410 assert(list !=
NULL);
411 assert(list->
size > 0);
412 assert(into !=
NULL);
416 void *
const to_pop =
INDEX_TO(list, slot, item_size);
418 memcpy(into, to_pop, item_size);
426 assert(list !=
NULL);
427 assert(list->
size > 0);
428 assert(into !=
NULL);
432 void *
const to_pop =
INDEX_TO(list, slot, item_size);
434 memcpy(into, to_pop, item_size);
442 assert(list !=
NULL);
443 assert(datap !=
NULL);
446 memcpy(datap, &list->
base,
sizeof(
void *));
Memory allocation wrappers that exit on failure.
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
static void * gv_calloc(size_t nmemb, size_t size)
macros for interacting with Address Sanitizer
#define ASAN_POISON(addr, size)
#define ASAN_UNPOISON(addr, size)
static NORETURN void graphviz_exit(int status)
static int cmp(const void *key, const void *candidate)
require define api prefix
Arithmetic helper functions.
internal implementation details of list.h
static void exchange(void *a, void *b, size_t size)
list_t_ gv_list_copy_(const list_t_ list, size_t item_size)
bool gv_list_try_append_(list_t_ *list, const void *item, size_t item_size)
static const void * slot_from_const_list(const list_t_ *list, size_t index, size_t stride)
size_t gv_list_prepend_slot_(list_t_ *list, size_t item_size)
void gv_list_pop_front_(list_t_ *list, void *into, size_t item_size)
static const void * slot_from_const_base(const void *base, size_t index, size_t stride)
#define INDEX_TO(origin, index, stride)
bool gv_list_contains_(const list_t_ list, const void *needle, size_t item_size)
size_t gv_list_append_slot_(list_t_ *list, size_t item_size)
void gv_list_reserve_(list_t_ *list, size_t capacity, size_t item_size)
void gv_list_free_(list_t_ *list)
static void * slot_from_base(void *base, size_t index, size_t stride)
void gv_list_clear_(list_t_ *list, size_t item_size)
void gv_list_detach_(list_t_ *list, void *datap, size_t *sizep, size_t item_size)
void gv_list_shrink_to_fit_(list_t_ *list, size_t item_size)
void gv_list_sort_(list_t_ *list, int(*cmp)(const void *, const void *), size_t item_size)
void gv_list_reverse_(list_t_ *list, size_t item_size)
static UNUSED bool is_contiguous(const list_t_ list)
void gv_list_pop_back_(list_t_ *list, void *into, size_t item_size)
size_t gv_list_find_(const list_t_ list, const void *needle, size_t item_size)
void gv_list_sync_(list_t_ *list, size_t item_size)
static int try_reserve(list_t_ *list, size_t capacity, size_t item_size)
static void * slot_from_list(list_t_ *list, size_t index, size_t stride)
void gv_list_remove_(list_t_ *list, size_t index, size_t item_size)
size_t gv_list_get_(const list_t_ list, size_t index)
size_t size
size <= capacity
size_t capacity
available storage slots
void * base
(base == NULL && capacity == 0) || (base != NULL && capacity > 0)
size_t head
(capacity == 0 && head == 0) || (capacity > 0 && head < capacity)
abstraction for squashing compiler warnings for unused symbols