Skip to content

Commit

Permalink
WIP: write atom to string
Browse files Browse the repository at this point in the history
Signed-off-by: Davide Bettio <davide@uninstall.it>
  • Loading branch information
bettio committed Nov 3, 2023
1 parent cc2e352 commit d8044b6
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 14 deletions.
52 changes: 43 additions & 9 deletions src/libAtomVM/atom_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,32 +197,41 @@ long atom_table_get_index(struct AtomTable *table, AtomString string)
return result;
}

// TODO: this function needs to be optimized
AtomString atom_table_get_atom_string(struct AtomTable *table, long index)
static struct HNode *get_node_using_index(struct AtomTable *table, long index)
{
SMP_RDLOCK(table);

if (UNLIKELY(index >= table->count)) {
SMP_UNLOCK(table);
return NULL;
}

struct HNodeGroup *node_group = table->first_node_group;
while (node_group) {
long first_index = node_group->first_index;
if (first_index + node_group->len > index) {
AtomString found_key = node_group->nodes[index - first_index].key;
SMP_UNLOCK(table);
return found_key;
return &node_group->nodes[index - first_index];
}

node_group = node_group->next;
}

SMP_UNLOCK(table);
return NULL;
}

// TODO: this function needs to be optimized
AtomString atom_table_get_atom_string(struct AtomTable *table, long index)
{
SMP_RDLOCK(table);

struct HNode *node = get_node_using_index(table, index);
if (IS_NULL_PTR(node)) {
return NULL;
}

AtomString found_key = node->key;

SMP_UNLOCK(table);
return found_key;
}

int atom_table_cmp_using_atom_index(struct AtomTable *table, int t_atom_index, int other_atom_index)
{
AtomString t_atom_string = atom_table_get_atom_string(table, t_atom_index);
Expand Down Expand Up @@ -250,6 +259,31 @@ int atom_table_cmp_using_atom_index(struct AtomTable *table, int t_atom_index, i
return memcmp_result;
}

atom_ref_t atom_table_get_atom_ptr_and_len(struct AtomTable *table, long index, size_t *out_len)
{
SMP_RDLOCK(table);

struct HNode *node = get_node_using_index(table, index);
if (IS_NULL_PTR(node)) {
return NULL;
}

*out_len = atom_string_len(node->key);

SMP_UNLOCK(table);
return node;
}

void atom_table_write_cstring(struct AtomTable *table, atom_ref_t atom, int buf_len, char *outbuf)
{
SMP_RDLOCK(table);

struct HNode *node = (struct HNode *) atom;
atom_string_to_c(node->key, outbuf, buf_len);

SMP_UNLOCK(table);
}

static inline void init_node(struct HNode *node, AtomString atom, long index)
{
node->key = atom;
Expand Down
4 changes: 4 additions & 0 deletions src/libAtomVM/atom_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ enum AtomTableCopyOpt
AtomTableAlreadyExisting = 2
};

typedef const void *atom_ref_t;

struct AtomTable *atom_table_new();
void atom_table_destroy(struct AtomTable *table);

Expand All @@ -49,5 +51,7 @@ long atom_table_ensure_atoms(

int atom_table_cmp_using_atom_index(
struct AtomTable *table, int t_atom_index, int other_atom_index);
atom_ref_t atom_table_get_atom_ptr_and_len(struct AtomTable *table, long index, size_t *out_len);
void atom_table_write_cstring(struct AtomTable *table, atom_ref_t atom, int buf_len, char *outbuf);

#endif
12 changes: 7 additions & 5 deletions src/libAtomVM/nifs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2024,17 +2024,19 @@ static term nif_erlang_atom_to_binary_2(Context *ctx, int argc, term argv[])
RAISE_ERROR(BADARG_ATOM);
}

int atom_index = term_to_atom_index(atom_term);
AtomString atom_string = atom_table_get_atom_string(ctx->global->atom_table, atom_index);
GlobalContext *glb = ctx->global;

int atom_len = atom_string_len(atom_string);
int atom_index = term_to_atom_index(atom_term);
size_t atom_len;
atom_ref_t atom_ref = atom_table_get_atom_ptr_and_len(glb->atom_table, atom_index, &atom_len);

if (UNLIKELY(memory_ensure_free_opt(ctx, term_binary_heap_size(atom_len), MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
}

const char *atom_data = (const char *) atom_string_data(atom_string);
return term_from_literal_binary(atom_data, atom_len, &ctx->heap, ctx->global);
term binary = term_create_uninitialized_binary(atom_len, &ctx->heap, glb);
atom_table_write_cstring(glb->atom_table, atom_ref, atom_len, (char *) term_binary_data(binary));
return binary;
}

static term nif_erlang_atom_to_list_1(Context *ctx, int argc, term argv[])
Expand Down

0 comments on commit d8044b6

Please sign in to comment.