Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | Copyright 2022 - 2025 Joel Svensson svenssonjoel@yahoo.se | ||
3 | Copyright 2022, 2023 Benjamin Vedder | ||
4 | |||
5 | This program is free software: you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation, either version 3 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include "extensions/array_extensions.h" | ||
20 | |||
21 | #include "extensions.h" | ||
22 | #include "symrepr.h" | ||
23 | #include "lbm_memory.h" | ||
24 | |||
25 | #include <math.h> | ||
26 | |||
27 | #ifdef LBM_OPT_ARRAY_EXTENSIONS_SIZE | ||
28 | #pragma GCC optimize ("-Os") | ||
29 | #endif | ||
30 | #ifdef LBM_OPT_ARRAY_EXTENSIONS_SIZE_AGGRESSIVE | ||
31 | #pragma GCC optimize ("-Oz") | ||
32 | #endif | ||
33 | |||
34 | static lbm_uint little_endian = 0; | ||
35 | static lbm_uint big_endian = 0; | ||
36 | |||
37 | static lbm_value array_extension_unsafe_free_array(lbm_value *args, lbm_uint argn); | ||
38 | static lbm_value array_extension_buffer_append_i8(lbm_value *args, lbm_uint argn); | ||
39 | static lbm_value array_extension_buffer_append_i16(lbm_value *args, lbm_uint argn); | ||
40 | static lbm_value array_extension_buffer_append_i32(lbm_value *args, lbm_uint argn); | ||
41 | static lbm_value array_extension_buffer_append_u8(lbm_value *args, lbm_uint argn); | ||
42 | static lbm_value array_extension_buffer_append_u16(lbm_value *args, lbm_uint argn); | ||
43 | static lbm_value array_extension_buffer_append_u24(lbm_value *args, lbm_uint argn); | ||
44 | static lbm_value array_extension_buffer_append_u32(lbm_value *args, lbm_uint argn); | ||
45 | static lbm_value array_extension_buffer_append_f32(lbm_value *args, lbm_uint argn); | ||
46 | |||
47 | static lbm_value array_extension_buffer_get_i8(lbm_value *args, lbm_uint argn); | ||
48 | static lbm_value array_extension_buffer_get_i16(lbm_value *args, lbm_uint argn); | ||
49 | static lbm_value array_extension_buffer_get_i32(lbm_value *args, lbm_uint argn); | ||
50 | static lbm_value array_extension_buffer_get_u8(lbm_value *args, lbm_uint argn); | ||
51 | static lbm_value array_extension_buffer_get_u16(lbm_value *args, lbm_uint argn); | ||
52 | static lbm_value array_extension_buffer_get_u24(lbm_value *args, lbm_uint argn); | ||
53 | static lbm_value array_extension_buffer_get_u32(lbm_value *args, lbm_uint argn); | ||
54 | static lbm_value array_extension_buffer_get_f32(lbm_value *args, lbm_uint argn); | ||
55 | |||
56 | static lbm_value array_extension_buffer_length(lbm_value *args, lbm_uint argn); | ||
57 | |||
58 | static lbm_value array_extensions_bufclear(lbm_value *args, lbm_uint argn); | ||
59 | static lbm_value array_extensions_bufcpy(lbm_value *args, lbm_uint argn); | ||
60 | static lbm_value array_extensions_bufset_bit(lbm_value *args, lbm_uint argn); | ||
61 | |||
62 | 44260 | void lbm_array_extensions_init(void) { | |
63 | |||
64 | 44260 | lbm_add_symbol_const("little-endian", &little_endian); | |
65 | 44260 | lbm_add_symbol_const("big-endian", &big_endian); | |
66 | |||
67 | 44260 | lbm_add_extension("free", array_extension_unsafe_free_array); | |
68 | 44260 | lbm_add_extension("bufset-i8", array_extension_buffer_append_i8); | |
69 | 44260 | lbm_add_extension("bufset-i16", array_extension_buffer_append_i16); | |
70 | 44260 | lbm_add_extension("bufset-i32", array_extension_buffer_append_i32); | |
71 | 44260 | lbm_add_extension("bufset-u8", array_extension_buffer_append_u8); | |
72 | 44260 | lbm_add_extension("bufset-u16", array_extension_buffer_append_u16); | |
73 | 44260 | lbm_add_extension("bufset-u24", array_extension_buffer_append_u24); | |
74 | 44260 | lbm_add_extension("bufset-u32", array_extension_buffer_append_u32); | |
75 | 44260 | lbm_add_extension("bufset-f32", array_extension_buffer_append_f32); | |
76 | |||
77 | 44260 | lbm_add_extension("bufget-i8", array_extension_buffer_get_i8); | |
78 | 44260 | lbm_add_extension("bufget-i16", array_extension_buffer_get_i16); | |
79 | 44260 | lbm_add_extension("bufget-i32", array_extension_buffer_get_i32); | |
80 | 44260 | lbm_add_extension("bufget-u8", array_extension_buffer_get_u8); | |
81 | 44260 | lbm_add_extension("bufget-u16", array_extension_buffer_get_u16); | |
82 | 44260 | lbm_add_extension("bufget-u24", array_extension_buffer_get_u24); | |
83 | 44260 | lbm_add_extension("bufget-u32", array_extension_buffer_get_u32); | |
84 | 44260 | lbm_add_extension("bufget-f32", array_extension_buffer_get_f32); | |
85 | |||
86 | 44260 | lbm_add_extension("buflen", array_extension_buffer_length); | |
87 | 44260 | lbm_add_extension("bufclear", array_extensions_bufclear); | |
88 | 44260 | lbm_add_extension("bufcpy", array_extensions_bufcpy); | |
89 | 44260 | lbm_add_extension("bufset-bit", array_extensions_bufset_bit); | |
90 | 44260 | } | |
91 | |||
92 | 224 | lbm_value array_extension_unsafe_free_array(lbm_value *args, lbm_uint argn) { | |
93 | 224 | lbm_value res = ENC_SYM_EERROR; | |
94 |
1/2✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
|
224 | if (argn == 1) { |
95 |
1/2✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
|
224 | if (lbm_is_array_rw(args[0])) { |
96 |
1/2✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
|
224 | if (lbm_heap_explicit_free_array(args[0])) { |
97 | 224 | res = ENC_SYM_TRUE; | |
98 | } else { | ||
99 | ✗ | res = ENC_SYM_NIL; | |
100 | } | ||
101 | } else { | ||
102 | ✗ | res = ENC_SYM_TERROR; | |
103 | } | ||
104 | } | ||
105 | 224 | return res; | |
106 | } | ||
107 | |||
108 | 119059 | static bool decode_append_args(lbm_value *error, lbm_value *args, lbm_uint argn, lbm_uint *index, bool *be, lbm_uint *a_size, uint8_t **a_data) { | |
109 | 119059 | *be = true; | |
110 | 119059 | *error = ENC_SYM_EERROR; | |
111 | 119059 | bool res = false; | |
112 |
2/3✓ Branch 0 taken 1960 times.
✓ Branch 1 taken 117099 times.
✗ Branch 2 not taken.
|
119059 | switch(argn) { |
113 | 1960 | case 4: | |
114 |
1/2✓ Branch 0 taken 1960 times.
✗ Branch 1 not taken.
|
1960 | if (lbm_type_of(args[3]) == LBM_TYPE_SYMBOL && |
115 |
1/2✓ Branch 0 taken 1960 times.
✗ Branch 1 not taken.
|
1960 | lbm_dec_sym(args[3]) == little_endian) { |
116 | 1960 | *be = false; | |
117 | } | ||
118 | /* fall through */ | ||
119 | case 3: { | ||
120 | 119059 | lbm_array_header_t *array = lbm_dec_array_rw(args[0]); | |
121 |
3/4✓ Branch 0 taken 118891 times.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 118891 times.
✗ Branch 3 not taken.
|
237950 | if(array && |
122 |
1/2✓ Branch 0 taken 118891 times.
✗ Branch 1 not taken.
|
237782 | lbm_is_number(args[1]) && |
123 | 118891 | lbm_is_number(args[2])) { | |
124 | 118891 | *a_size = array->size; | |
125 | 118891 | *a_data = (uint8_t*)array->data; | |
126 | 118891 | *index = lbm_dec_as_u32(args[1]); | |
127 | 118891 | res = true; | |
128 | } else { | ||
129 | 168 | *error = ENC_SYM_TERROR; | |
130 | } | ||
131 | } | ||
132 | } | ||
133 | 119059 | return res; | |
134 | } | ||
135 | |||
136 | 118891 | static bool buffer_append_bytes(uint8_t *data, lbm_uint d_size, bool be, lbm_uint index, lbm_uint nbytes, lbm_uint value) { | |
137 | |||
138 | 118891 | lbm_uint last_index = index + (nbytes - 1); | |
139 | 118891 | bool res = false; | |
140 |
2/2✓ Branch 0 taken 118443 times.
✓ Branch 1 taken 448 times.
|
118891 | if (last_index < d_size) { |
141 | 118443 | res = true; | |
142 |
4/4✓ Branch 0 taken 114577 times.
✓ Branch 1 taken 1289 times.
✓ Branch 2 taken 560 times.
✓ Branch 3 taken 2017 times.
|
118443 | switch(nbytes) { |
143 | 114577 | case 1: | |
144 | 114577 | data[index] = (uint8_t) value; | |
145 | 114577 | break; | |
146 | 1289 | case 2: | |
147 |
2/2✓ Branch 0 taken 729 times.
✓ Branch 1 taken 560 times.
|
1289 | if (be) { |
148 | 729 | data[index+1] = (uint8_t)value; | |
149 | 729 | data[index] = (uint8_t)(value >> 8); | |
150 | } else { | ||
151 | 560 | data[index] = (uint8_t)value; | |
152 | 560 | data[index +1] = (uint8_t)(value >> 8); | |
153 | } | ||
154 | 1289 | break; | |
155 | 560 | case 3: | |
156 |
2/2✓ Branch 0 taken 280 times.
✓ Branch 1 taken 280 times.
|
560 | if (be) { |
157 | 280 | data[index+2] = (uint8_t)value; | |
158 | 280 | data[index+1] = (uint8_t)(value >> 8); | |
159 | 280 | data[index] = (uint8_t)(value >> 16); | |
160 | } else { | ||
161 | 280 | data[index] = (uint8_t)value; | |
162 | 280 | data[index+1] = (uint8_t)(value >> 8); | |
163 | 280 | data[index+2] = (uint8_t)(value >> 16); | |
164 | } | ||
165 | 560 | break; | |
166 | 2017 | default: | |
167 |
2/2✓ Branch 0 taken 1457 times.
✓ Branch 1 taken 560 times.
|
2017 | if (be) { |
168 | 1457 | data[index+3] = (uint8_t) value; | |
169 | 1457 | data[index+2] = (uint8_t) (value >> 8); | |
170 | 1457 | data[index+1] = (uint8_t) (value >> 16); | |
171 | 1457 | data[index] = (uint8_t) (value >> 24); | |
172 | } else { | ||
173 | 560 | data[index] = (uint8_t) value; | |
174 | 560 | data[index+1] = (uint8_t) (value >> 8); | |
175 | 560 | data[index+2] = (uint8_t) (value >> 16); | |
176 | 560 | data[index+3] = (uint8_t) (value >> 24); | |
177 | } | ||
178 | 2017 | break; | |
179 | } | ||
180 | } | ||
181 | 118891 | return res; | |
182 | } | ||
183 | |||
184 | 113512 | lbm_value array_extension_buffer_append_i8(lbm_value *args, lbm_uint argn) { | |
185 | |||
186 | 113512 | lbm_value res = ENC_SYM_EERROR; | |
187 | 113512 | uint8_t *data = NULL; | |
188 | 113512 | lbm_uint d_size = 0; | |
189 | 113512 | bool be = false; | |
190 | 113512 | lbm_uint index = 0; | |
191 | |||
192 |
2/2✓ Branch 0 taken 113344 times.
✓ Branch 1 taken 168 times.
|
113512 | if (decode_append_args(&res, args, argn, &index, &be, &d_size, &data)) { |
193 |
2/2✓ Branch 0 taken 113288 times.
✓ Branch 1 taken 56 times.
|
113344 | if (buffer_append_bytes(data, d_size, be, index, 1, (lbm_uint)lbm_dec_as_i32(args[2]))) { |
194 | 113288 | res = ENC_SYM_TRUE; | |
195 | } | ||
196 | } | ||
197 | 113512 | return res; | |
198 | } | ||
199 | |||
200 | 1176 | lbm_value array_extension_buffer_append_i16(lbm_value *args, lbm_uint argn) { | |
201 | |||
202 | 1176 | lbm_value res = ENC_SYM_EERROR; | |
203 | 1176 | uint8_t *data = NULL; | |
204 | 1176 | lbm_uint d_size = 0; | |
205 | 1176 | bool be = false; | |
206 | 1176 | lbm_uint index = 0; | |
207 | |||
208 |
1/2✓ Branch 0 taken 1176 times.
✗ Branch 1 not taken.
|
1176 | if (decode_append_args(&res, args, argn, &index, &be, &d_size, &data)) { |
209 |
2/2✓ Branch 0 taken 1120 times.
✓ Branch 1 taken 56 times.
|
1176 | if (buffer_append_bytes(data, d_size, be, index, 2, (lbm_uint)lbm_dec_as_i32(args[2]))) { |
210 | 1120 | res = ENC_SYM_TRUE; | |
211 | } | ||
212 | } | ||
213 | 1176 | return res; | |
214 | } | ||
215 | |||
216 | 896 | lbm_value array_extension_buffer_append_i32(lbm_value *args, lbm_uint argn) { | |
217 | |||
218 | 896 | lbm_value res = ENC_SYM_EERROR; | |
219 | 896 | uint8_t *data = NULL; | |
220 | 896 | lbm_uint d_size = 0; | |
221 | 896 | bool be = false; | |
222 | 896 | lbm_uint index = 0; | |
223 | |||
224 |
1/2✓ Branch 0 taken 896 times.
✗ Branch 1 not taken.
|
896 | if (decode_append_args(&res, args, argn, &index, &be, &d_size, &data)) { |
225 |
2/2✓ Branch 0 taken 840 times.
✓ Branch 1 taken 56 times.
|
896 | if (buffer_append_bytes(data, d_size, be, index, 4, (lbm_uint)lbm_dec_as_i32(args[2]))) { |
226 | 840 | res = ENC_SYM_TRUE; | |
227 | } | ||
228 | } | ||
229 | 896 | return res; | |
230 | } | ||
231 | |||
232 | |||
233 | 1345 | lbm_value array_extension_buffer_append_u8(lbm_value *args, lbm_uint argn) { | |
234 | |||
235 | 1345 | lbm_value res = ENC_SYM_EERROR; | |
236 | 1345 | uint8_t *data = NULL; | |
237 | 1345 | lbm_uint d_size = 0; | |
238 | 1345 | bool be = false; | |
239 | 1345 | lbm_uint index = 0; | |
240 | |||
241 |
1/2✓ Branch 0 taken 1345 times.
✗ Branch 1 not taken.
|
1345 | if (decode_append_args(&res, args, argn, &index, &be, &d_size, &data)) { |
242 |
2/2✓ Branch 0 taken 1289 times.
✓ Branch 1 taken 56 times.
|
1345 | if (buffer_append_bytes(data, d_size, be, index, 1, (lbm_uint)lbm_dec_as_u32(args[2]))) { |
243 | 1289 | res = ENC_SYM_TRUE; | |
244 | } | ||
245 | } | ||
246 | 1345 | return res; | |
247 | } | ||
248 | |||
249 | 225 | lbm_value array_extension_buffer_append_u16(lbm_value *args, lbm_uint argn) { | |
250 | |||
251 | 225 | lbm_value res = ENC_SYM_EERROR; | |
252 | 225 | uint8_t *data = NULL; | |
253 | 225 | lbm_uint d_size = 0; | |
254 | 225 | bool be = false; | |
255 | 225 | lbm_uint index = 0; | |
256 | |||
257 |
1/2✓ Branch 0 taken 225 times.
✗ Branch 1 not taken.
|
225 | if (decode_append_args(&res, args, argn, &index, &be, &d_size, &data)) { |
258 |
2/2✓ Branch 0 taken 169 times.
✓ Branch 1 taken 56 times.
|
225 | if (buffer_append_bytes(data, d_size, be, index, 2, (lbm_uint)lbm_dec_as_u32(args[2]))) { |
259 | 169 | res = ENC_SYM_TRUE; | |
260 | } | ||
261 | } | ||
262 | 225 | return res; | |
263 | } | ||
264 | |||
265 | 616 | lbm_value array_extension_buffer_append_u24(lbm_value *args, lbm_uint argn) { | |
266 | |||
267 | 616 | lbm_value res = ENC_SYM_EERROR; | |
268 | 616 | uint8_t *data = NULL; | |
269 | 616 | lbm_uint d_size = 0; | |
270 | 616 | bool be = false; | |
271 | 616 | lbm_uint index = 0; | |
272 | |||
273 |
1/2✓ Branch 0 taken 616 times.
✗ Branch 1 not taken.
|
616 | if (decode_append_args(&res, args, argn, &index, &be, &d_size, &data)) { |
274 |
2/2✓ Branch 0 taken 560 times.
✓ Branch 1 taken 56 times.
|
616 | if (buffer_append_bytes(data, d_size, be, index, 3, (lbm_uint)lbm_dec_as_u32(args[2]))) { |
275 | 560 | res = ENC_SYM_TRUE; | |
276 | } | ||
277 | } | ||
278 | 616 | return res; | |
279 | } | ||
280 | |||
281 | 897 | lbm_value array_extension_buffer_append_u32(lbm_value *args, lbm_uint argn) { | |
282 | |||
283 | 897 | lbm_value res = ENC_SYM_EERROR; | |
284 | 897 | uint8_t *data = NULL; | |
285 | 897 | lbm_uint d_size = 0; | |
286 | 897 | bool be = false; | |
287 | 897 | lbm_uint index = 0; | |
288 | |||
289 |
1/2✓ Branch 0 taken 897 times.
✗ Branch 1 not taken.
|
897 | if (decode_append_args(&res, args, argn, &index, &be, &d_size, &data)) { |
290 |
2/2✓ Branch 0 taken 841 times.
✓ Branch 1 taken 56 times.
|
897 | if (buffer_append_bytes(data, d_size, be, index, 4, (lbm_uint)lbm_dec_as_u32(args[2]))) { |
291 | 841 | res = ENC_SYM_TRUE; | |
292 | } | ||
293 | } | ||
294 | 897 | return res; | |
295 | } | ||
296 | |||
297 | 392 | static lbm_uint float_to_u(float number) { | |
298 | // Set subnormal numbers to 0 as they are not handled properly | ||
299 | // using this method. | ||
300 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 392 times.
|
392 | if (fabsf(number) < 1.5e-38) { |
301 | ✗ | number = 0.0; | |
302 | } | ||
303 | |||
304 | 392 | int e = 0; | |
305 | 392 | float sig = frexpf(number, &e); | |
306 | 392 | float sig_abs = fabsf(sig); | |
307 | 392 | uint32_t sig_i = 0; | |
308 | |||
309 |
1/2✓ Branch 0 taken 392 times.
✗ Branch 1 not taken.
|
392 | if (sig_abs >= 0.5) { |
310 | 392 | sig_i = (uint32_t)((sig_abs - 0.5f) * 2.0f * 8388608.0f); | |
311 | 392 | e += 126; | |
312 | } | ||
313 | |||
314 | 392 | uint32_t res = (((uint32_t)e & 0xFFu) << 23) | (uint32_t)(sig_i & 0x7FFFFFu); | |
315 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 392 times.
|
392 | if (sig < 0) { |
316 | ✗ | res |= 1U << 31; | |
317 | } | ||
318 | |||
319 | 392 | return res; | |
320 | } | ||
321 | |||
322 | 336 | static lbm_float u_to_float(uint32_t v) { | |
323 | |||
324 | 336 | int e = (v >> 23) & 0xFF; | |
325 | 336 | uint32_t sig_i = v & 0x7FFFFF; | |
326 | 336 | bool neg = v & (1U << 31); | |
327 | |||
328 | 336 | float sig = 0.0; | |
329 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
336 | if (e != 0 || sig_i != 0) { |
330 | 336 | sig = (float)sig_i / (8388608.0f * 2.0f) + 0.5f; | |
331 | 336 | e -= 126; | |
332 | } | ||
333 | |||
334 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
|
336 | if (neg) { |
335 | ✗ | sig = -sig; | |
336 | } | ||
337 | |||
338 | 336 | return ldexpf(sig, e); | |
339 | } | ||
340 | |||
341 | 392 | lbm_value array_extension_buffer_append_f32(lbm_value *args, lbm_uint argn) { | |
342 | |||
343 | 392 | lbm_value res = ENC_SYM_EERROR; | |
344 | 392 | uint8_t *data = NULL; | |
345 | 392 | lbm_uint d_size = 0; | |
346 | 392 | bool be = false; | |
347 | 392 | lbm_uint index = 0; | |
348 | |||
349 |
1/2✓ Branch 0 taken 392 times.
✗ Branch 1 not taken.
|
392 | if (decode_append_args(&res, args, argn, &index, &be, &d_size, &data)) { |
350 |
2/2✓ Branch 0 taken 336 times.
✓ Branch 1 taken 56 times.
|
392 | if (buffer_append_bytes(data, d_size, be, index, 4, (lbm_uint)float_to_u(lbm_dec_as_float(args[2])))) { |
351 | 336 | res = ENC_SYM_TRUE; | |
352 | } | ||
353 | } | ||
354 | 392 | return res; | |
355 | } | ||
356 | |||
357 | /* (buffer-get-i8 buffer index) */ | ||
358 | /* (buffer-get-i16 buffer index little-endian) */ | ||
359 | |||
360 | 9925 | static bool decode_get_args(lbm_value *error, lbm_value *args, lbm_uint argn, lbm_uint *index, bool *be, lbm_uint *a_size, uint8_t **a_data) { | |
361 | 9925 | bool res = false; | |
362 | |||
363 | 9925 | *be=true; | |
364 | |||
365 |
2/3✓ Branch 0 taken 2352 times.
✓ Branch 1 taken 7573 times.
✗ Branch 2 not taken.
|
9925 | switch(argn) { |
366 | 2352 | case 3: | |
367 |
1/2✓ Branch 0 taken 2352 times.
✗ Branch 1 not taken.
|
2352 | if (lbm_type_of(args[2]) == LBM_TYPE_SYMBOL && |
368 |
1/2✓ Branch 0 taken 2352 times.
✗ Branch 1 not taken.
|
2352 | lbm_dec_sym(args[2]) == little_endian) { |
369 | 2352 | *be = false; | |
370 | } | ||
371 | /* fall through */ | ||
372 | case 2: { | ||
373 | 9925 | lbm_array_header_t *array = lbm_dec_array_r(args[0]); | |
374 |
2/4✓ Branch 0 taken 9925 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9925 times.
✗ Branch 3 not taken.
|
19850 | if (array && |
375 | 9925 | lbm_is_number(args[1])) { | |
376 | 9925 | *a_size = array->size; | |
377 | 9925 | *a_data = (uint8_t*)array->data; | |
378 | 9925 | *index = lbm_dec_as_u32(args[1]); | |
379 | 9925 | res = true; | |
380 | } else { | ||
381 | ✗ | *error = ENC_SYM_TERROR; | |
382 | } | ||
383 | } | ||
384 | } | ||
385 | 9925 | return res; | |
386 | } | ||
387 | |||
388 | 9925 | static bool buffer_get_uint(lbm_uint *r_value, uint8_t *data, lbm_uint d_size, bool be, lbm_uint index, lbm_uint nbytes) { | |
389 | |||
390 | 9925 | bool res = false; | |
391 | 9925 | lbm_uint last_index = index + (nbytes - 1); | |
392 | |||
393 |
2/2✓ Branch 0 taken 8693 times.
✓ Branch 1 taken 1232 times.
|
9925 | if (last_index < d_size) { |
394 | 8693 | lbm_uint value = 0; | |
395 | 8693 | res = true; | |
396 |
4/5✓ Branch 0 taken 4659 times.
✓ Branch 1 taken 1289 times.
✓ Branch 2 taken 560 times.
✓ Branch 3 taken 2185 times.
✗ Branch 4 not taken.
|
8693 | switch(nbytes) { |
397 | 4659 | case 1: | |
398 | 4659 | value = (lbm_uint)data[index]; | |
399 | 4659 | break; | |
400 | 1289 | case 2: | |
401 |
2/2✓ Branch 0 taken 729 times.
✓ Branch 1 taken 560 times.
|
1289 | if (be) { |
402 | 729 | value = | |
403 | 729 | (lbm_uint) data[index+1] | | |
404 | 729 | (lbm_uint) data[index] << 8; | |
405 | } else { | ||
406 | 560 | value = | |
407 | 560 | (lbm_uint) data[index] | | |
408 | 560 | (lbm_uint) data[index+1] << 8; | |
409 | } | ||
410 | 1289 | break; | |
411 | 560 | case 3: | |
412 |
2/2✓ Branch 0 taken 280 times.
✓ Branch 1 taken 280 times.
|
560 | if (be) { |
413 | 280 | value = | |
414 | 280 | (lbm_uint) data[index+2] | | |
415 | 280 | (lbm_uint) data[index+1] << 8 | | |
416 | 280 | (lbm_uint) data[index] << 16; | |
417 | } else { | ||
418 | 280 | value = | |
419 | 280 | (lbm_uint) data[index] | | |
420 | 280 | (lbm_uint) data[index+1] << 8 | | |
421 | 280 | (lbm_uint) data[index+2] << 16; | |
422 | } | ||
423 | 560 | break; | |
424 | 2185 | case 4: | |
425 |
2/2✓ Branch 0 taken 1625 times.
✓ Branch 1 taken 560 times.
|
2185 | if (be) { |
426 | 1625 | value = | |
427 | 1625 | (uint32_t) data[index+3] | | |
428 | 1625 | (uint32_t) data[index+2] << 8 | | |
429 | 1625 | (uint32_t) data[index+1] << 16 | | |
430 | 1625 | (uint32_t) data[index] << 24; | |
431 | } else { | ||
432 | 560 | value = | |
433 | 560 | (uint32_t) data[index] | | |
434 | 560 | (uint32_t) data[index+1] << 8 | | |
435 | 560 | (uint32_t) data[index+2] << 16 | | |
436 | 560 | (uint32_t) data[index+3] << 24; | |
437 | } | ||
438 | 2185 | break; | |
439 | ✗ | default: | |
440 | ✗ | res = false; | |
441 | } | ||
442 | 8693 | *r_value = value; | |
443 | } | ||
444 | 9925 | return res; | |
445 | } | ||
446 | |||
447 | |||
448 | |||
449 | 2800 | lbm_value array_extension_buffer_get_i8(lbm_value *args, lbm_uint argn) { | |
450 | 2800 | lbm_value res = ENC_SYM_EERROR; | |
451 | 2800 | uint8_t *data = NULL; | |
452 | 2800 | lbm_uint d_size = 0; | |
453 | 2800 | bool be = false; | |
454 | 2800 | lbm_uint index = 0; | |
455 | 2800 | lbm_uint value = 0; | |
456 | |||
457 |
1/2✓ Branch 0 taken 2800 times.
✗ Branch 1 not taken.
|
2800 | if (decode_get_args(&res, args, argn, &index, &be, &d_size, &data)) { |
458 |
2/2✓ Branch 0 taken 2632 times.
✓ Branch 1 taken 168 times.
|
2800 | if (buffer_get_uint(&value, data, d_size, be, index, 1)) { |
459 | 2632 | res =lbm_enc_i((int8_t)value); | |
460 | } | ||
461 | } | ||
462 | 2800 | return res; | |
463 | } | ||
464 | |||
465 | 1400 | lbm_value array_extension_buffer_get_i16(lbm_value *args, lbm_uint argn) { | |
466 | 1400 | lbm_value res = ENC_SYM_EERROR; | |
467 | 1400 | uint8_t *data = NULL; | |
468 | 1400 | lbm_uint d_size = 0; | |
469 | 1400 | bool be = false; | |
470 | 1400 | lbm_uint index = 0; | |
471 | 1400 | lbm_uint value = 0; | |
472 | |||
473 |
1/2✓ Branch 0 taken 1400 times.
✗ Branch 1 not taken.
|
1400 | if (decode_get_args(&res, args, argn, &index, &be, &d_size, &data)) { |
474 |
2/2✓ Branch 0 taken 1120 times.
✓ Branch 1 taken 280 times.
|
1400 | if (buffer_get_uint(&value, data, d_size, be, index, 2)) { |
475 | 1120 | res =lbm_enc_i((int16_t)value); | |
476 | } | ||
477 | } | ||
478 | 1400 | return res; | |
479 | } | ||
480 | |||
481 | 1008 | lbm_value array_extension_buffer_get_i32(lbm_value *args, lbm_uint argn) { | |
482 | 1008 | lbm_value res = ENC_SYM_EERROR; | |
483 | 1008 | uint8_t *data = NULL; | |
484 | 1008 | lbm_uint d_size = 0; | |
485 | 1008 | bool be = false; | |
486 | 1008 | lbm_uint index = 0; | |
487 | 1008 | lbm_uint value = 0; | |
488 | |||
489 |
1/2✓ Branch 0 taken 1008 times.
✗ Branch 1 not taken.
|
1008 | if (decode_get_args(&res, args, argn, &index, &be, &d_size, &data)) { |
490 |
2/2✓ Branch 0 taken 840 times.
✓ Branch 1 taken 168 times.
|
1008 | if (buffer_get_uint(&value, data, d_size, be, index, 4)) { |
491 | 840 | res =lbm_enc_i((int32_t)value); | |
492 | } | ||
493 | } | ||
494 | 1008 | return res; | |
495 | } | ||
496 | |||
497 | 2195 | lbm_value array_extension_buffer_get_u8(lbm_value *args, lbm_uint argn) { | |
498 | 2195 | lbm_value res = ENC_SYM_EERROR; | |
499 | 2195 | uint8_t *data = NULL; | |
500 | 2195 | lbm_uint d_size = 0; | |
501 | 2195 | bool be = false; | |
502 | 2195 | lbm_uint index = 0; | |
503 | 2195 | lbm_uint value = 0; | |
504 | |||
505 |
1/2✓ Branch 0 taken 2195 times.
✗ Branch 1 not taken.
|
2195 | if (decode_get_args(&res, args, argn, &index, &be, &d_size, &data)) { |
506 |
2/2✓ Branch 0 taken 2027 times.
✓ Branch 1 taken 168 times.
|
2195 | if (buffer_get_uint(&value, data, d_size, be, index, 1)) { |
507 | 2027 | res = lbm_enc_i((uint8_t)value); | |
508 | } | ||
509 | } | ||
510 | 2195 | return res; | |
511 | } | ||
512 | |||
513 | 225 | lbm_value array_extension_buffer_get_u16(lbm_value *args, lbm_uint argn) { | |
514 | 225 | lbm_value res = ENC_SYM_EERROR; | |
515 | 225 | uint8_t *data = NULL; | |
516 | 225 | lbm_uint d_size = 0; | |
517 | 225 | bool be = false; | |
518 | 225 | lbm_uint index = 0; | |
519 | 225 | lbm_uint value = 0; | |
520 | |||
521 |
1/2✓ Branch 0 taken 225 times.
✗ Branch 1 not taken.
|
225 | if (decode_get_args(&res, args, argn, &index, &be, &d_size, &data)) { |
522 |
2/2✓ Branch 0 taken 169 times.
✓ Branch 1 taken 56 times.
|
225 | if (buffer_get_uint(&value, data, d_size, be, index, 2)) { |
523 | 169 | res = lbm_enc_i((uint16_t)value); | |
524 | } | ||
525 | } | ||
526 | 225 | return res; | |
527 | } | ||
528 | |||
529 | 728 | lbm_value array_extension_buffer_get_u24(lbm_value *args, lbm_uint argn) { | |
530 | 728 | lbm_value res = ENC_SYM_EERROR; | |
531 | 728 | uint8_t *data = NULL; | |
532 | 728 | lbm_uint d_size = 0; | |
533 | 728 | bool be = false; | |
534 | 728 | lbm_uint index = 0; | |
535 | 728 | lbm_uint value = 0; | |
536 | |||
537 |
1/2✓ Branch 0 taken 728 times.
✗ Branch 1 not taken.
|
728 | if (decode_get_args(&res, args, argn, &index, &be, &d_size, &data)) { |
538 |
2/2✓ Branch 0 taken 560 times.
✓ Branch 1 taken 168 times.
|
728 | if (buffer_get_uint(&value, data, d_size, be, index, 3)) { |
539 | 560 | res = lbm_enc_i((int32_t)value); | |
540 | } | ||
541 | } | ||
542 | 728 | return res; | |
543 | } | ||
544 | |||
545 | 1177 | lbm_value array_extension_buffer_get_u32(lbm_value *args, lbm_uint argn) { | |
546 | 1177 | lbm_value res = ENC_SYM_EERROR; | |
547 | 1177 | uint8_t *data = NULL; | |
548 | 1177 | lbm_uint d_size = 0; | |
549 | 1177 | bool be = false; | |
550 | 1177 | lbm_uint index = 0; | |
551 | 1177 | lbm_uint value = 0; | |
552 | |||
553 |
1/2✓ Branch 0 taken 1177 times.
✗ Branch 1 not taken.
|
1177 | if (decode_get_args(&res, args, argn, &index, &be, &d_size, &data)) { |
554 |
2/2✓ Branch 0 taken 1009 times.
✓ Branch 1 taken 168 times.
|
1177 | if (buffer_get_uint(&value, data, d_size, be, index, 4)) { |
555 | 1009 | res = lbm_enc_u32((uint32_t)value); | |
556 | } | ||
557 | } | ||
558 | 1177 | return res; | |
559 | } | ||
560 | |||
561 | 392 | lbm_value array_extension_buffer_get_f32(lbm_value *args, lbm_uint argn) { | |
562 | 392 | lbm_value res = ENC_SYM_EERROR; | |
563 | 392 | uint8_t *data = NULL; | |
564 | 392 | lbm_uint d_size = 0; | |
565 | 392 | bool be = false; | |
566 | 392 | lbm_uint index = 0; | |
567 | 392 | lbm_uint value = 0; | |
568 | |||
569 |
1/2✓ Branch 0 taken 392 times.
✗ Branch 1 not taken.
|
392 | if (decode_get_args(&res, args, argn, &index, &be, &d_size, &data)) { |
570 |
2/2✓ Branch 0 taken 336 times.
✓ Branch 1 taken 56 times.
|
392 | if (buffer_get_uint(&value, data, d_size, be, index, 4)) { |
571 | 336 | res = lbm_enc_float(u_to_float((uint32_t)value)); | |
572 | } | ||
573 | } | ||
574 | 392 | return res; | |
575 | } | ||
576 | |||
577 | 504 | lbm_value array_extension_buffer_length(lbm_value *args, lbm_uint argn) { | |
578 | 504 | lbm_value res = ENC_SYM_EERROR; | |
579 | lbm_array_header_t *array; | ||
580 |
2/4✓ Branch 0 taken 504 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 504 times.
✗ Branch 3 not taken.
|
1008 | if (argn == 1 && |
581 |
1/2✓ Branch 0 taken 504 times.
✗ Branch 1 not taken.
|
1008 | (array = lbm_dec_array_r(args[0])) && |
582 | 504 | lbm_heap_array_valid(args[0])) { | |
583 | 504 | res = lbm_enc_i((lbm_int)array->size); | |
584 | } | ||
585 | 504 | return res; | |
586 | } | ||
587 | |||
588 | //TODO: Have to think about 32 vs 64 bit here | ||
589 | 1121 | static lbm_value array_extensions_bufclear(lbm_value *args, lbm_uint argn) { | |
590 | 1121 | lbm_value res = ENC_SYM_EERROR; | |
591 |
4/4✓ Branch 0 taken 1065 times.
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 1009 times.
✓ Branch 3 taken 56 times.
|
1121 | if (argn >= 1 && argn <= 4) { |
592 | 1009 | res = ENC_SYM_TERROR; | |
593 |
2/2✓ Branch 0 taken 1008 times.
✓ Branch 1 taken 1 times.
|
1009 | if (lbm_is_array_rw(args[0])) { |
594 | 1008 | lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]); | |
595 | |||
596 | 1008 | uint8_t clear_byte = 0; | |
597 |
2/2✓ Branch 0 taken 840 times.
✓ Branch 1 taken 168 times.
|
1008 | if (argn >= 2) { |
598 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 840 times.
|
840 | if (!lbm_is_number(args[1])) { |
599 | ✗ | return res; | |
600 | } | ||
601 | 840 | clear_byte = (uint8_t)lbm_dec_as_u32(args[1]); | |
602 | } | ||
603 | |||
604 | 1008 | uint32_t start = 0; | |
605 |
2/2✓ Branch 0 taken 112 times.
✓ Branch 1 taken 896 times.
|
1008 | if (argn >= 3) { |
606 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
|
112 | if (!lbm_is_number(args[2])) { |
607 | ✗ | return res; | |
608 | } | ||
609 | 112 | uint32_t start_new = lbm_dec_as_u32(args[2]); | |
610 |
1/2✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
|
112 | if (start_new < array->size) { |
611 | 112 | start = start_new; | |
612 | } else { | ||
613 | ✗ | return res; | |
614 | } | ||
615 | } | ||
616 | // Truncates size on 64 bit build | ||
617 | 1008 | uint32_t len = (uint32_t)array->size - start; | |
618 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 952 times.
|
1008 | if (argn >= 4) { |
619 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
|
56 | if (!lbm_is_number(args[3])) { |
620 | ✗ | return res; | |
621 | } | ||
622 | 56 | uint32_t len_new = lbm_dec_as_u32(args[3]); | |
623 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | if (len_new <= len) { |
624 | 56 | len = len_new; | |
625 | } | ||
626 | } | ||
627 | |||
628 | 1008 | memset((char*)array->data + start, clear_byte, len); | |
629 | 1008 | res = ENC_SYM_TRUE; | |
630 | } | ||
631 | } | ||
632 | 1121 | return res; | |
633 | } | ||
634 | |||
635 | 280 | static lbm_value array_extensions_bufcpy(lbm_value *args, lbm_uint argn) { | |
636 | 280 | lbm_value res = ENC_SYM_EERROR; | |
637 | |||
638 |
2/2✓ Branch 0 taken 224 times.
✓ Branch 1 taken 56 times.
|
280 | if (argn == 5) { |
639 | 224 | res = ENC_SYM_TERROR; | |
640 |
4/6✓ Branch 0 taken 112 times.
✓ Branch 1 taken 112 times.
✓ Branch 2 taken 112 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 112 times.
✗ Branch 5 not taken.
|
336 | if (lbm_is_array_rw(args[0]) && lbm_is_number(args[1]) && |
641 |
2/4✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✗ Branch 3 not taken.
|
224 | lbm_is_array_r(args[2]) && lbm_is_number(args[3]) &&lbm_is_number(args[4])) { |
642 | 112 | lbm_array_header_t *array1 = (lbm_array_header_t *)lbm_car(args[0]); | |
643 | |||
644 | 112 | uint32_t start1 = lbm_dec_as_u32(args[1]); | |
645 | |||
646 | 112 | lbm_array_header_t *array2 = (lbm_array_header_t *)lbm_car(args[2]); | |
647 | |||
648 | 112 | uint32_t start2 = lbm_dec_as_u32(args[3]); | |
649 | 112 | uint32_t len = lbm_dec_as_u32(args[4]); | |
650 | |||
651 |
2/4✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✗ Branch 3 not taken.
|
112 | if (start1 < array1->size && start2 < array2->size) { |
652 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
|
112 | if (len > (array1->size - start1)) { |
653 | ✗ | len = ((uint32_t)array1->size - start1); | |
654 | } | ||
655 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
|
112 | if (len > (array2->size - start2)) { |
656 | ✗ | len = ((uint32_t)array2->size - start2); | |
657 | } | ||
658 | |||
659 | 112 | memcpy((char*)array1->data + start1, (char*)array2->data + start2, len); | |
660 | } | ||
661 | 112 | res = ENC_SYM_TRUE; | |
662 | } | ||
663 | } | ||
664 | 280 | return res; | |
665 | } | ||
666 | |||
667 | 336 | static lbm_value array_extensions_bufset_bit(lbm_value *args, lbm_uint argn) { | |
668 | 336 | lbm_value res = ENC_SYM_EERROR; | |
669 | |||
670 |
2/2✓ Branch 0 taken 168 times.
✓ Branch 1 taken 168 times.
|
336 | if (argn == 3) { |
671 | 168 | res = ENC_SYM_TERROR; | |
672 |
3/4✓ Branch 0 taken 112 times.
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 112 times.
✗ Branch 3 not taken.
|
280 | if (lbm_is_array_rw(args[0]) && |
673 |
1/2✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
|
224 | lbm_is_number(args[1]) && lbm_is_number(args[2])) { |
674 | 112 | lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]); | |
675 | |||
676 | 112 | unsigned int pos = lbm_dec_as_u32(args[1]); | |
677 | 112 | unsigned int bit = lbm_dec_as_u32(args[2]) ? 1 : 0; | |
678 | |||
679 | 112 | unsigned int bytepos = pos / 8; | |
680 | |||
681 |
1/2✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
|
112 | if (bytepos < array->size) { |
682 | 112 | unsigned int bitpos = pos % 8; | |
683 | 112 | ((uint8_t*)array->data)[bytepos] &= (uint8_t)~(1 << bitpos); | |
684 | 112 | ((uint8_t*)array->data)[bytepos] |= (uint8_t)(bit << bitpos); | |
685 | } | ||
686 | |||
687 | 112 | res = ENC_SYM_TRUE; | |
688 | } | ||
689 | } | ||
690 | 336 | return res; | |
691 | } | ||
692 |