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