Skip to content

Commit a15c922

Browse files
committed
Add support for interop_iolist_fold
Signed-off-by: Fred Dushin <[email protected]>
1 parent e54a2e1 commit a15c922

File tree

2 files changed

+41
-55
lines changed

2 files changed

+41
-55
lines changed

src/libAtomVM/interop.c

Lines changed: 38 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -176,19 +176,16 @@ term interop_proplist_get_value_default(term list, term key, term default_value)
176176
return default_value;
177177
}
178178

179-
InteropFunctionResult interop_iolist_size(term t, size_t *size)
179+
inline InteropFunctionResult interop_iolist_fold(term t, interop_iolist_fold_fun fold_fun, void *accum)
180180
{
181181
if (term_is_binary(t)) {
182-
*size = term_binary_size(t);
183-
return InteropOk;
182+
return fold_fun(t, accum);
184183
}
185184

186185
if (UNLIKELY(!term_is_list(t))) {
187186
return InteropBadArg;
188187
}
189188

190-
unsigned long acc = 0;
191-
192189
struct TempStack temp_stack;
193190
if (UNLIKELY(temp_stack_init(&temp_stack) != TempStackOk)) {
194191
return InteropMemoryAllocFail;
@@ -200,9 +197,14 @@ InteropFunctionResult interop_iolist_size(term t, size_t *size)
200197
}
201198

202199
while (!temp_stack_is_empty(&temp_stack)) {
203-
if (term_is_integer(t)) {
204-
acc++;
205-
t = temp_stack_pop(&temp_stack);
200+
if (term_is_integer(t) || term_is_binary(t)) {
201+
InteropFunctionResult result = fold_fun(t, accum);
202+
if (UNLIKELY(result != InteropOk)) {
203+
temp_stack_destroy(&temp_stack);
204+
return result;
205+
} else {
206+
t = temp_stack_pop(&temp_stack);
207+
}
206208

207209
} else if (term_is_nil(t)) {
208210
t = temp_stack_pop(&temp_stack);
@@ -214,10 +216,6 @@ InteropFunctionResult interop_iolist_size(term t, size_t *size)
214216
}
215217
t = term_get_list_head(t);
216218

217-
} else if (term_is_binary(t)) {
218-
acc += term_binary_size(t);
219-
t = temp_stack_pop(&temp_stack);
220-
221219
} else {
222220
temp_stack_destroy(&temp_stack);
223221
return InteropBadArg;
@@ -226,60 +224,45 @@ InteropFunctionResult interop_iolist_size(term t, size_t *size)
226224

227225
temp_stack_destroy(&temp_stack);
228226

229-
*size = acc;
230227
return InteropOk;
231228
}
232229

233-
InteropFunctionResult interop_write_iolist(term t, char *p)
230+
static inline InteropFunctionResult size_fold_fun(term t, void *accum)
234231
{
235-
if (term_is_binary(t)) {
236-
int len = term_binary_size(t);
237-
memcpy(p, term_binary_data(t), len);
238-
return InteropOk;
239-
}
240-
241-
struct TempStack temp_stack;
242-
if (UNLIKELY(temp_stack_init(&temp_stack) != TempStackOk)) {
243-
return InteropMemoryAllocFail;
244-
}
245-
246-
if (UNLIKELY(temp_stack_push(&temp_stack, t) != TempStackOk)) {
247-
temp_stack_destroy(&temp_stack);
248-
return InteropMemoryAllocFail;
232+
size_t *size = (size_t *) accum;
233+
if (term_is_integer(t)) {
234+
*size += 1;
235+
} else if (term_is_binary(t)) {
236+
*size += term_binary_size(t);
249237
}
238+
return InteropOk;
239+
}
250240

251-
while (!temp_stack_is_empty(&temp_stack)) {
252-
if (term_is_integer(t)) {
253-
*p = term_to_int(t);
254-
p++;
255-
t = temp_stack_pop(&temp_stack);
256-
257-
} else if (term_is_nil(t)) {
258-
t = temp_stack_pop(&temp_stack);
259-
260-
} else if (term_is_nonempty_list(t)) {
261-
if (UNLIKELY(temp_stack_push(&temp_stack, term_get_list_tail(t)) != TempStackOk)) {
262-
temp_stack_destroy(&temp_stack);
263-
return InteropMemoryAllocFail;
264-
}
265-
t = term_get_list_head(t);
266-
267-
} else if (term_is_binary(t)) {
268-
int len = term_binary_size(t);
269-
memcpy(p, term_binary_data(t), len);
270-
p += len;
271-
t = temp_stack_pop(&temp_stack);
241+
InteropFunctionResult interop_iolist_size(term t, size_t *size)
242+
{
243+
*size = 0;
244+
return interop_iolist_fold(t, size_fold_fun, size);
245+
}
272246

273-
} else {
274-
temp_stack_destroy(&temp_stack);
275-
return InteropBadArg;
276-
}
247+
static inline InteropFunctionResult write_string_fold_fun(term t, void *accum)
248+
{
249+
char **p = (char **) accum;
250+
if (term_is_integer(t)) {
251+
**p = term_to_int(t);
252+
(*p)++;
253+
} else if (term_is_binary(t)) {
254+
int len = term_binary_size(t);
255+
memcpy(*p, term_binary_data(t), len);
256+
*p += len;
277257
}
278-
279-
temp_stack_destroy(&temp_stack);
280258
return InteropOk;
281259
}
282260

261+
InteropFunctionResult interop_write_iolist(term t, char *p)
262+
{
263+
return interop_iolist_fold(t, write_string_fold_fun, (void *) &p);
264+
}
265+
283266
term interop_map_get_value(GlobalContext *glb, term map, term key)
284267
{
285268
return interop_map_get_value_default(glb, map, key, term_nil());

src/libAtomVM/interop.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ typedef struct
5353
int i_val;
5454
} AtomStringIntPair;
5555

56+
typedef InteropFunctionResult (*interop_iolist_fold_fun)(term t, void *accum);
57+
5658
char *interop_term_to_string(term t, int *ok);
5759
char *interop_binary_to_string(term binary);
5860
char *interop_list_to_string(term list, int *ok);
@@ -65,6 +67,7 @@ term interop_map_get_value_default(GlobalContext *glb, term map, term key, term
6567

6668
NO_DISCARD InteropFunctionResult interop_iolist_size(term t, size_t *size);
6769
NO_DISCARD InteropFunctionResult interop_write_iolist(term t, char *p);
70+
NO_DISCARD InteropFunctionResult interop_iolist_fold(term t, interop_iolist_fold_fun fold_fun, void *accum);
6871

6972
/**
7073
* @brief Finds on a table the first matching atom string.

0 commit comments

Comments
 (0)