aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2015-12-17 14:14:54 +0100
committerLukas Larsson <[email protected]>2016-03-29 14:57:11 +0200
commit1bd56e2b5141a3afdca4e854e9b667807bf4e2f3 (patch)
tree0171c0a573a08068d7155ac73bcd6a6d3fc941d6 /erts/emulator/beam
parent348f3f2ee2d2707e30658c3600e05309ad0e72bf (diff)
downloadotp-1bd56e2b5141a3afdca4e854e9b667807bf4e2f3.tar.gz
otp-1bd56e2b5141a3afdca4e854e9b667807bf4e2f3.tar.bz2
otp-1bd56e2b5141a3afdca4e854e9b667807bf4e2f3.zip
erts: Add enif_term_to_binary and enif_binary_to_term
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/erl_nif.c70
-rw-r--r--erts/emulator/beam/erl_nif_api_funcs.h4
2 files changed, 74 insertions, 0 deletions
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)