GCC Code Coverage Report


Directory: ../src/
File: /home/joels/Current/lispbm/src/extensions/array_extensions.c
Date: 2024-08-06 17:32:21
Exec Total Coverage
Lines: 285 606 47.0%
Functions: 17 25 68.0%
Branches: 120 419 28.6%

Line Branch Exec Source
1 /*
2 Copyright 2022, 2023 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 static lbm_uint little_endian = 0;
28 static lbm_uint big_endian = 0;
29
30 static lbm_value array_extension_unsafe_free_array(lbm_value *args, lbm_uint argn);
31 static lbm_value array_extension_buffer_append_i8(lbm_value *args, lbm_uint argn);
32 static lbm_value array_extension_buffer_append_i16(lbm_value *args, lbm_uint argn);
33 static lbm_value array_extension_buffer_append_i24(lbm_value *args, lbm_uint argn);
34 static lbm_value array_extension_buffer_append_i32(lbm_value *args, lbm_uint argn);
35 static lbm_value array_extension_buffer_append_u8(lbm_value *args, lbm_uint argn);
36 static lbm_value array_extension_buffer_append_u16(lbm_value *args, lbm_uint argn);
37 static lbm_value array_extension_buffer_append_u24(lbm_value *args, lbm_uint argn);
38 static lbm_value array_extension_buffer_append_u32(lbm_value *args, lbm_uint argn);
39 static lbm_value array_extension_buffer_append_f32(lbm_value *args, lbm_uint argn);
40
41 static lbm_value array_extension_buffer_get_i8(lbm_value *args, lbm_uint argn);
42 static lbm_value array_extension_buffer_get_i16(lbm_value *args, lbm_uint argn);
43 static lbm_value array_extension_buffer_get_i32(lbm_value *args, lbm_uint argn);
44 static lbm_value array_extension_buffer_get_u8(lbm_value *args, lbm_uint argn);
45 static lbm_value array_extension_buffer_get_u16(lbm_value *args, lbm_uint argn);
46 static lbm_value array_extension_buffer_get_u24(lbm_value *args, lbm_uint argn);
47 static lbm_value array_extension_buffer_get_u32(lbm_value *args, lbm_uint argn);
48 static lbm_value array_extension_buffer_get_f32(lbm_value *args, lbm_uint argn);
49
50 static lbm_value array_extension_buffer_length(lbm_value *args, lbm_uint argn);
51
52 static lbm_value array_extensions_bufclear(lbm_value *args, lbm_uint argn);
53 static lbm_value array_extensions_bufcpy(lbm_value *args, lbm_uint argn);
54 static lbm_value array_extensions_bufset_bit(lbm_value *args, lbm_uint argn);
55
56 17444 bool lbm_array_extensions_init(void) {
57
58
1/2
✓ Branch 1 taken 17444 times.
✗ Branch 2 not taken.
17444 if (!lbm_get_symbol_by_name("little-endian", &little_endian)) {
59
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17444 times.
17444 if (!lbm_add_symbol_const("little-endian", &little_endian)) {
60 return false;
61 }
62 }
63
1/2
✓ Branch 1 taken 17444 times.
✗ Branch 2 not taken.
17444 if (!lbm_get_symbol_by_name("big-endian", &big_endian)) {
64
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17444 times.
17444 if (!lbm_add_symbol_const("big-endian", &big_endian)) {
65 return false;
66 }
67 }
68 17444 bool res = true;
69
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("free", array_extension_unsafe_free_array);
70
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufset-i8", array_extension_buffer_append_i8);
71
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufset-i16", array_extension_buffer_append_i16);
72
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufset-i24", array_extension_buffer_append_i24);
73
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufset-i32", array_extension_buffer_append_i32);
74
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufset-u8", array_extension_buffer_append_u8);
75
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufset-u16", array_extension_buffer_append_u16);
76
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufset-u24", array_extension_buffer_append_u24);
77
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufset-u32", array_extension_buffer_append_u32);
78
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufset-f32", array_extension_buffer_append_f32);
79
80
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufget-i8", array_extension_buffer_get_i8);
81
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufget-i16", array_extension_buffer_get_i16);
82
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufget-i32", array_extension_buffer_get_i32);
83
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufget-u8", array_extension_buffer_get_u8);
84
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufget-u16", array_extension_buffer_get_u16);
85
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufget-u24", array_extension_buffer_get_u24);
86
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufget-u32", array_extension_buffer_get_u32);
87
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufget-f32", array_extension_buffer_get_f32);
88
89
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("buflen", array_extension_buffer_length);
90
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufclear", array_extensions_bufclear);
91
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufcpy", array_extensions_bufcpy);
92
2/4
✓ Branch 0 taken 17444 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17444 times.
✗ Branch 4 not taken.
17444 res = res && lbm_add_extension("bufset-bit", array_extensions_bufset_bit);
93
94 17444 return res;
95 }
96
97 28 lbm_value array_extension_unsafe_free_array(lbm_value *args, lbm_uint argn) {
98
99 28 lbm_value res = ENC_SYM_EERROR;
100
2/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
56 if (argn != 1 ||
101 28 lbm_type_of(args[0]) != LBM_TYPE_ARRAY) {
102 return res;
103 }
104 28 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
105
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 if (lbm_memory_ptr_inside(array->data)) {
106 28 lbm_memory_free((lbm_uint *)array->data);
107 28 lbm_uint ptr = lbm_dec_ptr(args[0]);
108 28 lbm_value cons_ptr = lbm_enc_cons_ptr(ptr);
109 28 lbm_set_car(cons_ptr,ENC_SYM_NIL);
110 28 lbm_set_cdr(cons_ptr,ENC_SYM_NIL);
111 28 res = ENC_SYM_TRUE;
112 }
113 28 lbm_memory_free((lbm_uint *)array);
114 28 return res;
115 }
116
117 364 lbm_value array_extension_buffer_append_i8(lbm_value *args, lbm_uint argn) {
118
119 364 lbm_value res = ENC_SYM_EERROR;
120
121
1/2
✓ Branch 0 taken 364 times.
✗ Branch 1 not taken.
364 if (argn == 3) {
122
1/2
✓ Branch 1 taken 364 times.
✗ Branch 2 not taken.
364 if(!lbm_is_array_rw(args[0]) ||
123
1/2
✓ Branch 1 taken 364 times.
✗ Branch 2 not taken.
364 !lbm_is_number(args[1]) ||
124
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 364 times.
364 !lbm_is_number(args[2])) {
125 return res;
126 }
127 364 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
128 364 lbm_uint index = lbm_dec_as_u32(args[1]);
129 364 lbm_int value = lbm_dec_as_i32(args[2]);
130
131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 364 times.
364 if (index >= array->size) {
132 return res;
133 }
134
135 364 uint8_t *data = (uint8_t*)array->data;
136 364 data[index] = (uint8_t) value;
137 364 res = ENC_SYM_TRUE;
138 }
139 364 return res;
140 }
141
142 lbm_value array_extension_buffer_append_i16(lbm_value *args, lbm_uint argn) {
143
144 lbm_value res = ENC_SYM_EERROR;
145 bool be = true;
146
147 switch(argn) {
148
149 case 4:
150 if (lbm_type_of(args[3]) == LBM_TYPE_SYMBOL &&
151 lbm_dec_sym(args[3]) == little_endian) {
152 be = false;
153 }
154 /* fall through */
155 case 3: {
156 if(!lbm_is_array_rw(args[0]) ||
157 !lbm_is_number(args[1]) ||
158 !lbm_is_number(args[2])) {
159 return res;
160 }
161 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
162
163 lbm_uint index = lbm_dec_as_u32(args[1]);
164 lbm_int value = lbm_dec_as_i32(args[2]);
165
166 if (index+1 >= array->size) {
167 return res;
168 }
169
170 uint8_t *data = (uint8_t*)array->data;
171
172 if (be) {
173 data[index+1] = (uint8_t)value;
174 data[index] = (uint8_t)(value >> 8);
175 } else {
176 data[index] = (uint8_t)value;
177 data[index +1] = (uint8_t)(value >> 8);
178 }
179 res = ENC_SYM_TRUE;
180 } break;
181 default:
182 break;
183 }
184 return res;
185 }
186
187 lbm_value array_extension_buffer_append_i24(lbm_value *args, lbm_uint argn) {
188
189 lbm_value res = ENC_SYM_EERROR;
190 bool be = true;
191
192 switch(argn) {
193
194 case 4:
195 if (lbm_type_of(args[3]) == LBM_TYPE_SYMBOL &&
196 lbm_dec_sym(args[3]) == little_endian) {
197 be = false;
198 }
199 /* fall through */
200 case 3: {
201 if(!lbm_is_array_rw(args[0]) ||
202 !lbm_is_number(args[1]) ||
203 !lbm_is_number(args[2])) {
204 return res;
205 }
206 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
207
208 lbm_uint index = lbm_dec_as_u32(args[1]);
209 lbm_int value = lbm_dec_as_i32(args[2]);
210
211 if (index+2 >= array->size) {
212 return res;
213 }
214
215 uint8_t *data = (uint8_t*)array->data;
216
217 if (be) {
218 data[index+2] = (uint8_t)value;
219 data[index+1] = (uint8_t)(value >> 8);
220 data[index] = (uint8_t)(value >> 16);
221 } else {
222 data[index] = (uint8_t)value;
223 data[index+1] = (uint8_t)(value >> 8);
224 data[index+2] = (uint8_t)(value >> 16);
225 }
226 res = ENC_SYM_TRUE;
227 } break;
228 default:
229 break;
230 }
231 return res;
232 }
233
234 140 lbm_value array_extension_buffer_append_i32(lbm_value *args, lbm_uint argn) {
235
236 140 lbm_value res = ENC_SYM_EERROR;
237 140 bool be = true;
238
239
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 2 not taken.
140 switch(argn) {
240
241 case 4:
242 if (lbm_type_of(args[3]) == LBM_TYPE_SYMBOL &&
243 lbm_dec_sym(args[3]) == little_endian) {
244 be = false;
245 }
246 /* fall through */
247 case 3: {
248
1/2
✓ Branch 1 taken 140 times.
✗ Branch 2 not taken.
140 if(!lbm_is_array_rw(args[0]) ||
249
1/2
✓ Branch 1 taken 140 times.
✗ Branch 2 not taken.
140 !lbm_is_number(args[1]) ||
250
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 140 times.
140 !lbm_is_number(args[2])) {
251 return res;
252 }
253 140 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
254
255 140 lbm_uint index = lbm_dec_as_u32(args[1]);
256 140 lbm_int value = lbm_dec_as_i32(args[2]);
257
258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (index+3 >= array->size) {
259 return res;
260 }
261
262 140 uint8_t *data = (uint8_t*)array->data;
263
264
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 if (be) {
265 140 data[index+3] = (uint8_t) value;
266 140 data[index+2] = (uint8_t) (value >> 8);
267 140 data[index+1] = (uint8_t) (value >> 16);
268 140 data[index] = (uint8_t) (value >> 24);
269 } else {
270 data[index] = (uint8_t) value;
271 data[index+1] = (uint8_t) (value >> 8);
272 data[index+2] = (uint8_t) (value >> 16);
273 data[index+3] = (uint8_t) (value >> 24);
274 }
275 140 res = ENC_SYM_TRUE;
276 140 } break;
277 default:
278 break;
279 }
280 140 return res;
281 }
282
283 364 lbm_value array_extension_buffer_append_u8(lbm_value *args, lbm_uint argn) {
284
285 364 lbm_value res = ENC_SYM_EERROR;
286
287
1/2
✓ Branch 0 taken 364 times.
✗ Branch 1 not taken.
364 switch(argn) {
288
289 364 case 3: {
290
1/2
✓ Branch 1 taken 364 times.
✗ Branch 2 not taken.
364 if(!lbm_is_array_rw(args[0]) ||
291
1/2
✓ Branch 1 taken 364 times.
✗ Branch 2 not taken.
364 !lbm_is_number(args[1]) ||
292
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 364 times.
364 !lbm_is_number(args[2])) {
293 return res;
294 }
295 364 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
296
297 364 lbm_uint index = lbm_dec_as_u32(args[1]);
298 364 lbm_uint value = lbm_dec_as_u32(args[2]);
299
300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 364 times.
364 if (index >= array->size) {
301 return res;
302 }
303
304 364 uint8_t *data = (uint8_t*)array->data;
305 364 data[index] = (uint8_t)value;
306 364 res = ENC_SYM_TRUE;
307 364 } break;
308 default:
309 break;
310 }
311 364 return res;
312 }
313
314 84 lbm_value array_extension_buffer_append_u16(lbm_value *args, lbm_uint argn) {
315
316 84 lbm_value res = ENC_SYM_EERROR;
317 84 bool be = true;
318
319
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
84 switch(argn) {
320
321 case 4:
322 if (lbm_type_of(args[3]) == LBM_TYPE_SYMBOL &&
323 lbm_dec_sym(args[3]) == little_endian) {
324 be = false;
325 }
326 /* fall through */
327 case 3: {
328
1/2
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
84 if(!lbm_is_array_rw(args[0]) ||
329
1/2
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
84 !lbm_is_number(args[1]) ||
330
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
84 !lbm_is_number(args[2])) {
331 return res;
332 }
333 84 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
334
335 84 lbm_uint index = lbm_dec_as_u32(args[1]);
336 84 lbm_uint value = lbm_dec_as_u32(args[2]);
337
338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (index+1 >= array->size) {
339 return res;
340 }
341
342 84 uint8_t *data = (uint8_t*)array->data;
343
344
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 if (be) {
345 84 data[index+1] = (uint8_t)value;
346 84 data[index] = (uint8_t)(value >> 8);
347 } else {
348 data[index] = (uint8_t)value;
349 data[index +1] = (uint8_t)(value >> 8);
350 }
351 84 res = ENC_SYM_TRUE;
352 84 } break;
353 default:
354 break;
355 }
356 84 return res;
357 }
358
359 lbm_value array_extension_buffer_append_u24(lbm_value *args, lbm_uint argn) {
360
361 lbm_value res = ENC_SYM_EERROR;
362 bool be = true;
363
364 switch(argn) {
365
366 case 4:
367 if (lbm_type_of(args[3]) == LBM_TYPE_SYMBOL &&
368 lbm_dec_sym(args[3]) == little_endian) {
369 be = false;
370 }
371 /* fall through */
372 case 3: {
373 if(!lbm_is_array_rw(args[0]) ||
374 !lbm_is_number(args[1]) ||
375 !lbm_is_number(args[2])) {
376 return res;
377 }
378 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
379
380 lbm_uint index = lbm_dec_as_u32(args[1]);
381 lbm_uint value = lbm_dec_as_u32(args[2]);
382
383 if (index+2 >= array->size) {
384 return res;
385 }
386
387 uint8_t *data = (uint8_t*)array->data;
388
389 if (be) {
390 data[index+2] = (uint8_t)value;
391 data[index+1] = (uint8_t)(value >> 8);
392 data[index] = (uint8_t)(value >> 16);
393 } else {
394 data[index] = (uint8_t)value;
395 data[index +1] = (uint8_t)(value >> 8);
396 data[index +2] = (uint8_t)(value >> 16);
397 }
398 res = ENC_SYM_TRUE;
399 } break;
400 default:
401 break;
402 }
403 return res;
404 }
405
406 140 lbm_value array_extension_buffer_append_u32(lbm_value *args, lbm_uint argn) {
407
408 140 lbm_value res = ENC_SYM_EERROR;
409 140 bool be = true;
410
411
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 2 not taken.
140 switch(argn) {
412
413 case 4:
414 if (lbm_type_of(args[3]) == LBM_TYPE_SYMBOL &&
415 lbm_dec_sym(args[3]) == little_endian) {
416 be = false;
417 }
418 /* fall through */
419 case 3: {
420
1/2
✓ Branch 1 taken 140 times.
✗ Branch 2 not taken.
140 if(!lbm_is_array_rw(args[0]) ||
421
1/2
✓ Branch 1 taken 140 times.
✗ Branch 2 not taken.
140 !lbm_is_number(args[1]) ||
422
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 140 times.
140 !lbm_is_number(args[2])) {
423 return res;
424 }
425 140 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
426
427 140 lbm_uint index = lbm_dec_as_u32(args[1]);
428 140 lbm_uint value = lbm_dec_as_u32(args[2]);
429
430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (index+3 >= array->size) {
431 return res;
432 }
433
434 140 uint8_t *data = (uint8_t*)array->data;
435
436
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 if (be) {
437 140 data[index+3] = (uint8_t)value;
438 140 data[index+2] = (uint8_t)(value >> 8);
439 140 data[index+1] = (uint8_t)(value >> 16);
440 140 data[index] = (uint8_t)(value >> 24);
441 } else {
442 data[index] = (uint8_t)value;
443 data[index+1] = (uint8_t)(value >> 8);
444 data[index+2] = (uint8_t)(value >> 16);
445 data[index+3] = (uint8_t)(value >> 24);
446 }
447 140 res = ENC_SYM_TRUE;
448 140 } break;
449 default:
450 break;
451 }
452 140 return res;
453 }
454
455 168 static lbm_uint float_to_u(float number) {
456 // Set subnormal numbers to 0 as they are not handled properly
457 // using this method.
458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 if (fabsf(number) < 1.5e-38) {
459 number = 0.0;
460 }
461
462 168 int e = 0;
463 168 float sig = frexpf(number, &e);
464 168 float sig_abs = fabsf(sig);
465 168 uint32_t sig_i = 0;
466
467
1/2
✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
168 if (sig_abs >= 0.5) {
468 168 sig_i = (uint32_t)((sig_abs - 0.5f) * 2.0f * 8388608.0f);
469 168 e += 126;
470 }
471
472 168 uint32_t res = ((e & 0xFF) << 23) | (sig_i & 0x7FFFFF);
473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 if (sig < 0) {
474 res |= 1U << 31;
475 }
476
477 168 return res;
478 }
479
480 168 static lbm_float u_to_float(uint32_t v) {
481
482 168 int e = (v >> 23) & 0xFF;
483 168 uint32_t sig_i = v & 0x7FFFFF;
484 168 bool neg = v & (1U << 31);
485
486 168 float sig = 0.0;
487
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
168 if (e != 0 || sig_i != 0) {
488 168 sig = (float)sig_i / (8388608.0f * 2.0f) + 0.5f;
489 168 e -= 126;
490 }
491
492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 if (neg) {
493 sig = -sig;
494 }
495
496 168 return ldexpf(sig, e);
497 }
498
499 168 lbm_value array_extension_buffer_append_f32(lbm_value *args, lbm_uint argn) {
500
501 168 lbm_value res = ENC_SYM_EERROR;
502 168 bool be = true;
503
504
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
168 switch(argn) {
505
506 case 4:
507 if (lbm_type_of(args[3]) == LBM_TYPE_SYMBOL &&
508 lbm_dec_sym(args[3]) == little_endian) {
509 be = false;
510 }
511 /* fall through */
512 case 3: {
513
1/2
✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
168 if(!lbm_is_array_rw(args[0]) ||
514
1/2
✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
168 !lbm_is_number(args[1]) ||
515
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 168 times.
168 !lbm_is_number(args[2])) {
516 return res;
517 }
518 168 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
519
520 168 float f_value = (float)lbm_dec_as_float(args[2]);
521 168 lbm_value value = float_to_u(f_value);
522 168 lbm_uint index = lbm_dec_as_u32(args[1]);
523
524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 if (index+3 >= array->size) {
525 return res;
526 }
527
528 168 uint8_t *data = (uint8_t*)array->data;
529
530
1/2
✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
168 if (be) {
531 168 data[index+3] = (uint8_t)value;
532 168 data[index+2] = (uint8_t)(value >> 8);
533 168 data[index+1] = (uint8_t)(value >> 16);
534 168 data[index] = (uint8_t)(value >> 24);
535 } else {
536 data[index] = (uint8_t)value;
537 data[index+1] = (uint8_t)(value >> 8);
538 data[index+2] = (uint8_t)(value >> 16);
539 data[index+3] = (uint8_t)(value >> 24);
540 }
541 168 res = ENC_SYM_TRUE;
542 168 } break;
543 default:
544 break;
545 }
546 168 return res;
547 }
548
549 /* (buffer-get-i8 buffer index) */
550 /* (buffer-get-i16 buffer index little-endian) */
551
552 504 lbm_value array_extension_buffer_get_i8(lbm_value *args, lbm_uint argn) {
553 504 lbm_value res = ENC_SYM_EERROR;
554
555
1/2
✓ Branch 0 taken 504 times.
✗ Branch 1 not taken.
504 if (argn == 2) {
556
1/2
✓ Branch 1 taken 504 times.
✗ Branch 2 not taken.
504 if(!lbm_is_array_r(args[0]) ||
557
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 504 times.
504 !lbm_is_number(args[1])) {
558 return res;
559 }
560 504 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
561
562 504 lbm_uint index = lbm_dec_as_u32(args[1]);
563 504 lbm_uint value = 0;
564
565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
504 if (index >= array->size) {
566 return res;
567 }
568 504 uint8_t *data = (uint8_t*)array->data;
569
570 504 value = data[index];
571 504 res = lbm_enc_i((int8_t)value);
572 }
573 504 return res;
574 }
575
576 lbm_value array_extension_buffer_get_i16(lbm_value *args, lbm_uint argn) {
577 lbm_value res = ENC_SYM_EERROR;
578 bool be = true;
579
580 switch(argn) {
581
582 case 3:
583 if (lbm_type_of(args[2]) == LBM_TYPE_SYMBOL &&
584 lbm_dec_sym(args[2]) == little_endian) {
585 be = false;
586 }
587 /* fall through */
588 case 2: {
589 if (!lbm_is_array_r(args[0]) ||
590 !lbm_is_number(args[1])) {
591 return res;
592 }
593 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
594
595 lbm_uint index = lbm_dec_as_u32(args[1]);
596 lbm_uint value = 0;
597
598 if (index+1 >= array->size) {
599 return res;
600 }
601 uint8_t *data = (uint8_t*)array->data;
602
603 if (be) {
604 value =
605 (lbm_uint) data[index+1] |
606 (lbm_uint) data[index] << 8;
607 } else {
608 value =
609 (lbm_uint) data[index] |
610 (lbm_uint) data[index+1] << 8;
611 }
612
613 res = lbm_enc_i((int16_t)value);
614 } break;
615 default:
616 break;
617 }
618 return res;
619 }
620
621 140 lbm_value array_extension_buffer_get_i32(lbm_value *args, lbm_uint argn) {
622 140 lbm_value res = ENC_SYM_EERROR;
623 140 bool be = true;
624
625
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 2 not taken.
140 switch(argn) {
626
627 case 3:
628 if (lbm_type_of(args[2]) == LBM_TYPE_SYMBOL &&
629 lbm_dec_sym(args[2]) == little_endian) {
630 be = false;
631 }
632 /* fall through */
633 case 2: {
634
1/2
✓ Branch 1 taken 140 times.
✗ Branch 2 not taken.
140 if (!lbm_is_array_r(args[0]) ||
635
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 140 times.
140 !lbm_is_number(args[1])) {
636 return res;
637 }
638 140 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
639
640 140 lbm_uint index = lbm_dec_as_u32(args[1]);
641 140 uint32_t value = 0;
642
643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (index+3 >= array->size) {
644 return res;
645 }
646 140 uint8_t *data = (uint8_t*)array->data;
647
648
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 if (be) {
649 140 value =
650 140 (uint32_t) data[index+3] |
651 140 (uint32_t) data[index+2] << 8 |
652 140 (uint32_t) data[index+1] << 16 |
653 140 (uint32_t) data[index] << 24;
654 } else {
655 value =
656 (uint32_t) data[index] |
657 (uint32_t) data[index+1] << 8 |
658 (uint32_t) data[index+2] << 16 |
659 (uint32_t) data[index+3] << 24;
660 }
661
662 140 res = lbm_enc_i32((int32_t)value);
663 140 } break;
664 default:
665 break;
666 }
667 140 return res;
668 }
669
670
671 728 lbm_value array_extension_buffer_get_u8(lbm_value *args, lbm_uint argn) {
672 728 lbm_value res = ENC_SYM_EERROR;
673
674
1/2
✓ Branch 0 taken 728 times.
✗ Branch 1 not taken.
728 if (argn == 2) {
675
1/2
✓ Branch 1 taken 728 times.
✗ Branch 2 not taken.
728 if(!lbm_is_array_r(args[0])||
676
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 728 times.
728 !lbm_is_number(args[1])) {
677 return res;
678 }
679 728 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
680
681 728 lbm_uint index = lbm_dec_as_u32(args[1]);
682 728 lbm_int value = 0;
683
684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 728 times.
728 if (index >= array->size) {
685 return res;
686 }
687 728 uint8_t *data = (uint8_t*)array->data;
688
689 728 value = (lbm_int)data[index];
690 728 res = lbm_enc_i(value);
691 }
692 728 return res;
693 }
694
695
696 84 lbm_value array_extension_buffer_get_u16(lbm_value *args, lbm_uint argn) {
697 84 lbm_value res = ENC_SYM_EERROR;
698 84 bool be = true;
699
700
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
84 switch(argn) {
701
702 case 3:
703 if (lbm_type_of(args[2]) == LBM_TYPE_SYMBOL &&
704 lbm_dec_sym(args[2]) == little_endian) {
705 be = false;
706 }
707 /* fall through */
708 case 2: {
709
1/2
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
84 if (!lbm_is_array_r(args[0]) ||
710
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
84 !lbm_is_number(args[1])) {
711 return res;
712 }
713 84 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
714
715 84 lbm_uint index = lbm_dec_as_u32(args[1]);
716 84 lbm_int value = 0;
717
718
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (index+1 >= array->size) {
719 return res;
720 }
721 84 uint8_t *data = (uint8_t*)array->data;
722
723
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 if (be) {
724 84 value = (lbm_int)(
725 84 (lbm_uint) data[index+1] |
726 84 (lbm_uint) data[index] << 8);
727 } else {
728 value = (lbm_int)(
729 (lbm_uint) data[index] |
730 (lbm_uint) data[index+1] << 8);
731 }
732
733 84 res = lbm_enc_i(value);
734 84 } break;
735 default:
736 break;
737 }
738 84 return res;
739 }
740
741 lbm_value array_extension_buffer_get_u24(lbm_value *args, lbm_uint argn) {
742 lbm_value res = ENC_SYM_EERROR;
743 bool be = true;
744
745 switch(argn) {
746
747 case 3:
748 if (lbm_type_of(args[2]) == LBM_TYPE_SYMBOL &&
749 lbm_dec_sym(args[2]) == little_endian) {
750 be = false;
751 }
752 /* fall through */
753 case 2: {
754 if (!lbm_is_array_r(args[0]) ||
755 !lbm_is_number(args[1])) {
756 return res;
757 }
758 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
759
760 lbm_uint index = lbm_dec_as_u32(args[1]);
761 lbm_int value = 0;
762
763 if (index+2 >= array->size) {
764 return res;
765 }
766 uint8_t *data = (uint8_t*)array->data;
767
768 if (be) {
769 value = (lbm_int)(
770 (lbm_uint) data[index+2] |
771 (lbm_uint) data[index+1] << 8 |
772 (lbm_uint) data[index] << 16);
773 } else {
774 value = (lbm_int)(
775 (lbm_uint) data[index] |
776 (lbm_uint) data[index+1] << 8 |
777 (lbm_uint) data[index+2] << 16);
778 }
779
780 res = lbm_enc_i(value);
781 } break;
782 default:
783 break;
784 }
785 return res;
786 }
787
788
789 224 lbm_value array_extension_buffer_get_u32(lbm_value *args, lbm_uint argn) {
790 224 lbm_value res = ENC_SYM_EERROR;
791 224 bool be = true;
792
793
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
✗ Branch 2 not taken.
224 switch(argn) {
794
795 case 3:
796 if (lbm_type_of(args[2]) == LBM_TYPE_SYMBOL &&
797 lbm_dec_sym(args[2]) == little_endian) {
798 be = false;
799 }
800 /* fall through */
801 case 2: {
802
1/2
✓ Branch 1 taken 224 times.
✗ Branch 2 not taken.
224 if (!lbm_is_array_r(args[0]) ||
803
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 224 times.
224 !lbm_is_number(args[1])) {
804 return res;
805 }
806 224 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
807
808 224 lbm_uint index = lbm_dec_as_u32(args[1]);
809 224 uint32_t value = 0;
810
811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
224 if (index+3 >= array->size) {
812 return res;
813 }
814 224 uint8_t *data = (uint8_t*)array->data;
815
816
1/2
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
224 if (be) {
817 224 value =
818 224 (uint32_t) data[index+3] |
819 224 (uint32_t) data[index+2] << 8 |
820 224 (uint32_t) data[index+1] << 16 |
821 224 (uint32_t) data[index] << 24;
822 } else {
823 value =
824 (uint32_t) data[index] |
825 (uint32_t) data[index+1] << 8 |
826 (uint32_t) data[index+2] << 16 |
827 (uint32_t) data[index+3] << 24;
828 }
829
830 224 res = lbm_enc_u32(value);
831 224 } break;
832 default:
833 break;
834 }
835 224 return res;
836 }
837
838 168 lbm_value array_extension_buffer_get_f32(lbm_value *args, lbm_uint argn) {
839 168 lbm_value res = ENC_SYM_EERROR;
840 168 bool be = true;
841
842
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
168 switch(argn) {
843
844 case 3:
845 if (lbm_type_of(args[2]) == LBM_TYPE_SYMBOL &&
846 lbm_dec_sym(args[2]) == little_endian) {
847 be = false;
848 }
849 /* fall through */
850 case 2: {
851
1/2
✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
168 if (!lbm_is_array_r(args[0]) ||
852
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 168 times.
168 !lbm_is_number(args[1])) {
853 return res;
854 }
855 168 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
856
857 168 uint32_t index = (uint32_t)lbm_dec_as_u32(args[1]);
858 168 uint32_t value = 0;
859
860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 if (index+3 >= array->size) {
861 return res;
862 }
863 168 uint8_t *data = (uint8_t*)array->data;
864
865
1/2
✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
168 if (be) {
866 168 value =
867 168 (uint32_t) data[index+3] |
868 168 (uint32_t) data[index+2] << 8 |
869 168 (uint32_t) data[index+1] << 16 |
870 168 (uint32_t) data[index] << 24;
871 } else {
872 value =
873 (uint32_t) data[index] |
874 (uint32_t) data[index+1] << 8 |
875 (uint32_t) data[index+2] << 16 |
876 (uint32_t) data[index+3] << 24;
877 }
878
879 168 res = lbm_enc_float((float)u_to_float(value));
880 168 } break;
881 default:
882 break;
883 }
884 168 return res;
885 }
886
887 252 lbm_value array_extension_buffer_length(lbm_value *args, lbm_uint argn) {
888 252 lbm_value res = ENC_SYM_EERROR;
889
2/4
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 252 times.
✗ Branch 3 not taken.
504 if (argn == 1 &&
890 252 lbm_is_array_r(args[0])) {
891 252 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
892 252 res = lbm_enc_i((lbm_int)array->size);
893 }
894 252 return res;
895 }
896
897 //TODO: Have to think about 32 vs 64 bit here
898 static lbm_value array_extensions_bufclear(lbm_value *args, lbm_uint argn) {
899 lbm_value res = ENC_SYM_EERROR;
900
901 if ((argn != 1 && argn != 2 && argn != 3 && argn != 4) || !lbm_is_array_rw(args[0])) {
902 return res;
903 }
904
905 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
906
907 uint8_t clear_byte = 0;
908 if (argn >= 2) {
909 if (!lbm_is_number(args[1])) {
910 return res;
911 }
912 clear_byte = (uint8_t)lbm_dec_as_u32(args[1]);
913 }
914
915 uint32_t start = 0;
916 if (argn >= 3) {
917 if (!lbm_is_number(args[2])) {
918 return res;
919 }
920 uint32_t start_new = lbm_dec_as_u32(args[2]);
921 if (start_new < array->size) {
922 start = start_new;
923 } else {
924 return res;
925 }
926 }
927 // Truncates size on 64 bit build
928 uint32_t len = (uint32_t)array->size - start;
929 if (argn >= 4) {
930 if (!lbm_is_number(args[3])) {
931 return res;
932 }
933 uint32_t len_new = lbm_dec_as_u32(args[3]);
934 if (len_new <= len) {
935 len = len_new;
936 }
937 }
938
939 memset((char*)array->data + start, clear_byte, len);
940 res = ENC_SYM_TRUE;
941
942 return res;
943 }
944
945 static lbm_value array_extensions_bufcpy(lbm_value *args, lbm_uint argn) {
946 lbm_value res = ENC_SYM_EERROR;
947
948 if (argn != 5 || !lbm_is_array_rw(args[0]) || !lbm_is_number(args[1])
949 || !lbm_is_array_r(args[2]) || !lbm_is_number(args[3]) || !lbm_is_number(args[4])) {
950 return res;
951 }
952
953 lbm_array_header_t *array1 = (lbm_array_header_t *)lbm_car(args[0]);
954
955 uint32_t start1 = lbm_dec_as_u32(args[1]);
956
957 lbm_array_header_t *array2 = (lbm_array_header_t *)lbm_car(args[2]);
958
959 uint32_t start2 = lbm_dec_as_u32(args[3]);
960 uint32_t len = lbm_dec_as_u32(args[4]);
961
962 if (start1 < array1->size && start2 < array2->size) {
963 if (len > (array1->size - start1)) {
964 len = ((uint32_t)array1->size - start1);
965 }
966 if (len > (array2->size - start2)) {
967 len = ((uint32_t)array2->size - start2);
968 }
969
970 memcpy((char*)array1->data + start1, (char*)array2->data + start2, len);
971 }
972
973 res = ENC_SYM_TRUE;
974
975 return res;
976 }
977
978 static lbm_value array_extensions_bufset_bit(lbm_value *args, lbm_uint argn) {
979 lbm_value res = ENC_SYM_EERROR;
980
981 if (argn != 3 || !lbm_is_array_rw(args[0]) ||
982 !lbm_is_number(args[1]) || !lbm_is_number(args[2])) {
983 return res;
984 }
985
986 lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
987
988 unsigned int pos = lbm_dec_as_u32(args[1]);
989 unsigned int bit = lbm_dec_as_u32(args[2]) ? 1 : 0;
990
991 unsigned int bytepos = pos / 8;
992 unsigned int bitpos = pos % 8;
993
994 if (bytepos < array->size) {
995 ((uint8_t*)array->data)[bytepos] &= (uint8_t)~(1 << bitpos);
996 ((uint8_t*)array->data)[bytepos] |= (uint8_t)(bit << bitpos);
997 }
998
999 res = ENC_SYM_TRUE;
1000
1001 return res;
1002 }
1003