Skip to content

Commit

Permalink
Added interop_iolist_fold
Browse files Browse the repository at this point in the history
Signed-off-by: Fred Dushin <[email protected]>
  • Loading branch information
fadushin committed Jul 18, 2023
1 parent 299fa6a commit 94ed2f2
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 53 deletions.
98 changes: 45 additions & 53 deletions src/libAtomVM/interop.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,19 +176,33 @@ term interop_proplist_get_value_default(term list, term key, term default_value)
return default_value;
}

static InteropFunctionResult size_fold_fun(term t, void *accum)
{
size_t *size = (size_t *) accum;
if (term_is_integer(t)) {
*size += 1;
} else if (term_is_binary(t)) {
*size += term_binary_size(t);
}
return InteropOk;
}

InteropFunctionResult interop_iolist_size(term t, size_t *size)
{
*size = 0;
return interop_iolist_fold(t, size_fold_fun, (void *) size);
}

InteropFunctionResult interop_iolist_fold(term t, interop_iolist_fold_fun fold_fun, void *accum)
{
if (term_is_binary(t)) {
*size = term_binary_size(t);
return InteropOk;
return fold_fun(t, accum);
}

if (UNLIKELY(!term_is_list(t))) {
return InteropBadArg;
}

unsigned long acc = 0;

struct TempStack temp_stack;
if (UNLIKELY(temp_stack_init(&temp_stack) != TempStackOk)) {
return InteropMemoryAllocFail;
Expand All @@ -201,8 +215,13 @@ InteropFunctionResult interop_iolist_size(term t, size_t *size)

while (!temp_stack_is_empty(&temp_stack)) {
if (term_is_integer(t)) {
acc++;
t = temp_stack_pop(&temp_stack);
InteropFunctionResult result = fold_fun(t, accum);
if (UNLIKELY(result != InteropOk)) {
temp_stack_destroy(&temp_stack);
return result;
} else {
t = temp_stack_pop(&temp_stack);
}

} else if (term_is_nil(t)) {
t = temp_stack_pop(&temp_stack);
Expand All @@ -215,8 +234,13 @@ InteropFunctionResult interop_iolist_size(term t, size_t *size)
t = term_get_list_head(t);

} else if (term_is_binary(t)) {
acc += term_binary_size(t);
t = temp_stack_pop(&temp_stack);
InteropFunctionResult result = fold_fun(t, accum);
if (UNLIKELY(result != InteropOk)) {
temp_stack_destroy(&temp_stack);
return result;
} else {
t = temp_stack_pop(&temp_stack);
}

} else {
temp_stack_destroy(&temp_stack);
Expand All @@ -226,60 +250,28 @@ InteropFunctionResult interop_iolist_size(term t, size_t *size)

temp_stack_destroy(&temp_stack);

*size = acc;
return InteropOk;
}

InteropFunctionResult interop_write_iolist(term t, char *p)
static InteropFunctionResult write_string_fold_fun(term t, void *accum)
{
if (term_is_binary(t)) {
char **p = (char **) accum;
if (term_is_integer(t)) {
**p = term_to_int(t);
(*p)++;
} else if (term_is_binary(t)) {
int len = term_binary_size(t);
memcpy(p, term_binary_data(t), len);
return InteropOk;
}

struct TempStack temp_stack;
if (UNLIKELY(temp_stack_init(&temp_stack) != TempStackOk)) {
return InteropMemoryAllocFail;
}

if (UNLIKELY(temp_stack_push(&temp_stack, t) != TempStackOk)) {
temp_stack_destroy(&temp_stack);
return InteropMemoryAllocFail;
memcpy(*p, term_binary_data(t), len);
*p += len;
}

while (!temp_stack_is_empty(&temp_stack)) {
if (term_is_integer(t)) {
*p = term_to_int(t);
p++;
t = temp_stack_pop(&temp_stack);

} else if (term_is_nil(t)) {
t = temp_stack_pop(&temp_stack);

} else if (term_is_nonempty_list(t)) {
if (UNLIKELY(temp_stack_push(&temp_stack, term_get_list_tail(t)) != TempStackOk)) {
temp_stack_destroy(&temp_stack);
return InteropMemoryAllocFail;
}
t = term_get_list_head(t);

} else if (term_is_binary(t)) {
int len = term_binary_size(t);
memcpy(p, term_binary_data(t), len);
p += len;
t = temp_stack_pop(&temp_stack);

} else {
temp_stack_destroy(&temp_stack);
return InteropBadArg;
}
}

temp_stack_destroy(&temp_stack);
return InteropOk;
}

InteropFunctionResult interop_write_iolist(term t, char *p)
{
return interop_iolist_fold(t, write_string_fold_fun, (void *) &p);
}

term interop_map_get_value(GlobalContext *glb, term map, term key)
{
return interop_map_get_value_default(glb, map, key, term_nil());
Expand Down
3 changes: 3 additions & 0 deletions src/libAtomVM/interop.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ typedef struct
int i_val;
} AtomStringIntPair;

typedef InteropFunctionResult (*interop_iolist_fold_fun)(term t, void *accum);

char *interop_term_to_string(term t, int *ok);
char *interop_binary_to_string(term binary);
char *interop_list_to_string(term list, int *ok);
Expand All @@ -65,6 +67,7 @@ term interop_map_get_value_default(GlobalContext *glb, term map, term key, term

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

/**
* @brief Finds on a table the first matching atom string.
Expand Down

0 comments on commit 94ed2f2

Please sign in to comment.