GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
Copyright 2023, 2024, 2025 Joel Svensson svenssonjoel@yahoo.se |
||
3 |
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 <lbm_flat_value.h> |
||
20 |
#include <eval_cps.h> |
||
21 |
#include <stack.h> |
||
22 |
|||
23 |
#include <setjmp.h> |
||
24 |
|||
25 |
// ------------------------------------------------------------ |
||
26 |
// Access to GC from eval_cps |
||
27 |
int lbm_perform_gc(void); |
||
28 |
|||
29 |
|||
30 |
// ------------------------------------------------------------ |
||
31 |
// Flatteners |
||
32 |
40839 |
bool lbm_start_flatten(lbm_flat_value_t *v, size_t buffer_size) { |
|
33 |
40839 |
bool res = false; |
|
34 |
40839 |
uint8_t *data = lbm_malloc_reserve(buffer_size); |
|
35 |
✓✗ | 40839 |
if (data) { |
36 |
40839 |
v->buf = data; |
|
37 |
40839 |
v->buf_size = buffer_size; |
|
38 |
40839 |
v->buf_pos = 0; |
|
39 |
40839 |
res = true; |
|
40 |
} |
||
41 |
40839 |
return res; |
|
42 |
} |
||
43 |
|||
44 |
6273 |
bool lbm_finish_flatten(lbm_flat_value_t *v) { |
|
45 |
lbm_uint size_words; |
||
46 |
✗✓ | 6273 |
if (v->buf_pos % sizeof(lbm_uint) == 0) { |
47 |
size_words = v->buf_pos / sizeof(lbm_uint); |
||
48 |
} else { |
||
49 |
6273 |
size_words = (v->buf_pos / sizeof(lbm_uint)) + 1; |
|
50 |
} |
||
51 |
✓✓ | 6273 |
if (v->buf_size <= size_words * sizeof(lbm_uint)) return true; |
52 |
6245 |
v->buf_size = size_words * sizeof(lbm_uint); |
|
53 |
6245 |
return (lbm_memory_shrink((lbm_uint*)v->buf, size_words) >= 0); |
|
54 |
} |
||
55 |
|||
56 |
421555 |
static bool write_byte(lbm_flat_value_t *v, uint8_t b) { |
|
57 |
421555 |
bool res = false; |
|
58 |
✓✗ | 421555 |
if (v->buf_size >= v->buf_pos + 1) { |
59 |
421555 |
v->buf[v->buf_pos++] = b; |
|
60 |
421555 |
res = true; |
|
61 |
} |
||
62 |
421555 |
return res; |
|
63 |
} |
||
64 |
|||
65 |
181860 |
static bool write_bytes(lbm_flat_value_t *v, uint8_t *data,lbm_uint num_bytes) { |
|
66 |
181860 |
bool res = false; |
|
67 |
✓✗ | 181860 |
if (v->buf_size >= v->buf_pos + num_bytes) { |
68 |
181860 |
memcpy(v->buf + v->buf_pos, data, num_bytes); |
|
69 |
181860 |
v->buf_pos += num_bytes; |
|
70 |
181860 |
res = true; |
|
71 |
} |
||
72 |
181860 |
return res; |
|
73 |
} |
||
74 |
|||
75 |
237063 |
static bool write_word(lbm_flat_value_t *v, uint32_t w) { |
|
76 |
237063 |
bool res = false; |
|
77 |
✓✗ | 237063 |
if (v->buf_size >= v->buf_pos + 4) { |
78 |
237063 |
v->buf[v->buf_pos++] = (uint8_t)(w >> 24); |
|
79 |
237063 |
v->buf[v->buf_pos++] = (uint8_t)(w >> 16); |
|
80 |
237063 |
v->buf[v->buf_pos++] = (uint8_t)(w >> 8); |
|
81 |
237063 |
v->buf[v->buf_pos++] = (uint8_t)w; |
|
82 |
237063 |
res = true; |
|
83 |
} |
||
84 |
237063 |
return res; |
|
85 |
} |
||
86 |
|||
87 |
84 |
static bool write_dword(lbm_flat_value_t *v, uint64_t w) { |
|
88 |
84 |
bool res = false; |
|
89 |
✓✗ | 84 |
if (v->buf_size >= v->buf_pos + 8) { |
90 |
84 |
v->buf[v->buf_pos++] = (uint8_t)(w >> 56); |
|
91 |
84 |
v->buf[v->buf_pos++] = (uint8_t)(w >> 48); |
|
92 |
84 |
v->buf[v->buf_pos++] = (uint8_t)(w >> 40); |
|
93 |
84 |
v->buf[v->buf_pos++] = (uint8_t)(w >> 32); |
|
94 |
84 |
v->buf[v->buf_pos++] = (uint8_t)(w >> 24); |
|
95 |
84 |
v->buf[v->buf_pos++] = (uint8_t)(w >> 16); |
|
96 |
84 |
v->buf[v->buf_pos++] = (uint8_t)(w >> 8); |
|
97 |
84 |
v->buf[v->buf_pos++] = (uint8_t)w; |
|
98 |
84 |
res = true; |
|
99 |
} |
||
100 |
84 |
return res; |
|
101 |
} |
||
102 |
|||
103 |
319704 |
bool f_cons(lbm_flat_value_t *v) { |
|
104 |
319704 |
bool res = false; |
|
105 |
✓✗ | 319704 |
if (v->buf_size >= v->buf_pos + 1) { |
106 |
319704 |
v->buf[v->buf_pos++] = S_CONS; |
|
107 |
319704 |
res = true; |
|
108 |
} |
||
109 |
319704 |
return res; |
|
110 |
} |
||
111 |
|||
112 |
112 |
bool f_lisp_array(lbm_flat_value_t *v, uint32_t size) { |
|
113 |
// arrays are smaller than 2^32 elements long |
||
114 |
112 |
bool res = true; |
|
115 |
✓✗✓✗ |
112 |
res = res && write_byte(v, S_LBM_LISP_ARRAY); |
116 |
✓✗✓✗ |
112 |
res = res && write_word(v, size); // number of elements. |
117 |
112 |
return res; |
|
118 |
} |
||
119 |
|||
120 |
4987 |
bool f_sym(lbm_flat_value_t *v, lbm_uint sym_id) { |
|
121 |
4987 |
bool res = true; |
|
122 |
✓✗✓✗ |
4987 |
res = res && write_byte(v,S_SYM_VALUE); |
123 |
#ifndef LBM64 |
||
124 |
✓✗✓✗ |
4987 |
res = res && write_word(v,sym_id); |
125 |
#else |
||
126 |
res = res && write_dword(v,sym_id); |
||
127 |
#endif |
||
128 |
4987 |
return res; |
|
129 |
} |
||
130 |
|||
131 |
63112 |
bool f_sym_string(lbm_flat_value_t *v, char *str) { |
|
132 |
63112 |
bool res = false; |
|
133 |
✓✗ | 63112 |
if (str) { |
134 |
63112 |
lbm_uint sym_bytes = strlen(str) + 1; |
|
135 |
✓✗✓✗ |
126224 |
if (write_byte(v, S_SYM_STRING) && |
136 |
63112 |
write_bytes(v, (uint8_t*)str, sym_bytes)) { |
|
137 |
63112 |
res = true; |
|
138 |
} |
||
139 |
} |
||
140 |
63112 |
return res; |
|
141 |
} |
||
142 |
|||
143 |
// Potentially a difference between 32/64 bit version. |
||
144 |
// strlen returns size_t which is different on 32/64 bit platforms. |
||
145 |
63072 |
int f_sym_string_bytes(lbm_value sym) { |
|
146 |
63072 |
int res = FLATTEN_VALUE_ERROR_FATAL; |
|
147 |
✓✗ | 63072 |
if (lbm_is_symbol(sym)) { |
148 |
63072 |
lbm_uint s = lbm_dec_sym(sym); |
|
149 |
63072 |
char *sym_str = (char*)lbm_get_name_by_symbol(s); |
|
150 |
✓✗ | 63072 |
if (sym_str) { |
151 |
63072 |
lbm_uint sym_bytes = strlen(sym_str) + 1; |
|
152 |
63072 |
res = (int)sym_bytes; |
|
153 |
} |
||
154 |
} |
||
155 |
63072 |
return res; |
|
156 |
} |
||
157 |
|||
158 |
45626 |
bool f_i(lbm_flat_value_t *v, lbm_int i) { |
|
159 |
45626 |
bool res = true; |
|
160 |
#ifndef LBM64 |
||
161 |
✓✗✓✗ |
45626 |
res = res && write_byte(v,S_I28_VALUE); |
162 |
✓✗✓✗ |
45626 |
res = res && write_word(v,(uint32_t)i); |
163 |
#else |
||
164 |
res = res && write_byte(v,S_I56_VALUE); |
||
165 |
res = res && write_dword(v, (uint64_t)i); |
||
166 |
#endif |
||
167 |
45626 |
return res; |
|
168 |
} |
||
169 |
|||
170 |
28 |
bool f_u(lbm_flat_value_t *v, lbm_uint u) { |
|
171 |
28 |
bool res = true; |
|
172 |
#ifndef LBM64 |
||
173 |
✓✗✓✗ |
28 |
res = res && write_byte(v,S_U28_VALUE); |
174 |
✓✗✓✗ |
28 |
res = res && write_word(v,(uint32_t)u); |
175 |
#else |
||
176 |
res = res && write_byte(v,S_U56_VALUE); |
||
177 |
res = res && write_dword(v,(uint64_t)u); |
||
178 |
#endif |
||
179 |
28 |
return res; |
|
180 |
} |
||
181 |
|||
182 |
60648 |
bool f_b(lbm_flat_value_t *v, uint8_t b) { |
|
183 |
60648 |
bool res = true; |
|
184 |
✓✗✓✗ |
60648 |
res = res && write_byte(v,S_BYTE_VALUE); |
185 |
✓✗✓✗ |
60648 |
res = res && write_byte(v,b); |
186 |
60648 |
return res; |
|
187 |
} |
||
188 |
|||
189 |
29274 |
bool f_i32(lbm_flat_value_t *v, int32_t w) { |
|
190 |
29274 |
bool res = true; |
|
191 |
✓✗✓✗ |
29274 |
res = res && write_byte(v, S_I32_VALUE); |
192 |
✓✗✓✗ |
29274 |
res = res && write_word(v, (uint32_t)w); |
193 |
29274 |
return res; |
|
194 |
} |
||
195 |
|||
196 |
31122 |
bool f_u32(lbm_flat_value_t *v, uint32_t w) { |
|
197 |
31122 |
bool res = true; |
|
198 |
✓✗✓✗ |
31122 |
res = res && write_byte(v, S_U32_VALUE); |
199 |
✓✗✓✗ |
31122 |
res = res && write_word(v, w); |
200 |
31122 |
return res; |
|
201 |
} |
||
202 |
|||
203 |
7166 |
bool f_float(lbm_flat_value_t *v, float f) { |
|
204 |
7166 |
bool res = true; |
|
205 |
✓✗✓✗ |
7166 |
res = res && write_byte(v, S_FLOAT_VALUE); |
206 |
uint32_t u; |
||
207 |
7166 |
memcpy(&u, &f, sizeof(uint32_t)); |
|
208 |
✓✗✓✗ |
7166 |
res = res && write_word(v, (uint32_t)u); |
209 |
7166 |
return res; |
|
210 |
} |
||
211 |
|||
212 |
28 |
bool f_double(lbm_flat_value_t *v, double d) { |
|
213 |
28 |
bool res = true; |
|
214 |
✓✗✓✗ |
28 |
res = res && write_byte(v, S_DOUBLE_VALUE); |
215 |
uint64_t u; |
||
216 |
28 |
memcpy(&u, &d, sizeof(uint64_t)); |
|
217 |
✓✗✓✗ |
28 |
res = res && write_dword(v, u); |
218 |
28 |
return res; |
|
219 |
} |
||
220 |
|||
221 |
28 |
bool f_i64(lbm_flat_value_t *v, int64_t w) { |
|
222 |
28 |
bool res = true; |
|
223 |
✓✗✓✗ |
28 |
res = res && write_byte(v, S_I64_VALUE); |
224 |
✓✗✓✗ |
28 |
res = res && write_dword(v, (uint64_t)w); |
225 |
28 |
return res; |
|
226 |
} |
||
227 |
|||
228 |
28 |
bool f_u64(lbm_flat_value_t *v, uint64_t w) { |
|
229 |
28 |
bool res = true; |
|
230 |
✓✗✓✗ |
28 |
res = res && write_byte(v, S_U64_VALUE); |
231 |
✓✗✓✗ |
28 |
res = res && write_dword(v, w); |
232 |
28 |
return res; |
|
233 |
} |
||
234 |
|||
235 |
// num_bytes is specifically an uint32_t |
||
236 |
118748 |
bool f_lbm_array(lbm_flat_value_t *v, uint32_t num_bytes, uint8_t *data) { |
|
237 |
118748 |
bool res = write_byte(v, S_LBM_ARRAY); |
|
238 |
✓✗✓✗ |
118748 |
res = res && write_word(v, num_bytes); |
239 |
✓✗✓✗ |
118748 |
res = res && write_bytes(v, data, num_bytes); |
240 |
118748 |
return res; |
|
241 |
} |
||
242 |
|||
243 |
static int flatten_maximum_depth = FLATTEN_VALUE_MAXIMUM_DEPTH; |
||
244 |
|||
245 |
28 |
void lbm_set_max_flatten_depth(int depth) { |
|
246 |
28 |
flatten_maximum_depth = depth; |
|
247 |
28 |
} |
|
248 |
|||
249 |
int lbm_get_max_flatten_depth(void) { |
||
250 |
return flatten_maximum_depth; |
||
251 |
} |
||
252 |
|||
253 |
28 |
void flatten_error(jmp_buf jb, int val) { |
|
254 |
28 |
longjmp(jb, val); |
|
255 |
} |
||
256 |
|||
257 |
662746 |
int flatten_value_size_internal(jmp_buf jb, lbm_value v, int depth, bool image) { |
|
258 |
✓✓ | 662746 |
if (depth > flatten_maximum_depth) { |
259 |
28 |
flatten_error(jb, FLATTEN_VALUE_ERROR_MAXIMUM_DEPTH); |
|
260 |
} |
||
261 |
|||
262 |
662718 |
lbm_uint t = lbm_type_of(v); |
|
263 |
✓✓✓✗ |
662718 |
if (t >= LBM_POINTER_TYPE_FIRST && t < LBM_POINTER_TYPE_LAST) { |
264 |
// Clear constant bit, it is irrelevant to flattening |
||
265 |
493320 |
t = t & ~(LBM_PTR_TO_CONSTANT_BIT); |
|
266 |
} |
||
267 |
|||
268 |
✗✓✗✗ ✗✗ |
662718 |
if (image && lbm_is_ptr(v) && (v & LBM_PTR_TO_CONSTANT_BIT)) { |
269 |
// If flattening to image, constants can be stored by reference. |
||
270 |
return (sizeof(lbm_uint) + 1); // one byte tag, one word ptr |
||
271 |
} |
||
272 |
|||
273 |
✓✓✓✓ ✓✓✓✓ ✗ |
662718 |
switch (t) { |
274 |
313932 |
case LBM_TYPE_CONS: { |
|
275 |
313932 |
int res = 0; |
|
276 |
313932 |
int s1 = flatten_value_size_internal(jb,lbm_car(v), depth + 1, image); |
|
277 |
✓✗ | 313848 |
if (s1 > 0) { |
278 |
313848 |
int s2 = flatten_value_size_internal(jb,lbm_cdr(v), depth + 1, image); |
|
279 |
✓✗ | 313848 |
if (s2 > 0) { |
280 |
313848 |
res = (1 + s1 + s2); |
|
281 |
} |
||
282 |
} |
||
283 |
313848 |
return res; |
|
284 |
} |
||
285 |
112 |
case LBM_TYPE_LISPARRAY: { |
|
286 |
112 |
int sum = 4 + 1; // sizeof(uint32_t) + 1; |
|
287 |
112 |
lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(v); |
|
288 |
✓✗ | 112 |
if (header) { |
289 |
112 |
lbm_value *arrdata = (lbm_value*)header->data; |
|
290 |
112 |
lbm_uint size = header->size / sizeof(lbm_value); |
|
291 |
✓✓ | 476 |
for (lbm_uint i = 0; i < size; i ++ ) { |
292 |
364 |
sum += flatten_value_size_internal(jb, arrdata[i], depth + 1, image); |
|
293 |
} |
||
294 |
} else { |
||
295 |
flatten_error(jb, FLATTEN_VALUE_ERROR_ARRAY); |
||
296 |
} |
||
297 |
112 |
return sum; |
|
298 |
} |
||
299 |
60664 |
case LBM_TYPE_BYTE: |
|
300 |
60664 |
return 1 + 1; |
|
301 |
45662 |
case LBM_TYPE_U: /* fall through */ |
|
302 |
case LBM_TYPE_I: |
||
303 |
#ifndef LBM64 |
||
304 |
45662 |
return 1 + 4; |
|
305 |
#else |
||
306 |
return 1 + 8; |
||
307 |
#endif |
||
308 |
60468 |
case LBM_TYPE_U32: /* fall through */ |
|
309 |
case LBM_TYPE_I32: |
||
310 |
case LBM_TYPE_FLOAT: |
||
311 |
60468 |
return 1 + 4; |
|
312 |
84 |
case LBM_TYPE_U64: /* fall through */ |
|
313 |
case LBM_TYPE_I64: |
||
314 |
case LBM_TYPE_DOUBLE: |
||
315 |
84 |
return 1 + 8; |
|
316 |
63072 |
case LBM_TYPE_SYMBOL: { |
|
317 |
✓✗ | 63072 |
if (!image) { |
318 |
63072 |
int s = f_sym_string_bytes(v); |
|
319 |
✓✗ | 63072 |
if (s > 0) return 1 + s; |
320 |
flatten_error(jb, (int)s); |
||
321 |
} else { |
||
322 |
return 1 + sizeof(lbm_uint); |
||
323 |
} |
||
324 |
} return 0; // already terminated with error |
||
325 |
118724 |
case LBM_TYPE_ARRAY: { |
|
326 |
// Platform dependent size. |
||
327 |
// TODO: Something needs to be done to these inconsistencies. |
||
328 |
118724 |
lbm_int s = lbm_heap_array_get_size(v); |
|
329 |
✓✗ | 118724 |
if (s > 0) |
330 |
118724 |
return 1 + 4 + (int)s; |
|
331 |
flatten_error(jb, (int)s); |
||
332 |
} return 0; // already terminated with error |
||
333 |
default: |
||
334 |
return FLATTEN_VALUE_ERROR_CANNOT_BE_FLATTENED; |
||
335 |
} |
||
336 |
} |
||
337 |
|||
338 |
34602 |
int flatten_value_size(lbm_value v, bool image) { |
|
339 |
jmp_buf jb; |
||
340 |
34602 |
int r = setjmp(jb); |
|
341 |
✓✓ | 34630 |
if (r != 0) { |
342 |
28 |
return r; |
|
343 |
} |
||
344 |
34602 |
return flatten_value_size_internal(jb, v, 0, image); |
|
345 |
} |
||
346 |
|||
347 |
662466 |
int flatten_value_c(lbm_flat_value_t *fv, lbm_value v) { |
|
348 |
|||
349 |
662466 |
lbm_uint t = lbm_type_of(v); |
|
350 |
✓✓✓✗ |
662466 |
if (t >= LBM_POINTER_TYPE_FIRST && t < LBM_POINTER_TYPE_LAST) { |
351 |
// Clear constant bit, it is irrelevant to flattening |
||
352 |
493108 |
t = t & ~(LBM_PTR_TO_CONSTANT_BIT); |
|
353 |
} |
||
354 |
|||
355 |
✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✗ |
662466 |
switch (t) { |
356 |
313768 |
case LBM_TYPE_CONS: { |
|
357 |
313768 |
bool res = true; |
|
358 |
✓✗✓✗ |
313768 |
res = res && f_cons(fv); |
359 |
✓✗ | 313768 |
if (res) { |
360 |
313768 |
int fv_r = flatten_value_c(fv, lbm_car(v)); |
|
361 |
✓✗ | 313768 |
if (fv_r == FLATTEN_VALUE_OK) { |
362 |
313768 |
fv_r = flatten_value_c(fv, lbm_cdr(v)); |
|
363 |
} |
||
364 |
313768 |
return fv_r; |
|
365 |
} |
||
366 |
}break; |
||
367 |
112 |
case LBM_TYPE_LISPARRAY: { |
|
368 |
112 |
lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(v); |
|
369 |
✓✗ | 112 |
if (header) { |
370 |
112 |
lbm_value *arrdata = (lbm_value*)header->data; |
|
371 |
// always exact multiple of sizeof(lbm_value) |
||
372 |
112 |
uint32_t size = (uint32_t)(header->size / sizeof(lbm_value)); |
|
373 |
✗✓ | 112 |
if (!f_lisp_array(fv, size)) return FLATTEN_VALUE_ERROR_NOT_ENOUGH_MEMORY; |
374 |
112 |
int fv_r = FLATTEN_VALUE_OK; |
|
375 |
✓✓ | 476 |
for (lbm_uint i = 0; i < size; i ++ ) { |
376 |
364 |
fv_r = flatten_value_c(fv, arrdata[i]); |
|
377 |
✗✓ | 364 |
if (fv_r != FLATTEN_VALUE_OK) { |
378 |
break; |
||
379 |
} |
||
380 |
} |
||
381 |
112 |
return fv_r; |
|
382 |
} else { |
||
383 |
return FLATTEN_VALUE_ERROR_ARRAY; |
||
384 |
} |
||
385 |
} break; |
||
386 |
60648 |
case LBM_TYPE_BYTE: |
|
387 |
✓✗ | 60648 |
if (f_b(fv, (uint8_t)lbm_dec_as_char(v))) { |
388 |
60648 |
return FLATTEN_VALUE_OK; |
|
389 |
} |
||
390 |
break; |
||
391 |
28 |
case LBM_TYPE_U: |
|
392 |
✓✗ | 28 |
if (f_u(fv, lbm_dec_u(v))) { |
393 |
28 |
return FLATTEN_VALUE_OK; |
|
394 |
} |
||
395 |
break; |
||
396 |
45626 |
case LBM_TYPE_I: |
|
397 |
✓✗ | 45626 |
if (f_i(fv, lbm_dec_i(v))) { |
398 |
45626 |
return FLATTEN_VALUE_OK; |
|
399 |
} |
||
400 |
break; |
||
401 |
31122 |
case LBM_TYPE_U32: |
|
402 |
✓✗ | 31122 |
if (f_u32(fv, lbm_dec_as_u32(v))) { |
403 |
31122 |
return FLATTEN_VALUE_OK; |
|
404 |
} |
||
405 |
break; |
||
406 |
29274 |
case LBM_TYPE_I32: |
|
407 |
✓✗ | 29274 |
if (f_i32(fv, lbm_dec_as_i32(v))) { |
408 |
29274 |
return FLATTEN_VALUE_OK; |
|
409 |
} |
||
410 |
break; |
||
411 |
28 |
case LBM_TYPE_U64: |
|
412 |
✓✗ | 28 |
if (f_u64(fv, lbm_dec_as_u64(v))) { |
413 |
28 |
return FLATTEN_VALUE_OK; |
|
414 |
} |
||
415 |
break; |
||
416 |
28 |
case LBM_TYPE_I64: |
|
417 |
✓✗ | 28 |
if (f_i64(fv, lbm_dec_as_i64(v))) { |
418 |
28 |
return FLATTEN_VALUE_OK; |
|
419 |
} |
||
420 |
break; |
||
421 |
56 |
case LBM_TYPE_FLOAT: |
|
422 |
✓✗ | 56 |
if (f_float(fv, lbm_dec_as_float(v))) { |
423 |
56 |
return FLATTEN_VALUE_OK; |
|
424 |
} |
||
425 |
break; |
||
426 |
28 |
case LBM_TYPE_DOUBLE: |
|
427 |
✓✗ | 28 |
if (f_double(fv, lbm_dec_as_double(v))) { |
428 |
28 |
return FLATTEN_VALUE_OK; |
|
429 |
} |
||
430 |
break; |
||
431 |
63056 |
case LBM_TYPE_SYMBOL: { |
|
432 |
63056 |
char *sym_str = (char*)lbm_get_name_by_symbol(lbm_dec_sym(v)); |
|
433 |
✓✗ | 63056 |
if (f_sym_string(fv, sym_str)) { |
434 |
63056 |
return FLATTEN_VALUE_OK; |
|
435 |
} |
||
436 |
} break; |
||
437 |
118692 |
case LBM_TYPE_ARRAY: { |
|
438 |
118692 |
lbm_int s = lbm_heap_array_get_size(v); |
|
439 |
118692 |
const uint8_t *d = lbm_heap_array_get_data_ro(v); |
|
440 |
✓✗✓✗ |
118692 |
if (s > 0 && d != NULL) { |
441 |
✓✗ | 118692 |
if (f_lbm_array(fv, (uint32_t)s, (uint8_t*)d)) { |
442 |
118692 |
return FLATTEN_VALUE_OK; |
|
443 |
} |
||
444 |
} else { |
||
445 |
return FLATTEN_VALUE_ERROR_ARRAY; |
||
446 |
} |
||
447 |
}break; |
||
448 |
default: |
||
449 |
return FLATTEN_VALUE_ERROR_CANNOT_BE_FLATTENED; |
||
450 |
} |
||
451 |
return FLATTEN_VALUE_ERROR_BUFFER_TOO_SMALL; |
||
452 |
} |
||
453 |
|||
454 |
28 |
lbm_value handle_flatten_error(int err_val) { |
|
455 |
✗✗✓✗ ✗ |
28 |
switch (err_val) { |
456 |
case FLATTEN_VALUE_ERROR_CANNOT_BE_FLATTENED: |
||
457 |
return ENC_SYM_EERROR; |
||
458 |
case FLATTEN_VALUE_ERROR_BUFFER_TOO_SMALL: /* fall through */ |
||
459 |
case FLATTEN_VALUE_ERROR_FATAL: |
||
460 |
return ENC_SYM_FATAL_ERROR; |
||
461 |
28 |
case FLATTEN_VALUE_ERROR_CIRCULAR: /* fall through */ |
|
462 |
case FLATTEN_VALUE_ERROR_MAXIMUM_DEPTH: |
||
463 |
28 |
return ENC_SYM_EERROR; |
|
464 |
case FLATTEN_VALUE_ERROR_ARRAY: /* fall through */ |
||
465 |
case FLATTEN_VALUE_ERROR_NOT_ENOUGH_MEMORY: |
||
466 |
return ENC_SYM_MERROR; |
||
467 |
} |
||
468 |
return ENC_SYM_NIL; |
||
469 |
} |
||
470 |
|||
471 |
34628 |
lbm_value flatten_value(lbm_value v) { |
|
472 |
|||
473 |
34628 |
lbm_value array_cell = lbm_heap_allocate_cell(LBM_TYPE_CONS, ENC_SYM_NIL, ENC_SYM_ARRAY_TYPE); |
|
474 |
|||
475 |
✓✓ | 34628 |
if (array_cell == ENC_SYM_MERROR) { |
476 |
26 |
return array_cell; |
|
477 |
} |
||
478 |
|||
479 |
lbm_flat_value_t fv; |
||
480 |
|||
481 |
34602 |
lbm_array_header_t *array = NULL; |
|
482 |
34602 |
int required_mem = flatten_value_size(v, false); |
|
483 |
✓✓ | 34602 |
if (required_mem > 0) { |
484 |
34574 |
array = (lbm_array_header_t *)lbm_malloc(sizeof(lbm_array_header_t)); |
|
485 |
✓✓ | 34574 |
if (array == NULL) { |
486 |
8 |
lbm_set_car_and_cdr(array_cell, ENC_SYM_NIL, ENC_SYM_NIL); |
|
487 |
8 |
return ENC_SYM_MERROR; |
|
488 |
} |
||
489 |
|||
490 |
34566 |
bool r = lbm_start_flatten(&fv, (lbm_uint)required_mem); |
|
491 |
✗✓ | 34566 |
if (!r) { |
492 |
lbm_free(array); |
||
493 |
lbm_set_car_and_cdr(array_cell, ENC_SYM_NIL, ENC_SYM_NIL); |
||
494 |
return ENC_SYM_MERROR; |
||
495 |
} |
||
496 |
|||
497 |
✓✗ | 34566 |
if (flatten_value_c(&fv, v) == FLATTEN_VALUE_OK) { |
498 |
// it would be wasteful to run finish_flatten here. |
||
499 |
34566 |
r = true; |
|
500 |
} else { |
||
501 |
r = false; |
||
502 |
} |
||
503 |
|||
504 |
✓✗ | 34566 |
if (r) { |
505 |
// lift flat_value |
||
506 |
34566 |
array->data = (lbm_uint*)fv.buf; |
|
507 |
34566 |
array->size = fv.buf_size; |
|
508 |
34566 |
lbm_set_car(array_cell, (lbm_uint)array); |
|
509 |
34566 |
array_cell = lbm_set_ptr_type(array_cell, LBM_TYPE_ARRAY); |
|
510 |
34566 |
return array_cell; |
|
511 |
} |
||
512 |
} |
||
513 |
28 |
lbm_set_car_and_cdr(array_cell, ENC_SYM_NIL, ENC_SYM_NIL); |
|
514 |
28 |
return handle_flatten_error(required_mem); |
|
515 |
} |
||
516 |
|||
517 |
// ------------------------------------------------------------ |
||
518 |
// Unflattening |
||
519 |
60650 |
static bool extract_byte(lbm_flat_value_t *v, uint8_t *r) { |
|
520 |
✓✗ | 60650 |
if (v->buf_size >= v->buf_pos + 1) { |
521 |
60650 |
*r = v->buf[v->buf_pos++]; |
|
522 |
60650 |
return true; |
|
523 |
} |
||
524 |
return false; |
||
525 |
} |
||
526 |
|||
527 |
236489 |
static bool extract_word(lbm_flat_value_t *v, uint32_t *r) { |
|
528 |
236489 |
bool res = false; |
|
529 |
✓✗ | 236489 |
if (v->buf_size >= v->buf_pos + 4) { |
530 |
236489 |
uint32_t tmp = 0; |
|
531 |
236489 |
tmp |= (lbm_value)v->buf[v->buf_pos++]; |
|
532 |
236489 |
tmp = tmp << 8 | (uint32_t)v->buf[v->buf_pos++]; |
|
533 |
236489 |
tmp = tmp << 8 | (uint32_t)v->buf[v->buf_pos++]; |
|
534 |
236489 |
tmp = tmp << 8 | (uint32_t)v->buf[v->buf_pos++]; |
|
535 |
236489 |
*r = tmp; |
|
536 |
236489 |
res = true; |
|
537 |
} |
||
538 |
236489 |
return res; |
|
539 |
} |
||
540 |
|||
541 |
84 |
static bool extract_dword(lbm_flat_value_t *v, uint64_t *r) { |
|
542 |
84 |
bool res = false; |
|
543 |
✓✗ | 84 |
if (v->buf_size >= v->buf_pos + 8) { |
544 |
84 |
uint64_t tmp = 0; |
|
545 |
84 |
tmp |= (lbm_value)v->buf[v->buf_pos++]; |
|
546 |
84 |
tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; |
|
547 |
84 |
tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; |
|
548 |
84 |
tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; |
|
549 |
84 |
tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; |
|
550 |
84 |
tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; |
|
551 |
84 |
tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; |
|
552 |
84 |
tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; |
|
553 |
84 |
*r = tmp; |
|
554 |
84 |
res = true;; |
|
555 |
} |
||
556 |
84 |
return res; |
|
557 |
} |
||
558 |
|||
559 |
359899 |
static int lbm_unflatten_value_atom(lbm_flat_value_t *v, lbm_value *res) { |
|
560 |
✗✓ | 359899 |
if (v->buf_size == v->buf_pos) return UNFLATTEN_MALFORMED; |
561 |
|||
562 |
359899 |
uint8_t curr = v->buf[v->buf_pos++]; |
|
563 |
|||
564 |
✗✗✓✓ ✓✓✗✗ ✓✓✓✓ ✓✓✓✓ ✗ |
359899 |
switch(curr) { |
565 |
case S_CONS: { |
||
566 |
return UNFLATTEN_MALFORMED; |
||
567 |
} |
||
568 |
case S_CONSTANT_REF: { |
||
569 |
lbm_uint tmp; |
||
570 |
bool b; |
||
571 |
#ifndef LBM64 |
||
572 |
b = extract_word(v, &tmp); |
||
573 |
#else |
||
574 |
b = extract_dword(v, &tmp); |
||
575 |
#endif |
||
576 |
if (b) { |
||
577 |
*res = tmp; |
||
578 |
return UNFLATTEN_OK; |
||
579 |
} |
||
580 |
return UNFLATTEN_MALFORMED; |
||
581 |
} |
||
582 |
4983 |
case S_SYM_VALUE: { |
|
583 |
lbm_uint tmp; |
||
584 |
bool b; |
||
585 |
#ifndef LBM64 |
||
586 |
4983 |
b = extract_word(v, &tmp); |
|
587 |
#else |
||
588 |
b = extract_dword(v, &tmp); |
||
589 |
#endif |
||
590 |
✓✗ | 4983 |
if (b) { |
591 |
4983 |
*res = lbm_enc_sym(tmp); |
|
592 |
4983 |
return UNFLATTEN_OK; |
|
593 |
} |
||
594 |
return UNFLATTEN_MALFORMED; |
||
595 |
} |
||
596 |
60650 |
case S_BYTE_VALUE: { |
|
597 |
uint8_t tmp; |
||
598 |
60650 |
bool b = extract_byte(v, &tmp); |
|
599 |
✓✗ | 60650 |
if (b) { |
600 |
60650 |
*res = lbm_enc_char((uint8_t)tmp); |
|
601 |
60650 |
return UNFLATTEN_OK; |
|
602 |
} |
||
603 |
return UNFLATTEN_MALFORMED; |
||
604 |
} |
||
605 |
45486 |
case S_I28_VALUE: { |
|
606 |
uint32_t tmp; |
||
607 |
bool b; |
||
608 |
45486 |
b = extract_word(v, &tmp); |
|
609 |
✓✗ | 45486 |
if (b) { |
610 |
45486 |
*res = lbm_enc_i((int32_t)tmp); |
|
611 |
45486 |
return UNFLATTEN_OK; |
|
612 |
} |
||
613 |
return UNFLATTEN_MALFORMED; |
||
614 |
} |
||
615 |
28 |
case S_U28_VALUE: { |
|
616 |
uint32_t tmp; |
||
617 |
bool b; |
||
618 |
28 |
b = extract_word(v, &tmp); |
|
619 |
✓✗ | 28 |
if (b) { |
620 |
28 |
*res = lbm_enc_u((uint32_t)tmp); |
|
621 |
28 |
return UNFLATTEN_OK; |
|
622 |
} |
||
623 |
return UNFLATTEN_MALFORMED; |
||
624 |
} |
||
625 |
case S_I56_VALUE: { |
||
626 |
uint64_t tmp; |
||
627 |
bool b; |
||
628 |
b = extract_dword(v, &tmp); |
||
629 |
if (b) { |
||
630 |
#ifndef LBM64 |
||
631 |
*res = lbm_enc_i64((int64_t)tmp); |
||
632 |
#else |
||
633 |
*res = lbm_enc_i((int64_t)tmp); |
||
634 |
#endif |
||
635 |
return UNFLATTEN_OK; |
||
636 |
} |
||
637 |
return UNFLATTEN_MALFORMED; |
||
638 |
} |
||
639 |
case S_U56_VALUE: { |
||
640 |
uint64_t tmp; |
||
641 |
bool b; |
||
642 |
b = extract_dword(v, &tmp); |
||
643 |
if (b) { |
||
644 |
#ifndef LBM64 |
||
645 |
*res = lbm_enc_u64(tmp); |
||
646 |
#else |
||
647 |
*res = lbm_enc_u(tmp); |
||
648 |
#endif |
||
649 |
return UNFLATTEN_OK; |
||
650 |
} |
||
651 |
return UNFLATTEN_MALFORMED; |
||
652 |
} |
||
653 |
7164 |
case S_FLOAT_VALUE: { |
|
654 |
uint32_t tmp; |
||
655 |
bool b; |
||
656 |
7164 |
b = extract_word(v, &tmp); |
|
657 |
✓✗ | 7164 |
if (b) { |
658 |
lbm_float f; |
||
659 |
7164 |
memcpy(&f, &tmp, sizeof(lbm_float)); |
|
660 |
7164 |
lbm_value im = lbm_enc_float(f); |
|
661 |
✗✓ | 7164 |
if (lbm_is_symbol_merror(im)) { |
662 |
return UNFLATTEN_GC_RETRY; |
||
663 |
} |
||
664 |
7164 |
*res = im; |
|
665 |
7164 |
return UNFLATTEN_OK; |
|
666 |
} |
||
667 |
return UNFLATTEN_MALFORMED; |
||
668 |
} |
||
669 |
28 |
case S_DOUBLE_VALUE: { |
|
670 |
uint64_t tmp; |
||
671 |
bool b; |
||
672 |
28 |
b = extract_dword(v, &tmp); |
|
673 |
✓✗ | 28 |
if (b) { |
674 |
double f; |
||
675 |
28 |
memcpy(&f, &tmp, sizeof(uint64_t)); |
|
676 |
28 |
lbm_value im = lbm_enc_double(f); |
|
677 |
✗✓ | 28 |
if (lbm_is_symbol_merror(im)) { |
678 |
return UNFLATTEN_GC_RETRY; |
||
679 |
} |
||
680 |
28 |
*res = im; |
|
681 |
28 |
return UNFLATTEN_OK; |
|
682 |
} |
||
683 |
return UNFLATTEN_MALFORMED; |
||
684 |
} |
||
685 |
29130 |
case S_I32_VALUE: { |
|
686 |
uint32_t tmp; |
||
687 |
✓✗ | 29130 |
if (extract_word(v, &tmp)) { |
688 |
29130 |
lbm_value im = lbm_enc_i32((int32_t)tmp); |
|
689 |
✓✓ | 29130 |
if (lbm_is_symbol_merror(im)) { |
690 |
8 |
return UNFLATTEN_GC_RETRY; |
|
691 |
} |
||
692 |
29122 |
*res = im; |
|
693 |
29122 |
return UNFLATTEN_OK; |
|
694 |
} |
||
695 |
return UNFLATTEN_MALFORMED; |
||
696 |
} |
||
697 |
31194 |
case S_U32_VALUE: { |
|
698 |
uint32_t tmp; |
||
699 |
✓✗ | 31194 |
if (extract_word(v, &tmp)) { |
700 |
31194 |
lbm_value im = lbm_enc_u32(tmp); |
|
701 |
✓✓ | 31194 |
if (lbm_is_symbol_merror(im)) { |
702 |
20 |
return UNFLATTEN_GC_RETRY; |
|
703 |
} |
||
704 |
31174 |
*res = im; |
|
705 |
31174 |
return UNFLATTEN_OK; |
|
706 |
} |
||
707 |
return UNFLATTEN_MALFORMED; |
||
708 |
} |
||
709 |
28 |
case S_I64_VALUE: { |
|
710 |
28 |
uint64_t tmp = 0; |
|
711 |
✓✗ | 28 |
if (extract_dword(v, &tmp)) { |
712 |
28 |
lbm_value im = lbm_enc_i64((int64_t)tmp); |
|
713 |
✗✓ | 28 |
if (lbm_is_symbol_merror(im)) { |
714 |
return UNFLATTEN_GC_RETRY; |
||
715 |
} |
||
716 |
28 |
*res = im; |
|
717 |
28 |
return UNFLATTEN_OK; |
|
718 |
} |
||
719 |
return UNFLATTEN_MALFORMED; |
||
720 |
} |
||
721 |
28 |
case S_U64_VALUE: { |
|
722 |
28 |
uint64_t tmp = 0; |
|
723 |
✓✗ | 28 |
if (extract_dword(v, &tmp)) { |
724 |
28 |
lbm_value im = lbm_enc_u64(tmp); |
|
725 |
✗✓ | 28 |
if (lbm_is_symbol_merror(im)) { |
726 |
return UNFLATTEN_GC_RETRY; |
||
727 |
} |
||
728 |
28 |
*res = im; |
|
729 |
28 |
return UNFLATTEN_OK; |
|
730 |
} |
||
731 |
return UNFLATTEN_MALFORMED; |
||
732 |
} |
||
733 |
118392 |
case S_LBM_ARRAY: { |
|
734 |
uint32_t num_elt; |
||
735 |
✓✗ | 118392 |
if (extract_word(v, &num_elt)) { |
736 |
✓✓ | 118392 |
if (lbm_heap_allocate_array(res, num_elt)) { |
737 |
118254 |
lbm_array_header_t *arr = (lbm_array_header_t*)lbm_car(*res); |
|
738 |
118254 |
lbm_uint num_bytes = num_elt; |
|
739 |
118254 |
memcpy(arr->data, v->buf + v->buf_pos, num_bytes); |
|
740 |
118254 |
v->buf_pos += num_bytes; |
|
741 |
} else { |
||
742 |
138 |
return UNFLATTEN_GC_RETRY; |
|
743 |
} |
||
744 |
118254 |
return UNFLATTEN_OK; |
|
745 |
} |
||
746 |
return UNFLATTEN_MALFORMED; |
||
747 |
} |
||
748 |
62788 |
case S_SYM_STRING: { |
|
749 |
lbm_uint sym_id; |
||
750 |
✓✗ | 62788 |
if (lbm_add_symbol((char *)(v->buf + v->buf_pos), &sym_id)) { |
751 |
62788 |
lbm_uint num_bytes = strlen((char*)(v->buf + v->buf_pos)) + 1; |
|
752 |
62788 |
v->buf_pos += num_bytes; |
|
753 |
62788 |
*res = lbm_enc_sym(sym_id); |
|
754 |
62788 |
return UNFLATTEN_OK; |
|
755 |
} |
||
756 |
return UNFLATTEN_GC_RETRY; |
||
757 |
} |
||
758 |
default: |
||
759 |
return UNFLATTEN_MALFORMED; |
||
760 |
} |
||
761 |
} |
||
762 |
|||
763 |
// //////////////////////////////////////////////////////////// |
||
764 |
// Pointer-reversal-esque "stackless" deserialization of |
||
765 |
// flattened (serialized) trees. |
||
766 |
// |
||
767 |
// Initially: |
||
768 |
// curr = LBM_NULL; v->buf = { ... } |
||
769 |
// |
||
770 |
// FORWARDS PHASE: |
||
771 |
// Cons case: |
||
772 |
// Reading conses from the buffer builds a backpointing list. |
||
773 |
// Placeholder element acts as a 1 bit "visited" field. |
||
774 |
// |
||
775 |
// curr = p; v->buf = {S_CONS, ... } |
||
776 |
// => |
||
777 |
// curr = [p, placeholder]; v->buf = { ... } |
||
778 |
// |
||
779 |
// Lisp array case: |
||
780 |
// An Array tag in the buffer leads to the creation of an array |
||
781 |
// with a backptr in the last element position. Placeholder element |
||
782 |
// is not needed as LBM-Arrays have a built in index field (used by GC) |
||
783 |
// that can keep a count of how far along the array we have progressed. |
||
784 |
// |
||
785 |
// curr = p; v->buf = {S_LBM_LISP_ARRAY, ... } |
||
786 |
// => |
||
787 |
// curr = [| nil ... p |]; v->buf = { ... } |
||
788 |
// |
||
789 |
// Atom case: |
||
790 |
// Reading an atom triggers a backwards traversal along the backpointer |
||
791 |
// structure. |
||
792 |
// |
||
793 |
// curr = X; v->buf = {any_atom, ... } example integer, string. |
||
794 |
// => |
||
795 |
// val = unflatten_atom(v->buf); v->buf = { ... } |
||
796 |
// |
||
797 |
// BACKWARDS PHASE: Start the backwards traversal: |
||
798 |
// |
||
799 |
// Case on X |
||
800 |
// LBM_NULL; |
||
801 |
// => Done! result = val |
||
802 |
// |
||
803 |
// [p, placeholder]; |
||
804 |
// => |
||
805 |
// [p, val] Base case. Finishes back traversal. |
||
806 |
// Go back to FORWARDS PHASE. |
||
807 |
// |
||
808 |
// |
||
809 |
// [p, val0]; |
||
810 |
// => |
||
811 |
// tmp = [val0, val]; val = tmp; curr = p; continue backwards with value pointing to recently constructed final subresult. |
||
812 |
// |
||
813 |
// |
||
814 |
// [| a b nil ... p |] |
||
815 |
// => |
||
816 |
// [| a b val ... p |] Base case. Finishes back traversal. |
||
817 |
// Array internal index field keeps track of write position. |
||
818 |
// Go back to FORWARDS PHASE. |
||
819 |
// |
||
820 |
// |
||
821 |
// [| a0 a1 ... an p |] |
||
822 |
// => |
||
823 |
// tmp = [| a0 a1 ... an val |]; val = tmp; curr = p; continue backwards |
||
824 |
// |
||
825 |
40891 |
static int lbm_unflatten_value_nostack(lbm_flat_value_t *v, lbm_value *res) { |
|
826 |
40891 |
bool done = false; |
|
827 |
|||
828 |
40891 |
lbm_value curr = lbm_enc_cons_ptr(LBM_PTR_NULL); |
|
829 |
✓✗ | 679105 |
while (!done) { |
830 |
✓✓ | 679105 |
if (v->buf[v->buf_pos] == S_CONS) { |
831 |
319094 |
lbm_value tmp = curr; |
|
832 |
319094 |
curr = lbm_cons(tmp, ENC_SYM_PLACEHOLDER); |
|
833 |
✓✓ | 319094 |
if (lbm_is_symbol_merror(curr)) return UNFLATTEN_GC_RETRY; |
834 |
319008 |
v->buf_pos ++; |
|
835 |
✓✓ | 360011 |
} else if (v->buf[v->buf_pos] == S_LBM_LISP_ARRAY) { |
836 |
uint32_t size; |
||
837 |
112 |
v->buf_pos ++; |
|
838 |
112 |
bool b = extract_word(v, &size); |
|
839 |
✓✗ | 112 |
if (b) { |
840 |
lbm_value array; |
||
841 |
112 |
lbm_heap_allocate_lisp_array(&array, size); |
|
842 |
112 |
lbm_array_header_extended_t *header = (lbm_array_header_extended_t*)lbm_car(array); |
|
843 |
112 |
lbm_value *arrdata = (lbm_value*)header->data; |
|
844 |
✗✓ | 112 |
if (lbm_is_symbol_merror(array)) return UNFLATTEN_GC_RETRY; |
845 |
112 |
header->index = 0; |
|
846 |
112 |
arrdata[size-1] = curr; // backptr |
|
847 |
112 |
curr = array; |
|
848 |
} else { |
||
849 |
return UNFLATTEN_MALFORMED; |
||
850 |
} |
||
851 |
✗✓ | 359899 |
} else if (v->buf[v->buf_pos] == 0) { |
852 |
return UNFLATTEN_MALFORMED; |
||
853 |
} else { |
||
854 |
lbm_value unflattened; |
||
855 |
✓✓ | 359899 |
if (lbm_unflatten_value_atom(v, &unflattened) != UNFLATTEN_OK) { |
856 |
166 |
return UNFLATTEN_MALFORMED; |
|
857 |
} |
||
858 |
359733 |
lbm_value val0 = unflattened; |
|
859 |
✓✓✓✓ |
1315027 |
while (lbm_dec_ptr(curr) != LBM_PTR_NULL && |
860 |
637194 |
lbm_cdr(curr) != ENC_SYM_PLACEHOLDER) { // has done left |
|
861 |
✓✓ | 318352 |
if ( lbm_type_of(curr) == LBM_TYPE_LISPARRAY) { |
862 |
364 |
lbm_array_header_extended_t *header = (lbm_array_header_extended_t*)lbm_car(curr); |
|
863 |
364 |
lbm_value *arrdata = (lbm_value*)header->data; |
|
864 |
364 |
uint32_t arrlen = header->size / sizeof(lbm_value); |
|
865 |
✓✓ | 364 |
if (header->index == arrlen - 1) { |
866 |
112 |
lbm_value prev = arrdata[arrlen-1]; |
|
867 |
112 |
header->index = 0; |
|
868 |
112 |
arrdata[arrlen-1] = val0; |
|
869 |
112 |
val0 = curr; |
|
870 |
112 |
curr = prev; |
|
871 |
} else { |
||
872 |
252 |
arrdata[header->index++] = val0; |
|
873 |
252 |
break; |
|
874 |
} |
||
875 |
} else { |
||
876 |
317988 |
lbm_value prev = lbm_car(curr); |
|
877 |
317988 |
lbm_value r0 = lbm_cdr(curr); |
|
878 |
317988 |
lbm_set_cdr(curr, val0); |
|
879 |
317988 |
lbm_set_car(curr, r0); |
|
880 |
317988 |
val0 = curr; |
|
881 |
317988 |
curr = prev; |
|
882 |
} |
||
883 |
} |
||
884 |
✓✓ | 359733 |
if (lbm_dec_ptr(curr) == LBM_PTR_NULL) { |
885 |
40639 |
*res = val0; // done |
|
886 |
40639 |
break; |
|
887 |
✓✓ | 319094 |
} else if (lbm_type_of(curr) == LBM_TYPE_LISPARRAY) { |
888 |
// Do nothing in this case. It has been arranged.. |
||
889 |
✓✗ | 318842 |
} else if (lbm_cdr(curr) == ENC_SYM_PLACEHOLDER) { |
890 |
318842 |
lbm_set_cdr(curr, val0); |
|
891 |
} else { |
||
892 |
return UNFLATTEN_MALFORMED; |
||
893 |
} |
||
894 |
} |
||
895 |
} |
||
896 |
40639 |
return UNFLATTEN_OK; |
|
897 |
} |
||
898 |
|||
899 |
40805 |
bool lbm_unflatten_value(lbm_flat_value_t *v, lbm_value *res) { |
|
900 |
40805 |
bool b = false; |
|
901 |
#ifdef LBM_ALWAYS_GC |
||
902 |
lbm_perform_gc(); |
||
903 |
#endif |
||
904 |
40805 |
int r = lbm_unflatten_value_nostack(v,res); |
|
905 |
✓✓ | 40805 |
if (r == UNFLATTEN_GC_RETRY) { |
906 |
86 |
lbm_perform_gc(); |
|
907 |
86 |
v->buf_pos = 0; |
|
908 |
86 |
r = lbm_unflatten_value_nostack(v,res); |
|
909 |
} |
||
910 |
✓✓ | 40805 |
if (r == UNFLATTEN_MALFORMED) { |
911 |
166 |
*res = ENC_SYM_EERROR; |
|
912 |
✗✓ | 40639 |
} else if (r == UNFLATTEN_GC_RETRY) { |
913 |
*res = ENC_SYM_MERROR; |
||
914 |
} else { |
||
915 |
40639 |
b = true; |
|
916 |
} |
||
917 |
// Do not free the flat value buffer here. |
||
918 |
// there are 2 cases: |
||
919 |
// 1: unflatten was called from lisp code -> GC removes the buffer. |
||
920 |
// 2: unflatten called from event processing -> event processor frees buffer. |
||
921 |
40805 |
return b; |
|
922 |
} |
Generated by: GCOVR (Version 4.2) |