diff options
Diffstat (limited to 'erts/emulator/beam/erl_nif.c')
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 70 |
1 files changed, 70 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); |