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