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