]> git.lizzy.rs Git - nothing.git/blob - src/dynarray.c
Fix corner case for dynarray_insert_before()
[nothing.git] / src / dynarray.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include "system/stacktrace.h"
6 #include "system/lt.h"
7 #include "system/nth_alloc.h"
8 #include "dynarray.h"
9
10 void *dynarray_pointer_at(const Dynarray *dynarray, size_t index)
11 {
12     trace_assert(index < dynarray->count);
13     return (uint8_t *)dynarray->data + index * dynarray->element_size;
14 }
15
16 void dynarray_clear(Dynarray *dynarray)
17 {
18     trace_assert(dynarray);
19     dynarray->count = 0;
20 }
21
22 int dynarray_push(Dynarray *dynarray, const void *element)
23 {
24     trace_assert(dynarray);
25     trace_assert(element);
26     trace_assert(dynarray->count < DYNARRAY_CAPACITY);
27
28     memcpy(
29         (char*) dynarray->data + dynarray->count * dynarray->element_size,
30         element,
31         dynarray->element_size);
32
33     dynarray->count++;
34
35     return 0;
36 }
37
38 bool dynarray_contains(const Dynarray *dynarray,
39                        const void *element)
40 {
41     trace_assert(dynarray);
42     trace_assert(element);
43
44     for (size_t i = 0; i < dynarray->count; ++i) {
45         if (memcmp((const char*)dynarray->data + i * dynarray->element_size,
46                    (const char*)element,
47                    dynarray->element_size) == 0) {
48             return true;
49         }
50     }
51
52     return false;
53 }
54
55 void dynarray_delete_at(Dynarray *dynarray, size_t index)
56 {
57     trace_assert(dynarray);
58     trace_assert(index < dynarray->count);
59     memmove(
60         (uint8_t *) dynarray->data + index * dynarray->element_size,
61         (uint8_t *) dynarray->data + (index + 1) * dynarray->element_size,
62         dynarray->element_size * (dynarray->count - index - 1));
63     dynarray->count--;
64 }
65
66 void dynarray_insert_before(Dynarray *dynarray, size_t index, void *element)
67 {
68     trace_assert(dynarray);
69     trace_assert(dynarray->count < DYNARRAY_CAPACITY);
70     trace_assert(element);
71     trace_assert(index <= dynarray->count);
72
73     if (index == dynarray->count) {
74         dynarray_push(dynarray, element);
75         return;
76     }
77
78     memmove(
79         (uint8_t*) dynarray->data + (index + 1) * dynarray->element_size,
80         (uint8_t*) dynarray->data + index * dynarray->element_size,
81         dynarray->element_size * (dynarray->count - index));
82
83     memcpy(
84         (uint8_t*) dynarray->data + index * dynarray->element_size,
85         element,
86         dynarray->element_size);
87
88     dynarray->count++;
89 }
90
91 int dynarray_push_empty(Dynarray *dynarray)
92 {
93     trace_assert(dynarray);
94     trace_assert(dynarray->count < DYNARRAY_CAPACITY);
95
96     memset(
97         (char*) dynarray->data + dynarray->count * dynarray->element_size,
98         0,
99         dynarray->element_size);
100
101     dynarray->count++;
102
103     return 0;
104 }
105
106 // TODO(#980): dynarray_push and dynarray_push_empty have duplicate codez
107
108 void dynarray_pop(Dynarray *dynarray, void *element)
109 {
110     trace_assert(dynarray);
111     trace_assert(dynarray->count > 0);
112
113     dynarray->count--;
114
115     if (element) {
116         memcpy(
117             element,
118             (uint8_t*) dynarray->data + dynarray->count * dynarray->element_size,
119             dynarray->element_size);
120     }
121 }
122
123 void dynarray_replace_at(Dynarray *dynarray, size_t index, void *element)
124 {
125     trace_assert(dynarray);
126     trace_assert(element);
127     trace_assert(index < dynarray->count);
128
129     memcpy(
130         (uint8_t*) dynarray->data + index * dynarray->element_size,
131         element,
132         dynarray->element_size);
133 }
134
135 void dynarray_copy_to(Dynarray *dynarray, void *dest, size_t index)
136 {
137     trace_assert(dynarray);
138     trace_assert(dest);
139     trace_assert(index < dynarray->count);
140
141     memcpy(dest, (uint8_t*) dynarray->data + index * dynarray->element_size, dynarray->element_size);
142 }
143
144 void dynarray_swap(Dynarray *dynarray, size_t i, size_t j)
145 {
146     trace_assert(dynarray);
147     trace_assert(i < dynarray->count);
148     trace_assert(j < dynarray->count);
149
150     if (i == j) return;
151
152     char *a = dynarray_pointer_at(dynarray, i);
153     char *b = dynarray_pointer_at(dynarray, j);
154
155     for (size_t k = 0; k < dynarray->element_size; ++k) {
156         char t = a[k];
157         a[k] = b[k];
158         b[k] = t;
159     }
160 }