Subastra
Loading...
Searching...
No Matches
list.h
Go to the documentation of this file.
1#ifndef __H__LIST__
2#define __H__LIST__
3
4#include <memory.h>
5#include <sanitizer/asan_interface.h>
6#include <string.h>
7
8#include "defs.h"
9#include "memory.h"
10
11#define LIST_DEFAULT_CAPACITY 6
12
21
23 sz entry_size, sz capacity) {
24 ls->_alloc = alloc;
25 ls->_entry = entry_size;
26 ls->_capacity = capacity;
27 ls->data = allocator_alloc(alloc, entry_size * ls->_capacity);
28 ls->size = 0;
29 poison_memory_region(ls->data, ls->_capacity * entry_size);
30}
31
32static void list_init(list_t *ls, allocator_t alloc, sz entry_size) {
33 list_init_with_capacity(ls, alloc, entry_size, LIST_DEFAULT_CAPACITY);
34}
35
36#define list_init_ty(ty, ls, alloc) list_init(ls, alloc, sizeof(ty))
37
38#define list_init_ty_with_capacity(ty, ls, alloc, capacity) \
39 list_init_with_capacity(ls, alloc, sizeof(ty), capacity)
40
41static void list_init_copy(list_t *ls, allocator_t alloc, void *data,
42 sz entry_size, sz count) {
43 ls->_alloc = alloc;
44 ls->_entry = entry_size;
45 ls->_capacity = count;
46 ls->data = allocator_alloc_copy(alloc, data, count * entry_size);
47 ls->size = count;
48 poison_memory_region(ls->data, ls->size * entry_size);
49}
50
51#define list_init_copy_ty(ty, ls, alloc, data, count) \
52 list_init_copy(ls, alloc, data, sizeof(ty), count)
53
54static void list_init_int(list_t *ls, allocator_t alloc) {
55 list_init(ls, alloc, sizeof(i32));
56}
57
58// Grow the internal container and leave
59// room for at least one extra item
60static void list_grow(list_t *ls) {
61 // Duplicate of Python's logic
62 sz new_capacity = (ls->_capacity >> 3) + ls->_capacity + 6;
63
65
66 ls->data = allocator_realloc(ls->_alloc, ls->data, new_capacity * ls->_entry);
67 ls->_capacity = new_capacity;
68
70}
71
72static void list_push(list_t *ls, const void *data) {
73 if (ls->size == ls->_capacity)
74 list_grow(ls);
75 char *ptr = (char *)ls->data + ls->size * ls->_entry;
76
78
79 memcpy(ptr, data, ls->_entry);
80 ls->size++;
81}
82
83#define list_push_var(ls, var) \
84 ASSERT(sizeof(var) == (ls)->_entry, \
85 "Attempt to push a variable of size %ld into a list that expects " \
86 "size %ld", \
87 sizeof(var), (ls)->_entry); \
88 list_push(ls, &var)
89
90static void list_insert(list_t *ls, sz idx, const void *data) {
91 if (ls->size == ls->_capacity)
92 list_grow(ls);
93
94 if (idx == ls->size) {
95 list_push(ls, data);
96 return;
97 }
98
99 ASSERT(
100 idx < ls->size,
101 "Insertion index must be less must be within the list (idx=%d size=%d)",
102 (int)idx, (int)ls->size);
103
104 unpoison_memory_region((char *)ls->data + ls->size * ls->_entry, ls->_entry);
105
106 sz count_to_move = ls->size - idx;
107 memmove(&((char *)ls->data)[(idx + 1) * ls->_entry],
108 &((char *)ls->data)[idx * ls->_entry], count_to_move * ls->_entry);
109 memcpy(&((char *)ls->data)[idx * ls->_entry], data, ls->_entry);
110 ls->size++;
111}
112
113static void list_push_int(list_t *ls, const i32 value) {
114 ASSERT(sizeof(value) == ls->_entry,
115 "Size of a pushed value (%d) must match the entry size defined at "
116 "initilization (%d)",
117 value, (int)ls->_entry);
118
119 list_push(ls, &value);
120}
121
122static void *list_get(list_t *ls, sz idx) {
123 ASSERT(idx < ls->size, "Index %ld too large (size=%ld)", idx, ls->size);
124
125 return (void *)(&((char *)ls->data)[idx * ls->_entry]);
126}
127
128#define list_get_ty_ptr(ty, ls, idx) ((ty *)list_get(ls, idx))
129
130#define list_get_ty(ty, ls, idx) (*list_get_ty_ptr(ty, ls, idx))
131
137static bool list_pop_tail(list_t *ls, void *out) {
138 if (ls->size == 0)
139 return false;
140 if (out)
141 memcpy(out, list_get(ls, ls->size - 1), ls->_entry);
142 ls->size--;
143 return true;
144}
145
149static void list_remove(list_t *ls, sz idx) {
150 ASSERT__(idx < ls->size);
151
152 if (idx == ls->size) {
153 list_pop_tail(ls, 0);
154 }
155
156 byte *data = (byte *)ls->data;
157 byte *tail = data + ls->_entry * (ls->size + idx);
158 memmove(tail, tail + ls->_entry, ls->_entry * (ls->size - idx));
159}
160
161static void list_clear(list_t *ls) {
162 poison_memory_region(ls->data, ls->entry * ls->size);
163 ls->size = 0;
164}
165
166static void list_cleanup(list_t *ls) { allocator_free(ls->_alloc, ls->data); }
167
168#endif
#define ASSERT(expr, msg,...)
Definition defs.h:35
int32_t i32
Definition defs.h:47
#define ASSERT__(expr)
Definition defs.h:21
size_t sz
Definition defs.h:51
static void list_init_int(list_t *ls, allocator_t alloc)
Definition list.h:54
static void list_init(list_t *ls, allocator_t alloc, sz entry_size)
Definition list.h:32
static void list_init_copy(list_t *ls, allocator_t alloc, void *data, sz entry_size, sz count)
Definition list.h:41
static void list_init_with_capacity(list_t *ls, allocator_t alloc, sz entry_size, sz capacity)
Definition list.h:22
static void list_cleanup(list_t *ls)
Definition list.h:166
static void list_push(list_t *ls, const void *data)
Definition list.h:72
static void list_insert(list_t *ls, sz idx, const void *data)
Definition list.h:90
#define LIST_DEFAULT_CAPACITY
Definition list.h:11
static void list_grow(list_t *ls)
Definition list.h:60
static void list_push_int(list_t *ls, const i32 value)
Definition list.h:113
static void * list_get(list_t *ls, sz idx)
Definition list.h:122
static void list_clear(list_t *ls)
Definition list.h:161
#define unpoison_memory_region(ptr, sz)
Makes previously poisoned memory safe again. Idemponent. Pair of poison_memory_region....
Definition memory.h:136
#define poison_memory_region(ptr, sz)
If compiled with a memory sanitizer, any write to the brief selected memory will crash the program....
Definition memory.h:128
A generic allocator type passed by value. Contains a fallback allocator and a set of function pointer...
Definition memory.h:30
Definition list.h:13
void * data
Definition list.h:19
allocator_t _alloc
Definition list.h:14
static void list_remove(list_t *ls, sz idx)
Removes an element at index idx. Panics if the index is out of range.
Definition list.h:149
sz size
Definition list.h:17
sz _capacity
Definition list.h:16
sz _entry
Definition list.h:15
static bool list_pop_tail(list_t *ls, void *out)
Removes the last index in the list. Returns true if the element was removed and false if the list was...
Definition list.h:137