From 1bd56e2b5141a3afdca4e854e9b667807bf4e2f3 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 17 Dec 2015 14:14:54 +0100 Subject: erts: Add enif_term_to_binary and enif_binary_to_term --- erts/emulator/beam/erl_nif.c | 70 ++++++++++++++++++++++++++++++++++ erts/emulator/beam/erl_nif_api_funcs.h | 4 ++ 2 files changed, 74 insertions(+) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 8440fd26b5..21bf752bb6 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -638,6 +638,76 @@ unsigned char* enif_make_new_binary(ErlNifEnv* env, size_t size, return binary_bytes(*termp); } +int enif_term_to_binary(ErlNifEnv *dst_env, ERL_NIF_TERM term, + ErlNifBinary *bin) +{ + Sint size; + byte *bp; + Binary* refbin; + + size = erts_encode_ext_size(term); + if (!enif_alloc_binary(size, bin)) + return 0; + + refbin = bin->ref_bin; + + bp = bin->data; + + erts_encode_ext(term, &bp); + + bin->size = bp - bin->data; + refbin->orig_size = bin->size; + + ASSERT(bin->data + bin->size == bp); + + return 1; +} + +int enif_binary_to_term(ErlNifEnv *dst_env, ErlNifBinary *bin, + ERL_NIF_TERM *term) +{ + Sint size; + ErtsHeapFactory factory; + + if ((size = erts_decode_ext_size(bin->data, bin->size)) < 0) + return 0; + + if (size > 0) { + byte *bp; + + if (is_internal_pid(dst_env->proc->common.id)) { + flush_env(dst_env); + erts_factory_proc_prealloc_init(&factory, dst_env->proc, size); + cache_env(dst_env); + } else { + + /* this is guaranteed to create a heap fragment */ + if (!alloc_heap(dst_env, size)) + return 0; + + erts_factory_heap_frag_init(&factory, dst_env->heap_frag); + } + + bp = bin->data; + *term = erts_decode_ext(&factory, &bp); + + if (is_non_value(*term)) { + return 0; + } + + erts_factory_close(&factory); + } + else { + erts_factory_dummy_init(&factory); + *term = erts_decode_ext(&factory, &bin->data); + if (is_non_value(*term)) { + return 0; + } + ASSERT(is_immed(*term)); + } + return 1; +} + int enif_is_identical(Eterm lhs, Eterm rhs) { return EQ(lhs,rhs); diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h index 21864c8b35..0333e95331 100644 --- a/erts/emulator/beam/erl_nif_api_funcs.h +++ b/erts/emulator/beam/erl_nif_api_funcs.h @@ -169,6 +169,8 @@ ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM, enif_make_unique_integer, (ErlNifEnv *env, E ERL_NIF_API_FUNC_DECL(int, enif_is_process_alive, (ErlNifEnv *env, ErlNifPid *pid)); ERL_NIF_API_FUNC_DECL(int, enif_is_port_alive, (ErlNifEnv *env, ErlNifPort *port_id)); ERL_NIF_API_FUNC_DECL(int, enif_get_local_port, (ErlNifEnv* env, ERL_NIF_TERM, ErlNifPort* port_id)); +ERL_NIF_API_FUNC_DECL(int, enif_term_to_binary, (ErlNifEnv *env, ERL_NIF_TERM term, ErlNifBinary *bin)); +ERL_NIF_API_FUNC_DECL(int, enif_binary_to_term, (ErlNifEnv *env, ErlNifBinary *bin, ERL_NIF_TERM *term)); /* ** ADD NEW ENTRIES HERE (before this comment) !!! @@ -330,6 +332,8 @@ ERL_NIF_API_FUNC_DECL(int,enif_is_on_dirty_scheduler,(ErlNifEnv*)); # define enif_is_process_alive ERL_NIF_API_FUNC_MACRO(enif_is_process_alive) # define enif_is_port_alive ERL_NIF_API_FUNC_MACRO(enif_is_port_alive) # define enif_get_local_port ERL_NIF_API_FUNC_MACRO(enif_get_local_port) +# define enif_term_to_binary ERL_NIF_API_FUNC_MACRO(enif_term_to_binary) +# define enif_binary_to_term ERL_NIF_API_FUNC_MACRO(enif_binary_to_term) /* ** ADD NEW ENTRIES HERE (before this comment) -- cgit v1.2.3