/src/nss-nspr/nss/lib/freebl/verified/eurydice_glue.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #if defined(__cplusplus) |
4 | | extern "C" { |
5 | | #endif |
6 | | |
7 | | #include <inttypes.h> |
8 | | #include <stdbool.h> |
9 | | #include <stdio.h> |
10 | | #include <stdlib.h> |
11 | | #include <string.h> |
12 | | |
13 | | #ifdef _MSC_VER |
14 | | #include <intrin.h> |
15 | | #endif |
16 | | |
17 | | #include "krml/internal/target.h" |
18 | | #include "krml/lowstar_endianness.h" |
19 | | |
20 | | #define LowStar_Ignore_ignore(e, t, _ret_t) ((void)e) |
21 | | |
22 | | // SLICES, ARRAYS, ETC. |
23 | | |
24 | | #if defined(__cplusplus) |
25 | | #define CLITERAL(type) type |
26 | | #else |
27 | 0 | #define CLITERAL(type) (type) |
28 | | #endif |
29 | | |
30 | | // We represent a slice as a pair of an (untyped) pointer, along with the length |
31 | | // of the slice, i.e. the number of elements in the slice (this is NOT the |
32 | | // number of bytes). This design choice has two important consequences. |
33 | | // - if you need to use `ptr`, you MUST cast it to a proper type *before* |
34 | | // performing pointer |
35 | | // arithmetic on it (remember that C desugars pointer arithmetic based on the |
36 | | // type of the address) |
37 | | // - if you need to use `len` for a C style function (e.g. memcpy, memcmp), you |
38 | | // need to multiply it |
39 | | // by sizeof t, where t is the type of the elements. |
40 | | typedef struct { |
41 | | void *ptr; |
42 | | size_t len; |
43 | | } Eurydice_slice; |
44 | | |
45 | | // Helper macro to create a slice out of a pointer x, a start index in x |
46 | | // (included), and an end index in x (excluded). The argument x must be suitably |
47 | | // cast to something that can decay (see remark above about how pointer |
48 | | // arithmetic works in C), meaning either pointer or array type. |
49 | | #define EURYDICE_SLICE(x, start, end) \ |
50 | 0 | (CLITERAL(Eurydice_slice){ .ptr = (void *)(x + start), .len = end - start }) |
51 | 0 | #define EURYDICE_SLICE_LEN(s, _) s.len |
52 | | // This macro is a pain because in case the dereferenced element type is an |
53 | | // array, you cannot simply write `t x` as it would yield `int[4] x` instead, |
54 | | // which is NOT correct C syntax, so we add a dedicated phase in Eurydice that |
55 | | // adds an extra argument to this macro at the last minute so that we have the |
56 | | // correct type of *pointers* to elements. |
57 | 0 | #define Eurydice_slice_index(s, i, t, t_ptr_t) (((t_ptr_t)s.ptr)[i]) |
58 | | #define Eurydice_slice_subslice(s, r, t, _) \ |
59 | | EURYDICE_SLICE((t *)s.ptr, r.start, r.end) |
60 | | // Variant for when the start and end indices are statically known (i.e., the |
61 | | // range argument `r` is a literal). |
62 | | #define Eurydice_slice_subslice2(s, start, end, t) \ |
63 | 0 | EURYDICE_SLICE((t *)s.ptr, start, end) |
64 | | #define Eurydice_slice_subslice_to(s, subslice_end_pos, t, _) \ |
65 | 0 | EURYDICE_SLICE((t *)s.ptr, 0, subslice_end_pos) |
66 | | #define Eurydice_slice_subslice_from(s, subslice_start_pos, t, _) \ |
67 | 0 | EURYDICE_SLICE((t *)s.ptr, subslice_start_pos, s.len) |
68 | | #define Eurydice_array_to_slice(end, x, t) \ |
69 | 0 | EURYDICE_SLICE(x, 0, \ |
70 | 0 | end) /* x is already at an array type, no need for cast */ |
71 | | #define Eurydice_array_to_subslice(_arraylen, x, r, t, _) \ |
72 | | EURYDICE_SLICE((t *)x, r.start, r.end) |
73 | | // Same as above, variant for when start and end are statically known |
74 | | #define Eurydice_array_to_subslice2(x, start, end, t) \ |
75 | 0 | EURYDICE_SLICE((t *)x, start, end) |
76 | | #define Eurydice_array_to_subslice_to(_size, x, r, t, _range_t) \ |
77 | 0 | EURYDICE_SLICE((t *)x, 0, r) |
78 | | #define Eurydice_array_to_subslice_from(size, x, r, t, _range_t) \ |
79 | 0 | EURYDICE_SLICE((t *)x, r, size) |
80 | | #define Eurydice_array_repeat(dst, len, init, t) \ |
81 | | ERROR "should've been desugared" |
82 | 0 | #define Eurydice_slice_len(s, t) EURYDICE_SLICE_LEN(s, t) |
83 | | #define Eurydice_slice_copy(dst, src, t) \ |
84 | 0 | memcpy(dst.ptr, src.ptr, dst.len * sizeof(t)) |
85 | | #define core_array___Array_T__N__23__as_slice(len_, ptr_, t, _ret_t) \ |
86 | | ((Eurydice_slice){ .ptr = ptr_, .len = len_ }) |
87 | | |
88 | | #define core_array___core__clone__Clone_for__Array_T__N___20__clone( \ |
89 | | len, src, dst, elem_type, _ret_t) \ |
90 | | (memcpy(dst, src, len * sizeof(elem_type))) |
91 | | #define core_array_TryFromSliceError uint8_t |
92 | | |
93 | | #define Eurydice_array_eq(sz, a1, a2, t, _) \ |
94 | 0 | (memcmp(a1, a2, sz * sizeof(t)) == 0) |
95 | | #define core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq( \ |
96 | | sz, a1, a2, t, _, _ret_t) \ |
97 | 0 | Eurydice_array_eq(sz, a1, a2, t, _) |
98 | | #define core_array_equality___core__cmp__PartialEq__0___Slice_U____for__Array_T__N___3__eq( \ |
99 | | sz, a1, a2, t, _, _ret_t) \ |
100 | 0 | Eurydice_array_eq(sz, a1, ((a2)->ptr), t, _) |
101 | | |
102 | | #define Eurydice_slice_split_at(slice, mid, element_type, ret_t) \ |
103 | 0 | (CLITERAL(ret_t){ \ |
104 | 0 | .fst = EURYDICE_SLICE((element_type *)slice.ptr, 0, mid), \ |
105 | 0 | .snd = EURYDICE_SLICE((element_type *)slice.ptr, mid, slice.len) }) |
106 | | #define Eurydice_slice_split_at_mut(slice, mid, element_type, ret_t) \ |
107 | 0 | (CLITERAL(ret_t){ \ |
108 | 0 | .fst = { .ptr = slice.ptr, .len = mid }, \ |
109 | 0 | .snd = { .ptr = (char *)slice.ptr + mid * sizeof(element_type), \ |
110 | 0 | .len = slice.len - mid } }) |
111 | | |
112 | | // Conversion of slice to an array, rewritten (by Eurydice) to name the |
113 | | // destination array, since arrays are not values in C. |
114 | | // N.B.: see note in karamel/lib/Inlining.ml if you change this. |
115 | | #define Eurydice_slice_to_array2(dst, src, _, t_arr) \ |
116 | 0 | Eurydice_slice_to_array3(&(dst)->tag, (char *)&(dst)->val.case_Ok, src, \ |
117 | 0 | sizeof(t_arr)) |
118 | | |
119 | | static inline void |
120 | | Eurydice_slice_to_array3(uint8_t *dst_tag, char *dst_ok, |
121 | | Eurydice_slice src, size_t sz) |
122 | 0 | { |
123 | 0 | *dst_tag = 0; |
124 | 0 | memcpy(dst_ok, src.ptr, sz); |
125 | 0 | } Unexecuted instantiation: kyber.c:Eurydice_slice_to_array3 Unexecuted instantiation: libcrux_mlkem768_portable.c:Eurydice_slice_to_array3 Unexecuted instantiation: libcrux_mlkem_portable.c:Eurydice_slice_to_array3 Unexecuted instantiation: libcrux_core.c:Eurydice_slice_to_array3 |
126 | | |
127 | | // CORE STUFF (conversions, endianness, ...) |
128 | | |
129 | | static inline void |
130 | | core_num__u32_8__to_be_bytes(uint32_t src, uint8_t dst[4]) |
131 | 0 | { |
132 | 0 | // TODO: why not store32_be? |
133 | 0 | uint32_t x = htobe32(src); |
134 | 0 | memcpy(dst, &x, 4); |
135 | 0 | } Unexecuted instantiation: kyber.c:core_num__u32_8__to_be_bytes Unexecuted instantiation: libcrux_mlkem768_portable.c:core_num__u32_8__to_be_bytes Unexecuted instantiation: libcrux_mlkem_portable.c:core_num__u32_8__to_be_bytes Unexecuted instantiation: libcrux_core.c:core_num__u32_8__to_be_bytes |
136 | | |
137 | | static inline uint32_t |
138 | | core_num__u32_8__from_le_bytes(uint8_t buf[4]) |
139 | 0 | { |
140 | 0 | return load32_le(buf); |
141 | 0 | } Unexecuted instantiation: kyber.c:core_num__u32_8__from_le_bytes Unexecuted instantiation: libcrux_mlkem768_portable.c:core_num__u32_8__from_le_bytes Unexecuted instantiation: libcrux_mlkem_portable.c:core_num__u32_8__from_le_bytes Unexecuted instantiation: libcrux_core.c:core_num__u32_8__from_le_bytes |
142 | | |
143 | | static inline void |
144 | | core_num__u64_9__to_le_bytes(uint64_t v, uint8_t buf[8]) |
145 | 0 | { |
146 | 0 | store64_le(buf, v); |
147 | 0 | } Unexecuted instantiation: kyber.c:core_num__u64_9__to_le_bytes Unexecuted instantiation: libcrux_mlkem768_portable.c:core_num__u64_9__to_le_bytes Unexecuted instantiation: libcrux_mlkem_portable.c:core_num__u64_9__to_le_bytes Unexecuted instantiation: libcrux_core.c:core_num__u64_9__to_le_bytes |
148 | | static inline uint64_t |
149 | | core_num__u64_9__from_le_bytes(uint8_t buf[8]) |
150 | 0 | { |
151 | 0 | return load64_le(buf); |
152 | 0 | } Unexecuted instantiation: kyber.c:core_num__u64_9__from_le_bytes Unexecuted instantiation: libcrux_mlkem768_portable.c:core_num__u64_9__from_le_bytes Unexecuted instantiation: libcrux_mlkem_portable.c:core_num__u64_9__from_le_bytes Unexecuted instantiation: libcrux_core.c:core_num__u64_9__from_le_bytes |
153 | | |
154 | | static inline int64_t |
155 | | core_convert_num___core__convert__From_i32__for_i64__59__from(int32_t x) |
156 | 0 | { |
157 | 0 | return x; |
158 | 0 | } Unexecuted instantiation: kyber.c:core_convert_num___core__convert__From_i32__for_i64__59__from Unexecuted instantiation: libcrux_mlkem768_portable.c:core_convert_num___core__convert__From_i32__for_i64__59__from Unexecuted instantiation: libcrux_mlkem_portable.c:core_convert_num___core__convert__From_i32__for_i64__59__from Unexecuted instantiation: libcrux_core.c:core_convert_num___core__convert__From_i32__for_i64__59__from |
159 | | |
160 | | static inline uint64_t |
161 | | core_convert_num___core__convert__From_u8__for_u64__66__from(uint8_t x) |
162 | 0 | { |
163 | 0 | return x; |
164 | 0 | } Unexecuted instantiation: kyber.c:core_convert_num___core__convert__From_u8__for_u64__66__from Unexecuted instantiation: libcrux_mlkem768_portable.c:core_convert_num___core__convert__From_u8__for_u64__66__from Unexecuted instantiation: libcrux_mlkem_portable.c:core_convert_num___core__convert__From_u8__for_u64__66__from Unexecuted instantiation: libcrux_core.c:core_convert_num___core__convert__From_u8__for_u64__66__from |
165 | | |
166 | | static inline uint64_t |
167 | | core_convert_num___core__convert__From_u16__for_u64__70__from(uint16_t x) |
168 | 0 | { |
169 | 0 | return x; |
170 | 0 | } Unexecuted instantiation: kyber.c:core_convert_num___core__convert__From_u16__for_u64__70__from Unexecuted instantiation: libcrux_mlkem768_portable.c:core_convert_num___core__convert__From_u16__for_u64__70__from Unexecuted instantiation: libcrux_mlkem_portable.c:core_convert_num___core__convert__From_u16__for_u64__70__from Unexecuted instantiation: libcrux_core.c:core_convert_num___core__convert__From_u16__for_u64__70__from |
171 | | |
172 | | static inline size_t |
173 | | core_convert_num___core__convert__From_u16__for_usize__96__from(uint16_t x) |
174 | 0 | { |
175 | 0 | return x; |
176 | 0 | } Unexecuted instantiation: kyber.c:core_convert_num___core__convert__From_u16__for_usize__96__from Unexecuted instantiation: libcrux_mlkem768_portable.c:core_convert_num___core__convert__From_u16__for_usize__96__from Unexecuted instantiation: libcrux_mlkem_portable.c:core_convert_num___core__convert__From_u16__for_usize__96__from Unexecuted instantiation: libcrux_core.c:core_convert_num___core__convert__From_u16__for_usize__96__from |
177 | | |
178 | | static inline uint32_t |
179 | | core_num__u8_6__count_ones(uint8_t x0) |
180 | 0 | { |
181 | 0 | #ifdef _MSC_VER |
182 | 0 | return __popcnt(x0); |
183 | 0 | #else |
184 | 0 | return __builtin_popcount(x0); |
185 | 0 | #endif |
186 | 0 | } Unexecuted instantiation: kyber.c:core_num__u8_6__count_ones Unexecuted instantiation: libcrux_mlkem768_portable.c:core_num__u8_6__count_ones Unexecuted instantiation: libcrux_mlkem_portable.c:core_num__u8_6__count_ones Unexecuted instantiation: libcrux_core.c:core_num__u8_6__count_ones |
187 | | |
188 | | // unsigned overflow wraparound semantics in C |
189 | | static inline uint16_t |
190 | | core_num__u16_7__wrapping_add(uint16_t x, uint16_t y) |
191 | 0 | { |
192 | 0 | return x + y; |
193 | 0 | } Unexecuted instantiation: kyber.c:core_num__u16_7__wrapping_add Unexecuted instantiation: libcrux_mlkem768_portable.c:core_num__u16_7__wrapping_add Unexecuted instantiation: libcrux_mlkem_portable.c:core_num__u16_7__wrapping_add Unexecuted instantiation: libcrux_core.c:core_num__u16_7__wrapping_add |
194 | | static inline uint8_t |
195 | | core_num__u8_6__wrapping_sub(uint8_t x, uint8_t y) |
196 | 0 | { |
197 | 0 | return x - y; |
198 | 0 | } Unexecuted instantiation: kyber.c:core_num__u8_6__wrapping_sub Unexecuted instantiation: libcrux_mlkem768_portable.c:core_num__u8_6__wrapping_sub Unexecuted instantiation: libcrux_mlkem_portable.c:core_num__u8_6__wrapping_sub Unexecuted instantiation: libcrux_core.c:core_num__u8_6__wrapping_sub |
199 | | |
200 | | static inline void |
201 | | core_ops_arith__i32_319__add_assign(int32_t *x0, |
202 | | int32_t *x1) |
203 | 0 | { |
204 | 0 | *x0 = *x0 + *x1; |
205 | 0 | } Unexecuted instantiation: kyber.c:core_ops_arith__i32_319__add_assign Unexecuted instantiation: libcrux_mlkem768_portable.c:core_ops_arith__i32_319__add_assign Unexecuted instantiation: libcrux_mlkem_portable.c:core_ops_arith__i32_319__add_assign Unexecuted instantiation: libcrux_core.c:core_ops_arith__i32_319__add_assign |
206 | | |
207 | | static inline uint8_t |
208 | | Eurydice_bitand_pv_u8(uint8_t *p, uint8_t v) |
209 | 0 | { |
210 | 0 | return (*p) & v; |
211 | 0 | } Unexecuted instantiation: kyber.c:Eurydice_bitand_pv_u8 Unexecuted instantiation: libcrux_mlkem768_portable.c:Eurydice_bitand_pv_u8 Unexecuted instantiation: libcrux_mlkem_portable.c:Eurydice_bitand_pv_u8 Unexecuted instantiation: libcrux_core.c:Eurydice_bitand_pv_u8 |
212 | | static inline uint8_t |
213 | | Eurydice_shr_pv_u8(uint8_t *p, int32_t v) |
214 | 0 | { |
215 | 0 | return (*p) >> v; |
216 | 0 | } Unexecuted instantiation: kyber.c:Eurydice_shr_pv_u8 Unexecuted instantiation: libcrux_mlkem768_portable.c:Eurydice_shr_pv_u8 Unexecuted instantiation: libcrux_mlkem_portable.c:Eurydice_shr_pv_u8 Unexecuted instantiation: libcrux_core.c:Eurydice_shr_pv_u8 |
217 | | |
218 | | #define core_num_nonzero_private_NonZeroUsizeInner size_t |
219 | | static inline core_num_nonzero_private_NonZeroUsizeInner |
220 | | core_num_nonzero_private___core__clone__Clone_for_core__num__nonzero__private__NonZeroUsizeInner__26__clone( |
221 | | core_num_nonzero_private_NonZeroUsizeInner *x0) |
222 | 0 | { |
223 | 0 | return *x0; |
224 | 0 | } Unexecuted instantiation: kyber.c:core_num_nonzero_private___core__clone__Clone_for_core__num__nonzero__private__NonZeroUsizeInner__26__clone Unexecuted instantiation: libcrux_mlkem768_portable.c:core_num_nonzero_private___core__clone__Clone_for_core__num__nonzero__private__NonZeroUsizeInner__26__clone Unexecuted instantiation: libcrux_mlkem_portable.c:core_num_nonzero_private___core__clone__Clone_for_core__num__nonzero__private__NonZeroUsizeInner__26__clone Unexecuted instantiation: libcrux_core.c:core_num_nonzero_private___core__clone__Clone_for_core__num__nonzero__private__NonZeroUsizeInner__26__clone |
225 | | |
226 | | // ITERATORS |
227 | | #define Eurydice_range_iter_next(iter_ptr, t, ret_t) \ |
228 | 0 | (((iter_ptr)->start == (iter_ptr)->end) \ |
229 | 0 | ? (CLITERAL(ret_t){ .tag = core_option_None }) \ |
230 | 0 | : (CLITERAL(ret_t){ .tag = core_option_Some, \ |
231 | 0 | .f0 = (iter_ptr)->start++ })) |
232 | | |
233 | | // Old name (TODO: remove once everyone has upgraded to the latest Charon) |
234 | | #define core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___3__next \ |
235 | | Eurydice_range_iter_next |
236 | | |
237 | | #define core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A___6__next \ |
238 | 0 | Eurydice_range_iter_next |
239 | | |
240 | | // See note in karamel/lib/Inlining.ml if you change this |
241 | 0 | #define Eurydice_into_iter(x, t, _ret_t) (x) |
242 | | #define core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter \ |
243 | | Eurydice_into_iter |
244 | | // This name changed on 20240627 |
245 | | #define core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter \ |
246 | 0 | Eurydice_into_iter |
247 | | |
248 | | typedef struct { |
249 | | Eurydice_slice slice; |
250 | | size_t chunk_size; |
251 | | } Eurydice_chunks; |
252 | | |
253 | | // Can't use macros Eurydice_slice_subslice_{to,from} because they require a |
254 | | // type, and this static inline function cannot receive a type as an argument. |
255 | | // Instead, we receive the element size and use it to peform manual offset |
256 | | // computations rather than going through the macros. |
257 | | static inline Eurydice_slice |
258 | | chunk_next(Eurydice_chunks *chunks, |
259 | | size_t element_size) |
260 | 0 | { |
261 | 0 | size_t chunk_size = chunks->slice.len >= chunks->chunk_size |
262 | 0 | ? chunks->chunk_size |
263 | 0 | : chunks->slice.len; |
264 | 0 | Eurydice_slice curr_chunk; |
265 | 0 | curr_chunk.ptr = chunks->slice.ptr; |
266 | 0 | curr_chunk.len = chunk_size; |
267 | 0 | chunks->slice.ptr = (char *)(chunks->slice.ptr) + chunk_size * element_size; |
268 | 0 | chunks->slice.len = chunks->slice.len - chunk_size; |
269 | 0 | return curr_chunk; |
270 | 0 | } Unexecuted instantiation: kyber.c:chunk_next Unexecuted instantiation: libcrux_mlkem768_portable.c:chunk_next Unexecuted instantiation: libcrux_mlkem_portable.c:chunk_next Unexecuted instantiation: libcrux_core.c:chunk_next |
271 | | |
272 | | #define core_slice___Slice_T___chunks(slice_, sz_, t, _ret_t) \ |
273 | | ((Eurydice_chunks){ .slice = slice_, .chunk_size = sz_ }) |
274 | | #define core_slice___Slice_T___chunks_exact(slice_, sz_, t, _ret_t) \ |
275 | | ((Eurydice_chunks){ \ |
276 | | .slice = { .ptr = slice_.ptr, .len = slice_.len - (slice_.len % sz_) }, \ |
277 | | .chunk_size = sz_ }) |
278 | | #define core_slice_iter_Chunks Eurydice_chunks |
279 | | #define core_slice_iter_ChunksExact Eurydice_chunks |
280 | | #define Eurydice_chunks_next(iter, t, ret_t) \ |
281 | | (((iter)->slice.len == 0) ? ((ret_t){ .tag = core_option_None }) \ |
282 | | : ((ret_t){ .tag = core_option_Some, \ |
283 | | .f0 = chunk_next(iter, sizeof(t)) })) |
284 | | #define core_slice_iter___core__iter__traits__iterator__Iterator_for_core__slice__iter__Chunks__a__T___70__next \ |
285 | | Eurydice_chunks_next |
286 | | // This name changed on 20240627 |
287 | | #define core_slice_iter___core__iter__traits__iterator__Iterator_for_core__slice__iter__Chunks__a__T___71__next \ |
288 | | Eurydice_chunks_next |
289 | | #define core_slice_iter__core__slice__iter__ChunksExact__a__T__89__next( \ |
290 | | iter, t, _ret_t) \ |
291 | | core_slice_iter__core__slice__iter__Chunks__a__T__70__next(iter, t) |
292 | | |
293 | | typedef struct { |
294 | | Eurydice_slice s; |
295 | | size_t index; |
296 | | } Eurydice_slice_iterator; |
297 | | |
298 | | #define core_slice___Slice_T___iter(x, t, _ret_t) \ |
299 | | ((Eurydice_slice_iterator){ .s = x, .index = 0 }) |
300 | | #define core_slice_iter_Iter Eurydice_slice_iterator |
301 | | #define core_slice_iter__core__slice__iter__Iter__a__T__181__next(iter, t, \ |
302 | | ret_t) \ |
303 | | (((iter)->index == (iter)->s.len) \ |
304 | | ? (CLITERAL(ret_t){ .tag = core_option_None }) \ |
305 | | : (CLITERAL(ret_t){ \ |
306 | | .tag = core_option_Some, \ |
307 | | .f0 = ((iter)->index++, \ |
308 | | &((t *)((iter)->s.ptr))[(iter)->index - 1]) })) |
309 | | |
310 | | // STRINGS |
311 | | |
312 | | typedef const char *Prims_string; |
313 | | |
314 | | // MISC (UNTESTED) |
315 | | |
316 | | typedef void *core_fmt_Formatter; |
317 | | typedef void *core_fmt_Arguments; |
318 | | typedef void *core_fmt_rt_Argument; |
319 | | #define core_fmt_rt__core__fmt__rt__Argument__a__1__new_display(x1, x2, x3, \ |
320 | | x4) \ |
321 | | NULL |
322 | | |
323 | | // VECTORS (ANCIENT, POSSIBLY UNTESTED) |
324 | | |
325 | | /* For now these are passed by value -- three words. We could conceivably change |
326 | | * the representation to heap-allocate this struct and only pass around the |
327 | | * pointer (one word). */ |
328 | | typedef struct { |
329 | | void *ptr; |
330 | | size_t len; /* the number of elements */ |
331 | | size_t alloc_size; /* the size of the allocation, in number of BYTES */ |
332 | | } Eurydice_vec_s, *Eurydice_vec; |
333 | | |
334 | | /* Here, we set everything to zero rather than use a non-standard GCC |
335 | | * statement-expression -- this suitably initializes ptr to NULL and len and |
336 | | * size to 0. */ |
337 | | #define EURYDICE_VEC_NEW(_) calloc(1, sizeof(Eurydice_vec_s)) |
338 | | #define EURYDICE_VEC_PUSH(v, x, t) \ |
339 | | do { \ |
340 | | /* Grow the vector if capacity has been reached. */ \ |
341 | | if (v->len == v->alloc_size / sizeof(t)) { \ |
342 | | /* Assuming that this does not exceed SIZE_MAX, because code proven \ |
343 | | * correct by Aeneas. Would this even happen in practice? */ \ |
344 | | size_t new_size; \ |
345 | | if (v->alloc_size == 0) \ |
346 | | new_size = 8 * sizeof(t); \ |
347 | | else if (v->alloc_size <= SIZE_MAX / 2) \ |
348 | | /* TODO: discuss growth policy */ \ |
349 | | new_size = 2 * v->alloc_size; \ |
350 | | else \ |
351 | | new_size = (SIZE_MAX / sizeof(t)) * sizeof(t); \ |
352 | | v->ptr = realloc(v->ptr, new_size); \ |
353 | | v->alloc_size = new_size; \ |
354 | | } \ |
355 | | ((t *)v->ptr)[v->len] = x; \ |
356 | | v->len++; \ |
357 | | } while (0) |
358 | | |
359 | | #define EURYDICE_VEC_DROP(v, t) \ |
360 | | do { \ |
361 | | free(v->ptr); \ |
362 | | free(v); \ |
363 | | } while (0) |
364 | | |
365 | | #define EURYDICE_VEC_INDEX(v, i, t) &((t *)v->ptr)[i] |
366 | | #define EURYDICE_VEC_LEN(v, t) (v)->len |
367 | | |
368 | | /* TODO: remove GCC-isms */ |
369 | | #define EURYDICE_BOX_NEW(x, t) \ |
370 | | ({ \ |
371 | | t *p = malloc(sizeof(t)); \ |
372 | | *p = x; \ |
373 | | p; \ |
374 | | }) |
375 | | |
376 | | #define EURYDICE_REPLACE(ptr, new_v, t) \ |
377 | | ({ \ |
378 | | t old_v = *ptr; \ |
379 | | *ptr = new_v; \ |
380 | | old_v; \ |
381 | | }) |
382 | | |
383 | | #if defined(__cplusplus) |
384 | | } |
385 | | #endif |