Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | Copyright 2023, 2024 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 | |||
33 | 8346 | bool lbm_start_flatten(lbm_flat_value_t *v, size_t buffer_size) { | |
34 | |||
35 | 8346 | uint8_t *data = lbm_malloc_reserve(buffer_size); | |
36 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8346 times.
|
8346 | if (!data) return false; |
37 | |||
38 | 8346 | v->buf = data; | |
39 | 8346 | v->buf_size = buffer_size; | |
40 | 8346 | v->buf_pos = 0; | |
41 | 8346 | return true; | |
42 | } | ||
43 | |||
44 | 8066 | bool lbm_finish_flatten(lbm_flat_value_t *v) { | |
45 | |||
46 | lbm_uint size_words; | ||
47 | |||
48 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8066 times.
|
8066 | if (v->buf_pos % sizeof(lbm_uint) == 0) { |
49 | ✗ | size_words = v->buf_pos / sizeof(lbm_uint); | |
50 | } else { | ||
51 | 8066 | size_words = (v->buf_pos / sizeof(lbm_uint)) + 1; | |
52 | } | ||
53 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 8038 times.
|
8066 | if (v->buf_size <= size_words * sizeof(lbm_uint)) return true; |
54 | 8038 | v->buf_size = size_words * sizeof(lbm_uint); | |
55 | 8038 | return (lbm_memory_shrink((lbm_uint*)v->buf, size_words) >= 0); | |
56 | } | ||
57 | |||
58 | 18941 | static bool write_byte(lbm_flat_value_t *v, uint8_t b) { | |
59 |
1/2✓ Branch 0 taken 18941 times.
✗ Branch 1 not taken.
|
18941 | if (v->buf_size >= v->buf_pos + 1) { |
60 | 18941 | v->buf[v->buf_pos++] = b; | |
61 | 18941 | return true; | |
62 | } | ||
63 | ✗ | return false; | |
64 | } | ||
65 | |||
66 | 17037 | static bool write_word(lbm_flat_value_t *v, uint32_t w) { | |
67 | |||
68 |
1/2✓ Branch 0 taken 17037 times.
✗ Branch 1 not taken.
|
17037 | if (v->buf_size >= v->buf_pos + 4) { |
69 | 17037 | v->buf[v->buf_pos++] = (uint8_t)(w >> 24); | |
70 | 17037 | v->buf[v->buf_pos++] = (uint8_t)(w >> 16); | |
71 | 17037 | v->buf[v->buf_pos++] = (uint8_t)(w >> 8); | |
72 | 17037 | v->buf[v->buf_pos++] = (uint8_t)w; | |
73 | 17037 | return true; | |
74 | } | ||
75 | ✗ | return false; | |
76 | } | ||
77 | |||
78 | ✗ | static bool write_dword(lbm_flat_value_t *v, uint64_t w) { | |
79 | ✗ | if (v->buf_size >= v->buf_pos + 8) { | |
80 | ✗ | v->buf[v->buf_pos++] = (uint8_t)(w >> 56); | |
81 | ✗ | v->buf[v->buf_pos++] = (uint8_t)(w >> 48); | |
82 | ✗ | v->buf[v->buf_pos++] = (uint8_t)(w >> 40); | |
83 | ✗ | v->buf[v->buf_pos++] = (uint8_t)(w >> 32); | |
84 | ✗ | v->buf[v->buf_pos++] = (uint8_t)(w >> 24); | |
85 | ✗ | v->buf[v->buf_pos++] = (uint8_t)(w >> 16); | |
86 | ✗ | v->buf[v->buf_pos++] = (uint8_t)(w >> 8); | |
87 | ✗ | v->buf[v->buf_pos++] = (uint8_t)w; | |
88 | ✗ | return true; | |
89 | } | ||
90 | ✗ | return false; | |
91 | } | ||
92 | |||
93 | 8999 | bool f_cons(lbm_flat_value_t *v) { | |
94 |
1/2✓ Branch 0 taken 8999 times.
✗ Branch 1 not taken.
|
8999 | if (v->buf_size >= v->buf_pos + 1) { |
95 | 8999 | v->buf[v->buf_pos++] = S_CONS; | |
96 | 8999 | return true; | |
97 | } | ||
98 | ✗ | return false; | |
99 | } | ||
100 | |||
101 | 28 | bool f_lisp_array(lbm_flat_value_t *v, uint32_t size) { | |
102 | // arrays are smaller than 2^32 elements long | ||
103 | 28 | bool res = true; | |
104 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
|
28 | res = res && write_byte(v, S_LBM_LISP_ARRAY); |
105 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
|
28 | res = res && write_word(v, size); // number of elements. |
106 | 28 | return res; | |
107 | } | ||
108 | |||
109 | 6341 | bool f_sym(lbm_flat_value_t *v, lbm_uint sym_id) { | |
110 | 6341 | bool res = true; | |
111 |
2/4✓ Branch 0 taken 6341 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 6341 times.
✗ Branch 4 not taken.
|
6341 | res = res && write_byte(v,S_SYM_VALUE); |
112 | #ifndef LBM64 | ||
113 |
2/4✓ Branch 0 taken 6341 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 6341 times.
✗ Branch 4 not taken.
|
6341 | res = res && write_word(v,sym_id); |
114 | #else | ||
115 | res = res && write_dword(v,sym_id); | ||
116 | #endif | ||
117 | 6341 | return res; | |
118 | } | ||
119 | |||
120 | 392 | bool f_sym_string(lbm_flat_value_t *v, char *str) { | |
121 | 392 | bool res = true; | |
122 |
1/2✓ Branch 0 taken 392 times.
✗ Branch 1 not taken.
|
392 | if (str) { |
123 | 392 | lbm_uint sym_bytes = strlen(str) + 1; | |
124 |
2/4✓ Branch 0 taken 392 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 392 times.
✗ Branch 4 not taken.
|
392 | res = res && write_byte(v, S_SYM_STRING); |
125 |
2/4✓ Branch 0 taken 392 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 392 times.
✗ Branch 3 not taken.
|
392 | if (res && v->buf_size >= v->buf_pos + sym_bytes) { |
126 |
2/2✓ Branch 0 taken 1512 times.
✓ Branch 1 taken 392 times.
|
1904 | for (lbm_uint i = 0; i < sym_bytes; i ++) { |
127 |
2/4✓ Branch 0 taken 1512 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1512 times.
✗ Branch 4 not taken.
|
1512 | res = res && write_byte(v, (uint8_t)str[i]); |
128 | } | ||
129 | 392 | return res; | |
130 | } | ||
131 | } | ||
132 | ✗ | return false; | |
133 | } | ||
134 | |||
135 | // Potentially a difference between 32/64 bit version. | ||
136 | // strlen returns size_t which is different on 32/64 bit platforms. | ||
137 | 364 | int f_sym_string_bytes(lbm_value sym) { | |
138 | char *sym_str; | ||
139 |
1/2✓ Branch 1 taken 364 times.
✗ Branch 2 not taken.
|
364 | if (lbm_is_symbol(sym)) { |
140 | 364 | lbm_uint s = lbm_dec_sym(sym); | |
141 | 364 | sym_str = (char*)lbm_get_name_by_symbol(s); | |
142 |
1/2✓ Branch 0 taken 364 times.
✗ Branch 1 not taken.
|
364 | if (sym_str) { |
143 | 364 | lbm_uint sym_bytes = strlen(sym_str) + 1; | |
144 | 364 | return (int)sym_bytes; | |
145 | } | ||
146 | } | ||
147 | ✗ | return FLATTEN_VALUE_ERROR_FATAL; | |
148 | } | ||
149 | |||
150 | 756 | bool f_i(lbm_flat_value_t *v, lbm_int i) { | |
151 | 756 | bool res = true; | |
152 | #ifndef LBM64 | ||
153 |
2/4✓ Branch 0 taken 756 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 756 times.
✗ Branch 4 not taken.
|
756 | res = res && write_byte(v,S_I28_VALUE); |
154 |
2/4✓ Branch 0 taken 756 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 756 times.
✗ Branch 4 not taken.
|
756 | res = res && write_word(v,(uint32_t)i); |
155 | #else | ||
156 | res = res && write_byte(v,S_I56_VALUE); | ||
157 | res = res && write_dword(v, (uint64_t)i); | ||
158 | #endif | ||
159 | 756 | return res; | |
160 | } | ||
161 | |||
162 | ✗ | bool f_u(lbm_flat_value_t *v, lbm_uint u) { | |
163 | ✗ | bool res = true; | |
164 | #ifndef LBM64 | ||
165 | ✗ | res = res && write_byte(v,S_U28_VALUE); | |
166 | ✗ | res = res && write_word(v,(uint32_t)u); | |
167 | #else | ||
168 | res = res && write_byte(v,S_U56_VALUE); | ||
169 | res = res && write_dword(v,(uint64_t)u); | ||
170 | #endif | ||
171 | ✗ | return res; | |
172 | } | ||
173 | |||
174 | ✗ | bool f_b(lbm_flat_value_t *v, uint8_t b) { | |
175 | ✗ | bool res = true; | |
176 | ✗ | res = res && write_byte(v,S_BYTE_VALUE); | |
177 | ✗ | res = res && write_byte(v,b); | |
178 | ✗ | return res; | |
179 | } | ||
180 | |||
181 | 28 | bool f_i32(lbm_flat_value_t *v, int32_t w) { | |
182 | 28 | bool res = true; | |
183 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
|
28 | res = res && write_byte(v, S_I32_VALUE); |
184 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
|
28 | res = res && write_word(v, (uint32_t)w); |
185 | 28 | return res; | |
186 | } | ||
187 | |||
188 | 28 | bool f_u32(lbm_flat_value_t *v, uint32_t w) { | |
189 | 28 | bool res = true; | |
190 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
|
28 | res = res && write_byte(v, S_U32_VALUE); |
191 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
|
28 | res = res && write_word(v, w); |
192 | 28 | return res; | |
193 | } | ||
194 | |||
195 | 9576 | bool f_float(lbm_flat_value_t *v, float f) { | |
196 | 9576 | bool res = true; | |
197 |
2/4✓ Branch 0 taken 9576 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 9576 times.
✗ Branch 4 not taken.
|
9576 | res = res && write_byte(v, S_FLOAT_VALUE); |
198 | uint32_t u; | ||
199 | 9576 | memcpy(&u, &f, sizeof(uint32_t)); | |
200 |
2/4✓ Branch 0 taken 9576 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 9576 times.
✗ Branch 4 not taken.
|
9576 | res = res && write_word(v, (uint32_t)u); |
201 | 9576 | return res; | |
202 | } | ||
203 | |||
204 | ✗ | bool f_double(lbm_flat_value_t *v, double d) { | |
205 | ✗ | bool res = true; | |
206 | ✗ | res = res && write_byte(v, S_DOUBLE_VALUE); | |
207 | uint64_t u; | ||
208 | ✗ | memcpy(&u, &d, sizeof(uint64_t)); | |
209 | ✗ | res = res && write_dword(v, u); | |
210 | ✗ | return res; | |
211 | } | ||
212 | |||
213 | ✗ | bool f_i64(lbm_flat_value_t *v, int64_t w) { | |
214 | ✗ | bool res = true; | |
215 | ✗ | res = res && write_byte(v, S_I64_VALUE); | |
216 | ✗ | res = res && write_dword(v, (uint64_t)w); | |
217 | ✗ | return res; | |
218 | } | ||
219 | |||
220 | ✗ | bool f_u64(lbm_flat_value_t *v, uint64_t w) { | |
221 | ✗ | bool res = true; | |
222 | ✗ | res = res && write_byte(v, S_U64_VALUE); | |
223 | ✗ | res = res && write_dword(v, w); | |
224 | ✗ | return res; | |
225 | } | ||
226 | |||
227 | // num_bytes is specifically an uint32_t | ||
228 | 280 | bool f_lbm_array(lbm_flat_value_t *v, uint32_t num_bytes, uint8_t *data) { | |
229 | 280 | bool res = true; | |
230 |
2/4✓ Branch 0 taken 280 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 280 times.
✗ Branch 4 not taken.
|
280 | res = res && write_byte(v, S_LBM_ARRAY); |
231 |
2/4✓ Branch 0 taken 280 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 280 times.
✗ Branch 4 not taken.
|
280 | res = res && write_word(v, num_bytes); |
232 |
2/4✓ Branch 0 taken 280 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 280 times.
✗ Branch 3 not taken.
|
280 | if (res && v->buf_size >= v->buf_pos + num_bytes) { |
233 | 280 | memcpy(v->buf + v->buf_pos, data, num_bytes); | |
234 | 280 | v->buf_pos += num_bytes; | |
235 | } else { | ||
236 | ✗ | res = false; | |
237 | } | ||
238 | 280 | return res; | |
239 | } | ||
240 | |||
241 | static int flatten_maximum_depth = FLATTEN_VALUE_MAXIMUM_DEPTH; | ||
242 | |||
243 | ✗ | void lbm_set_max_flatten_depth(int depth) { | |
244 | ✗ | flatten_maximum_depth = depth; | |
245 | ✗ | } | |
246 | |||
247 | ✗ | void flatten_error(jmp_buf jb, int val) { | |
248 | ✗ | longjmp(jb, val); | |
249 | } | ||
250 | |||
251 | 2548 | int flatten_value_size_internal(jmp_buf jb, lbm_value v, int depth) { | |
252 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2548 times.
|
2548 | if (depth > flatten_maximum_depth) { |
253 | ✗ | flatten_error(jb, FLATTEN_VALUE_ERROR_MAXIMUM_DEPTH); | |
254 | } | ||
255 | |||
256 | 2548 | lbm_uint t = lbm_type_of(v); | |
257 |
3/4✓ Branch 0 taken 1428 times.
✓ Branch 1 taken 1120 times.
✓ Branch 2 taken 1428 times.
✗ Branch 3 not taken.
|
2548 | if (t >= LBM_POINTER_TYPE_FIRST && t < LBM_POINTER_TYPE_LAST) { |
258 | // Clear constant bit, it is irrelevant to flattening | ||
259 | 1428 | t = t & ~(LBM_PTR_TO_CONSTANT_BIT); | |
260 | } | ||
261 | |||
262 |
6/9✓ Branch 0 taken 1092 times.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 756 times.
✓ Branch 4 taken 84 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 364 times.
✓ Branch 7 taken 224 times.
✗ Branch 8 not taken.
|
2548 | switch (t) { |
263 | 1092 | case LBM_TYPE_CONS: { | |
264 | 1092 | int s2 = 0; | |
265 | 1092 | int s1 = flatten_value_size_internal(jb,lbm_car(v), depth + 1); | |
266 |
1/2✓ Branch 0 taken 1092 times.
✗ Branch 1 not taken.
|
1092 | if (s1 > 0) { |
267 | 1092 | s2 = flatten_value_size_internal(jb,lbm_cdr(v), depth + 1); | |
268 |
1/2✓ Branch 0 taken 1092 times.
✗ Branch 1 not taken.
|
1092 | if (s2 > 0) { |
269 | 1092 | return (1 + s1 + s2); | |
270 | } | ||
271 | } | ||
272 | ✗ | return 0; // already terminated with error | |
273 | } | ||
274 | 28 | case LBM_TYPE_LISPARRAY: { | |
275 | 28 | int sum = 4 + 1; // sizeof(uint32_t) + 1; | |
276 | 28 | lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(v); | |
277 | 28 | lbm_value *arrdata = (lbm_value*)header->data; | |
278 | 28 | lbm_uint size = header->size / sizeof(lbm_value); | |
279 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 28 times.
|
112 | for (lbm_uint i = 0; i < size; i ++ ) { |
280 | 84 | sum += flatten_value_size_internal(jb, arrdata[i], depth + 1); | |
281 | } | ||
282 | 28 | return sum; | |
283 | } | ||
284 | ✗ | case LBM_TYPE_BYTE: | |
285 | ✗ | return 1 + 1; | |
286 | 756 | case LBM_TYPE_U: /* fall through */ | |
287 | case LBM_TYPE_I: | ||
288 | #ifndef LBM64 | ||
289 | 756 | return 1 + 4; | |
290 | #else | ||
291 | return 1 + 8; | ||
292 | #endif | ||
293 | 84 | case LBM_TYPE_U32: /* fall through */ | |
294 | case LBM_TYPE_I32: | ||
295 | case LBM_TYPE_FLOAT: | ||
296 | 84 | return 1 + 4; | |
297 | ✗ | case LBM_TYPE_U64: /* fall through */ | |
298 | case LBM_TYPE_I64: | ||
299 | case LBM_TYPE_DOUBLE: | ||
300 | ✗ | return 1 + 8; | |
301 | 364 | case LBM_TYPE_SYMBOL: { | |
302 | 364 | int s = f_sym_string_bytes(v); | |
303 |
1/2✓ Branch 0 taken 364 times.
✗ Branch 1 not taken.
|
364 | if (s > 0) return 1 + s; |
304 | ✗ | flatten_error(jb, (int)s); | |
305 | ✗ | } return 0; // already terminated with error | |
306 | 224 | case LBM_TYPE_ARRAY: { | |
307 | // Platform dependent size. | ||
308 | // TODO: Something needs to be done to these inconsistencies. | ||
309 | 224 | lbm_int s = lbm_heap_array_get_size(v); | |
310 |
1/2✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
|
224 | if (s > 0) |
311 | 224 | return 1 + 4 + (int)s; | |
312 | ✗ | flatten_error(jb, (int)s); | |
313 | ✗ | } return 0; // already terminated with error | |
314 | ✗ | default: | |
315 | ✗ | return FLATTEN_VALUE_ERROR_CANNOT_BE_FLATTENED; | |
316 | } | ||
317 | } | ||
318 | |||
319 | 280 | int flatten_value_size(lbm_value v, int depth) { | |
320 | jmp_buf jb; | ||
321 | 280 | int r = setjmp(jb); | |
322 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 280 times.
|
280 | if (r != 0) { |
323 | ✗ | return r; | |
324 | } | ||
325 | 280 | return flatten_value_size_internal(jb, v, depth); | |
326 | } | ||
327 | |||
328 | 2548 | int flatten_value_c(lbm_flat_value_t *fv, lbm_value v) { | |
329 | |||
330 | 2548 | lbm_uint t = lbm_type_of(v); | |
331 |
3/4✓ Branch 0 taken 1428 times.
✓ Branch 1 taken 1120 times.
✓ Branch 2 taken 1428 times.
✗ Branch 3 not taken.
|
2548 | if (t >= LBM_POINTER_TYPE_FIRST && t < LBM_POINTER_TYPE_LAST) { |
332 | // Clear constant bit, it is irrelevant to flattening | ||
333 | 1428 | t = t & ~(LBM_PTR_TO_CONSTANT_BIT); | |
334 | } | ||
335 | |||
336 |
8/14✓ Branch 0 taken 1092 times.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 756 times.
✓ Branch 5 taken 28 times.
✓ Branch 6 taken 28 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 28 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 364 times.
✓ Branch 12 taken 224 times.
✗ Branch 13 not taken.
|
2548 | switch (t) { |
337 | 1092 | case LBM_TYPE_CONS: { | |
338 | 1092 | bool res = true; | |
339 |
2/4✓ Branch 0 taken 1092 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1092 times.
✗ Branch 4 not taken.
|
1092 | res = res && f_cons(fv); |
340 |
1/2✓ Branch 0 taken 1092 times.
✗ Branch 1 not taken.
|
1092 | if (res) { |
341 | 1092 | int fv_r = flatten_value_c(fv, lbm_car(v)); | |
342 |
1/2✓ Branch 0 taken 1092 times.
✗ Branch 1 not taken.
|
1092 | if (fv_r == FLATTEN_VALUE_OK) { |
343 | 1092 | fv_r = flatten_value_c(fv, lbm_cdr(v)); | |
344 | } | ||
345 | 1092 | return fv_r; | |
346 | } | ||
347 | ✗ | }break; | |
348 | 28 | case LBM_TYPE_LISPARRAY: { | |
349 | 28 | lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(v); | |
350 | 28 | lbm_value *arrdata = (lbm_value*)header->data; | |
351 | 28 | lbm_uint size = header->size / sizeof(lbm_value); | |
352 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
|
28 | if (!f_lisp_array(fv, size)) return FLATTEN_VALUE_ERROR_NOT_ENOUGH_MEMORY; |
353 | int fv_r; | ||
354 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 28 times.
|
112 | for (lbm_uint i = 0; i < size; i ++ ) { |
355 | 84 | fv_r = flatten_value_c(fv, arrdata[i]); | |
356 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
|
84 | if (fv_r != FLATTEN_VALUE_OK) { |
357 | ✗ | return fv_r; | |
358 | } | ||
359 | } | ||
360 | 28 | return FLATTEN_VALUE_OK; | |
361 | } break; | ||
362 | ✗ | case LBM_TYPE_BYTE: | |
363 | ✗ | if (f_b(fv, (uint8_t)lbm_dec_as_char(v))) { | |
364 | ✗ | return FLATTEN_VALUE_OK; | |
365 | } | ||
366 | ✗ | break; | |
367 | ✗ | case LBM_TYPE_U: | |
368 | ✗ | if (f_u(fv, lbm_dec_u(v))) { | |
369 | ✗ | return FLATTEN_VALUE_OK; | |
370 | } | ||
371 | ✗ | break; | |
372 | 756 | case LBM_TYPE_I: | |
373 |
1/2✓ Branch 2 taken 756 times.
✗ Branch 3 not taken.
|
756 | if (f_i(fv, lbm_dec_i(v))) { |
374 | 756 | return FLATTEN_VALUE_OK; | |
375 | } | ||
376 | ✗ | break; | |
377 | 28 | case LBM_TYPE_U32: | |
378 |
1/2✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
28 | if (f_u32(fv, lbm_dec_as_u32(v))) { |
379 | 28 | return FLATTEN_VALUE_OK; | |
380 | } | ||
381 | ✗ | break; | |
382 | 28 | case LBM_TYPE_I32: | |
383 |
1/2✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
28 | if (f_i32(fv, lbm_dec_as_i32(v))) { |
384 | 28 | return FLATTEN_VALUE_OK; | |
385 | } | ||
386 | ✗ | break; | |
387 | ✗ | case LBM_TYPE_U64: | |
388 | ✗ | if (f_u64(fv, lbm_dec_as_u64(v))) { | |
389 | ✗ | return FLATTEN_VALUE_OK; | |
390 | } | ||
391 | ✗ | break; | |
392 | ✗ | case LBM_TYPE_I64: | |
393 | ✗ | if (f_i64(fv, lbm_dec_as_i64(v))) { | |
394 | ✗ | return FLATTEN_VALUE_OK; | |
395 | } | ||
396 | ✗ | break; | |
397 | 28 | case LBM_TYPE_FLOAT: | |
398 |
1/2✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
28 | if (f_float(fv, lbm_dec_as_float(v))) { |
399 | 28 | return FLATTEN_VALUE_OK; | |
400 | } | ||
401 | ✗ | break; | |
402 | ✗ | case LBM_TYPE_DOUBLE: | |
403 | ✗ | if (f_double(fv, lbm_dec_as_double(v))) { | |
404 | ✗ | return FLATTEN_VALUE_OK; | |
405 | } | ||
406 | ✗ | break; | |
407 | 364 | case LBM_TYPE_SYMBOL: { | |
408 | 364 | char *sym_str = (char*)lbm_get_name_by_symbol(lbm_dec_sym(v)); | |
409 |
1/2✓ Branch 1 taken 364 times.
✗ Branch 2 not taken.
|
364 | if (f_sym_string(fv, sym_str)) { |
410 | 364 | return FLATTEN_VALUE_OK; | |
411 | } | ||
412 | ✗ | } break; | |
413 | 224 | case LBM_TYPE_ARRAY: { | |
414 | 224 | lbm_int s = lbm_heap_array_get_size(v); | |
415 | 224 | const uint8_t *d = lbm_heap_array_get_data_ro(v); | |
416 |
2/4✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 224 times.
✗ Branch 3 not taken.
|
224 | if (s > 0 && d != NULL) { |
417 |
1/2✓ Branch 1 taken 224 times.
✗ Branch 2 not taken.
|
224 | if (f_lbm_array(fv, (uint32_t)s, (uint8_t*)d)) { |
418 | 224 | return FLATTEN_VALUE_OK; | |
419 | } | ||
420 | } else { | ||
421 | ✗ | return FLATTEN_VALUE_ERROR_ARRAY; | |
422 | } | ||
423 | ✗ | }break; | |
424 | ✗ | default: | |
425 | ✗ | return FLATTEN_VALUE_ERROR_CANNOT_BE_FLATTENED; | |
426 | } | ||
427 | ✗ | return FLATTEN_VALUE_ERROR_BUFFER_TOO_SMALL; | |
428 | } | ||
429 | |||
430 | ✗ | lbm_value handle_flatten_error(int err_val) { | |
431 | ✗ | switch (err_val) { | |
432 | ✗ | case FLATTEN_VALUE_ERROR_CANNOT_BE_FLATTENED: | |
433 | ✗ | return ENC_SYM_EERROR; | |
434 | ✗ | case FLATTEN_VALUE_ERROR_BUFFER_TOO_SMALL: /* fall through */ | |
435 | case FLATTEN_VALUE_ERROR_FATAL: | ||
436 | ✗ | return ENC_SYM_FATAL_ERROR; | |
437 | ✗ | case FLATTEN_VALUE_ERROR_CIRCULAR: /* fall through */ | |
438 | case FLATTEN_VALUE_ERROR_MAXIMUM_DEPTH: | ||
439 | ✗ | return ENC_SYM_EERROR; | |
440 | ✗ | case FLATTEN_VALUE_ERROR_NOT_ENOUGH_MEMORY: | |
441 | ✗ | return ENC_SYM_MERROR; | |
442 | } | ||
443 | ✗ | return ENC_SYM_NIL; | |
444 | } | ||
445 | |||
446 | 280 | lbm_value flatten_value(lbm_value v) { | |
447 | |||
448 | 280 | lbm_value array_cell = lbm_heap_allocate_cell(LBM_TYPE_CONS, ENC_SYM_NIL, ENC_SYM_ARRAY_TYPE); | |
449 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 280 times.
|
280 | if (lbm_type_of(array_cell) == LBM_TYPE_SYMBOL) { |
450 | ✗ | return ENC_SYM_MERROR; | |
451 | } | ||
452 | |||
453 | lbm_flat_value_t fv; | ||
454 | |||
455 | 280 | lbm_array_header_t *array = NULL; | |
456 | 280 | int required_mem = flatten_value_size(v, 0); | |
457 |
1/2✓ Branch 0 taken 280 times.
✗ Branch 1 not taken.
|
280 | if (required_mem > 0) { |
458 | 280 | array = (lbm_array_header_t *)lbm_malloc(sizeof(lbm_array_header_t)); | |
459 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 280 times.
|
280 | if (array == NULL) { |
460 | ✗ | lbm_set_car_and_cdr(array_cell, ENC_SYM_NIL, ENC_SYM_NIL); | |
461 | ✗ | return ENC_SYM_MERROR; | |
462 | } | ||
463 | |||
464 | 280 | bool r = lbm_start_flatten(&fv, (lbm_uint)required_mem); | |
465 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 280 times.
|
280 | if (!r) { |
466 | ✗ | lbm_free(array); | |
467 | ✗ | lbm_set_car_and_cdr(array_cell, ENC_SYM_NIL, ENC_SYM_NIL); | |
468 | ✗ | return ENC_SYM_MERROR; | |
469 | } | ||
470 | |||
471 |
1/2✓ Branch 1 taken 280 times.
✗ Branch 2 not taken.
|
280 | if (flatten_value_c(&fv, v) == FLATTEN_VALUE_OK) { |
472 | // it would be wasteful to run finish_flatten here. | ||
473 | 280 | r = true; | |
474 | } else { | ||
475 | ✗ | r = false; | |
476 | } | ||
477 | |||
478 |
1/2✓ Branch 0 taken 280 times.
✗ Branch 1 not taken.
|
280 | if (r) { |
479 | // lift flat_value | ||
480 | 280 | array->data = (lbm_uint*)fv.buf; | |
481 | 280 | array->size = fv.buf_size; | |
482 | 280 | lbm_set_car(array_cell, (lbm_uint)array); | |
483 | 280 | array_cell = lbm_set_ptr_type(array_cell, LBM_TYPE_ARRAY); | |
484 | 280 | return array_cell; | |
485 | } | ||
486 | } | ||
487 | ✗ | lbm_set_car_and_cdr(array_cell, ENC_SYM_NIL, ENC_SYM_NIL); | |
488 | ✗ | return handle_flatten_error(required_mem); | |
489 | } | ||
490 | |||
491 | // ------------------------------------------------------------ | ||
492 | // Unflattening | ||
493 | ✗ | static bool extract_byte(lbm_flat_value_t *v, uint8_t *r) { | |
494 | ✗ | if (v->buf_size >= v->buf_pos + 1) { | |
495 | ✗ | *r = v->buf[v->buf_pos++]; | |
496 | ✗ | return true; | |
497 | } | ||
498 | ✗ | return false; | |
499 | } | ||
500 | |||
501 | 16938 | static bool extract_word(lbm_flat_value_t *v, uint32_t *r) { | |
502 |
1/2✓ Branch 0 taken 16938 times.
✗ Branch 1 not taken.
|
16938 | if (v->buf_size >= v->buf_pos + 4) { |
503 | 16938 | uint32_t tmp = 0; | |
504 | 16938 | tmp |= (lbm_value)v->buf[v->buf_pos++]; | |
505 | 16938 | tmp = tmp << 8 | (uint32_t)v->buf[v->buf_pos++]; | |
506 | 16938 | tmp = tmp << 8 | (uint32_t)v->buf[v->buf_pos++]; | |
507 | 16938 | tmp = tmp << 8 | (uint32_t)v->buf[v->buf_pos++]; | |
508 | 16938 | *r = tmp; | |
509 | 16938 | return true; | |
510 | } | ||
511 | ✗ | return false; | |
512 | } | ||
513 | |||
514 | ✗ | static bool extract_dword(lbm_flat_value_t *v, uint64_t *r) { | |
515 | ✗ | if (v->buf_size >= v->buf_pos + 8) { | |
516 | ✗ | uint64_t tmp = 0; | |
517 | ✗ | tmp |= (lbm_value)v->buf[v->buf_pos++]; | |
518 | ✗ | tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; | |
519 | ✗ | tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; | |
520 | ✗ | tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; | |
521 | ✗ | tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; | |
522 | ✗ | tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; | |
523 | ✗ | tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; | |
524 | ✗ | tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; | |
525 | ✗ | *r = tmp; | |
526 | ✗ | return true; | |
527 | } | ||
528 | ✗ | return false; | |
529 | } | ||
530 | |||
531 | /* Recursive and potentially stack hungry for large flat values */ | ||
532 | 26267 | static int lbm_unflatten_value_internal(lbm_flat_value_t *v, lbm_value *res) { | |
533 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26267 times.
|
26267 | if (v->buf_size == v->buf_pos) return UNFLATTEN_MALFORMED; |
534 | |||
535 | 26267 | uint8_t curr = v->buf[v->buf_pos++]; | |
536 | |||
537 |
9/17✓ Branch 0 taken 8937 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 6334 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 756 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 9568 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 28 times.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 196 times.
✓ Branch 15 taken 392 times.
✗ Branch 16 not taken.
|
26267 | switch(curr) { |
538 | 8937 | case S_CONS: { | |
539 | lbm_value a; | ||
540 | lbm_value b; | ||
541 | 8937 | int r = lbm_unflatten_value_internal(v, &a); | |
542 |
1/2✓ Branch 0 taken 8937 times.
✗ Branch 1 not taken.
|
8937 | if (r == UNFLATTEN_OK) { |
543 | 8937 | r = lbm_unflatten_value_internal(v, &b); | |
544 |
1/2✓ Branch 0 taken 8937 times.
✗ Branch 1 not taken.
|
8937 | if (r == UNFLATTEN_OK) { |
545 | lbm_value c; | ||
546 | 8937 | c = lbm_cons(a,b); | |
547 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8937 times.
|
8937 | if (lbm_is_symbol_merror(c)) return UNFLATTEN_GC_RETRY; |
548 | 8937 | *res = c; | |
549 | 8937 | r = UNFLATTEN_OK; | |
550 | } | ||
551 | } | ||
552 | 8937 | return r; | |
553 | } | ||
554 | 28 | case S_LBM_LISP_ARRAY: { | |
555 | uint32_t size; | ||
556 | 28 | bool b = extract_word(v, &size); | |
557 | 28 | int r = UNFLATTEN_MALFORMED; | |
558 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | if (b) { |
559 | lbm_value array; | ||
560 | 28 | lbm_heap_allocate_lisp_array(&array, size); | |
561 | 28 | lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(array); | |
562 | 28 | lbm_value *arrdata = (lbm_value*)header->data; | |
563 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
|
28 | if (lbm_is_symbol_merror(array)) return UNFLATTEN_GC_RETRY; |
564 | lbm_value a; | ||
565 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 28 times.
|
112 | for (uint32_t i = 0; i < size; i ++) { |
566 | 84 | r = lbm_unflatten_value_internal(v, &a); | |
567 |
1/2✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
|
84 | if (r == UNFLATTEN_OK) { |
568 | 84 | arrdata[i] = a; | |
569 | } else { | ||
570 | ✗ | break; | |
571 | } | ||
572 | } | ||
573 | 28 | *res = array; | |
574 | } | ||
575 | 28 | return r; | |
576 | } | ||
577 | 6334 | case S_SYM_VALUE: { | |
578 | lbm_uint tmp; | ||
579 | bool b; | ||
580 | #ifndef LBM64 | ||
581 | 6334 | b = extract_word(v, &tmp); | |
582 | #else | ||
583 | b = extract_dword(v, &tmp); | ||
584 | #endif | ||
585 |
1/2✓ Branch 0 taken 6334 times.
✗ Branch 1 not taken.
|
6334 | if (b) { |
586 | 6334 | *res = lbm_enc_sym(tmp); | |
587 | 6334 | return UNFLATTEN_OK; | |
588 | } | ||
589 | ✗ | return UNFLATTEN_MALFORMED; | |
590 | } | ||
591 | ✗ | case S_BYTE_VALUE: { | |
592 | uint8_t tmp; | ||
593 | ✗ | bool b = extract_byte(v, &tmp); | |
594 | ✗ | if (b) { | |
595 | ✗ | *res = lbm_enc_char((uint8_t)tmp); | |
596 | ✗ | return UNFLATTEN_OK; | |
597 | } | ||
598 | ✗ | return UNFLATTEN_MALFORMED; | |
599 | } | ||
600 | 756 | case S_I28_VALUE: { | |
601 | uint32_t tmp; | ||
602 | bool b; | ||
603 | 756 | b = extract_word(v, &tmp); | |
604 |
1/2✓ Branch 0 taken 756 times.
✗ Branch 1 not taken.
|
756 | if (b) { |
605 | 756 | *res = lbm_enc_i((int32_t)tmp); | |
606 | 756 | return UNFLATTEN_OK; | |
607 | } | ||
608 | ✗ | return UNFLATTEN_MALFORMED; | |
609 | } | ||
610 | ✗ | case S_U28_VALUE: { | |
611 | uint32_t tmp; | ||
612 | bool b; | ||
613 | ✗ | b = extract_word(v, &tmp); | |
614 | ✗ | if (b) { | |
615 | ✗ | *res = lbm_enc_u((uint32_t)tmp); | |
616 | ✗ | return UNFLATTEN_OK; | |
617 | } | ||
618 | ✗ | return UNFLATTEN_MALFORMED; | |
619 | } | ||
620 | ✗ | case S_I56_VALUE: { | |
621 | uint64_t tmp; | ||
622 | bool b; | ||
623 | ✗ | b = extract_dword(v, &tmp); | |
624 | ✗ | if (b) { | |
625 | #ifndef LBM64 | ||
626 | ✗ | *res = lbm_enc_i64((int64_t)tmp); | |
627 | #else | ||
628 | *res = lbm_enc_i((int64_t)tmp); | ||
629 | #endif | ||
630 | ✗ | return UNFLATTEN_OK; | |
631 | } | ||
632 | ✗ | return UNFLATTEN_MALFORMED; | |
633 | } | ||
634 | ✗ | case S_U56_VALUE: { | |
635 | uint64_t tmp; | ||
636 | bool b; | ||
637 | ✗ | b = extract_dword(v, &tmp); | |
638 | ✗ | if (b) { | |
639 | #ifndef LBM64 | ||
640 | ✗ | *res = lbm_enc_u64(tmp); | |
641 | #else | ||
642 | *res = lbm_enc_u(tmp); | ||
643 | #endif | ||
644 | ✗ | return UNFLATTEN_OK; | |
645 | } | ||
646 | ✗ | return UNFLATTEN_MALFORMED; | |
647 | } | ||
648 | 9568 | case S_FLOAT_VALUE: { | |
649 | uint32_t tmp; | ||
650 | bool b; | ||
651 | 9568 | b = extract_word(v, &tmp); | |
652 |
1/2✓ Branch 0 taken 9568 times.
✗ Branch 1 not taken.
|
9568 | if (b) { |
653 | lbm_float f; | ||
654 | 9568 | memcpy(&f, &tmp, sizeof(lbm_float)); | |
655 | 9568 | lbm_value im = lbm_enc_float(f); | |
656 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9568 times.
|
9568 | if (lbm_is_symbol_merror(im)) { |
657 | ✗ | return UNFLATTEN_GC_RETRY; | |
658 | } | ||
659 | 9568 | *res = im; | |
660 | 9568 | return UNFLATTEN_OK; | |
661 | } | ||
662 | ✗ | return UNFLATTEN_MALFORMED; | |
663 | } | ||
664 | ✗ | case S_DOUBLE_VALUE: { | |
665 | uint64_t tmp; | ||
666 | bool b; | ||
667 | ✗ | b = extract_dword(v, &tmp); | |
668 | ✗ | if (b) { | |
669 | double f; | ||
670 | ✗ | memcpy(&f, &tmp, sizeof(uint64_t)); | |
671 | ✗ | lbm_value im = lbm_enc_double(f); | |
672 | ✗ | if (lbm_is_symbol_merror(im)) { | |
673 | ✗ | return UNFLATTEN_GC_RETRY; | |
674 | } | ||
675 | ✗ | *res = im; | |
676 | ✗ | return UNFLATTEN_OK; | |
677 | } | ||
678 | ✗ | return UNFLATTEN_MALFORMED; | |
679 | } | ||
680 | 28 | case S_I32_VALUE: { | |
681 | uint32_t tmp; | ||
682 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | if (extract_word(v, &tmp)) { |
683 | 28 | lbm_value im = lbm_enc_i32((int32_t)tmp); | |
684 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
|
28 | if (lbm_is_symbol_merror(im)) { |
685 | ✗ | return UNFLATTEN_GC_RETRY; | |
686 | } | ||
687 | 28 | *res = im; | |
688 | 28 | return UNFLATTEN_OK; | |
689 | } | ||
690 | ✗ | return UNFLATTEN_MALFORMED; | |
691 | } | ||
692 | 28 | case S_U32_VALUE: { | |
693 | uint32_t tmp; | ||
694 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | if (extract_word(v, &tmp)) { |
695 | 28 | lbm_value im = lbm_enc_u32(tmp); | |
696 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
|
28 | if (lbm_is_symbol_merror(im)) { |
697 | ✗ | return UNFLATTEN_GC_RETRY; | |
698 | } | ||
699 | 28 | *res = im; | |
700 | 28 | return UNFLATTEN_OK; | |
701 | } | ||
702 | ✗ | return UNFLATTEN_MALFORMED; | |
703 | } | ||
704 | ✗ | case S_I64_VALUE: { | |
705 | ✗ | uint64_t tmp = 0; | |
706 | ✗ | if (extract_dword(v, &tmp)) { | |
707 | ✗ | lbm_value im = lbm_enc_i64((int64_t)tmp); | |
708 | ✗ | if (lbm_is_symbol_merror(im)) { | |
709 | ✗ | return UNFLATTEN_GC_RETRY; | |
710 | } | ||
711 | ✗ | *res = im; | |
712 | ✗ | return UNFLATTEN_OK; | |
713 | } | ||
714 | ✗ | return UNFLATTEN_MALFORMED; | |
715 | } | ||
716 | ✗ | case S_U64_VALUE: { | |
717 | ✗ | uint64_t tmp = 0; | |
718 | ✗ | if (extract_dword(v, &tmp)) { | |
719 | ✗ | lbm_value im = lbm_enc_u64(tmp); | |
720 | ✗ | if (lbm_is_symbol_merror(im)) { | |
721 | ✗ | return UNFLATTEN_GC_RETRY; | |
722 | } | ||
723 | ✗ | *res = im; | |
724 | ✗ | return UNFLATTEN_OK; | |
725 | } | ||
726 | ✗ | return UNFLATTEN_MALFORMED; | |
727 | } | ||
728 | 196 | case S_LBM_ARRAY: { | |
729 | uint32_t num_elt; | ||
730 |
1/2✓ Branch 1 taken 196 times.
✗ Branch 2 not taken.
|
196 | if (extract_word(v, &num_elt)) { |
731 |
1/2✓ Branch 1 taken 196 times.
✗ Branch 2 not taken.
|
196 | if (lbm_heap_allocate_array(res, num_elt)) { |
732 | 196 | lbm_array_header_t *arr = (lbm_array_header_t*)lbm_car(*res); | |
733 | 196 | lbm_uint num_bytes = num_elt; | |
734 | 196 | memcpy(arr->data, v->buf + v->buf_pos, num_bytes); | |
735 | 196 | v->buf_pos += num_bytes; | |
736 | } else { | ||
737 | ✗ | return UNFLATTEN_GC_RETRY; | |
738 | } | ||
739 | 196 | return UNFLATTEN_OK; | |
740 | } | ||
741 | ✗ | return UNFLATTEN_MALFORMED; | |
742 | } | ||
743 | 392 | case S_SYM_STRING: { | |
744 | lbm_uint sym_id; | ||
745 | 392 | int r = lbm_get_symbol_by_name((char *)(v->buf + v->buf_pos), &sym_id); | |
746 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 392 times.
|
392 | if (!r) { |
747 | ✗ | r = lbm_add_symbol_base((char *)(v->buf + v->buf_pos), &sym_id,false); //ram | |
748 | } | ||
749 |
1/2✓ Branch 0 taken 392 times.
✗ Branch 1 not taken.
|
392 | if (r) { |
750 | 392 | lbm_uint num_bytes = strlen((char*)(v->buf + v->buf_pos)) + 1; | |
751 | 392 | v->buf_pos += num_bytes; | |
752 | 392 | *res = lbm_enc_sym(sym_id); | |
753 | 392 | return UNFLATTEN_OK; | |
754 | } | ||
755 | ✗ | return UNFLATTEN_MALFORMED; | |
756 | } | ||
757 | ✗ | default: | |
758 | ✗ | return UNFLATTEN_MALFORMED; | |
759 | } | ||
760 | } | ||
761 | |||
762 | 8309 | bool lbm_unflatten_value(lbm_flat_value_t *v, lbm_value *res) { | |
763 | 8309 | bool b = false; | |
764 | 8309 | int r = lbm_unflatten_value_internal(v,res); | |
765 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8309 times.
|
8309 | if (r == UNFLATTEN_GC_RETRY) { |
766 | ✗ | lbm_perform_gc(); | |
767 | ✗ | v->buf_pos = 0; | |
768 | ✗ | r = lbm_unflatten_value_internal(v,res); | |
769 | } | ||
770 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8309 times.
|
8309 | if (r == UNFLATTEN_MALFORMED) { |
771 | ✗ | *res = ENC_SYM_EERROR; | |
772 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8309 times.
|
8309 | } else if (r == UNFLATTEN_GC_RETRY) { |
773 | ✗ | *res = ENC_SYM_MERROR; | |
774 | } else { | ||
775 | 8309 | b = true; | |
776 | } | ||
777 | // Do not free the flat value buffer here. | ||
778 | // there are 2 cases: | ||
779 | // 1: unflatten was called from lisp code -> GC removes the buffer. | ||
780 | // 2: unflatten called from event processing -> event processor frees buffer. | ||
781 | 8309 | return b; | |
782 | } | ||
783 |