// This file is part of Jiffy released under the MIT license. // See the LICENSE file for more information. #include "erl_nif.h" #include "jiffy.h" typedef struct { // The Wrapper is a struct intended to be used as a resource to hold a // binary that's been validated by jiffy to be a valid JSON value ErlNifEnv* env; // Process independent env to hold the wrapped binary ERL_NIF_TERM bin; } Wrapper; static ERL_NIF_TERM wrap_new(ErlNifEnv* process_env, ErlNifEnv* process_independent_env, ERL_NIF_TERM binary) { jiffy_st* st = (jiffy_st*) enif_priv_data(process_env); Wrapper* wrapper_p = enif_alloc_resource(st->res_wrapper, sizeof(Wrapper)); ERL_NIF_TERM wrapper_term = enif_make_resource(process_env, wrapper_p); enif_release_resource(wrapper_p); wrapper_p->env = process_independent_env; wrapper_p->bin = binary; return wrapper_term; } ERL_NIF_TERM wrap_binary(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { if(argc != 1) { return enif_make_badarg(env); } ERL_NIF_TERM binary = argv[0]; if(!enif_is_binary(env, binary)) { return enif_make_badarg(env); } ErlNifEnv* process_independent_env = enif_alloc_env(); ERL_NIF_TERM bin_copy = enif_make_copy(process_independent_env, binary); return wrap_new(env, process_independent_env, bin_copy); } ERL_NIF_TERM wrap_enif_make_sub_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term, size_t pos, size_t size) { ErlNifEnv* process_independent_env = enif_alloc_env(); // sub_bin must be created in the same env as the parent binary and then // copied, segfaults sometimes otherwise ERL_NIF_TERM sub_bin = enif_make_sub_binary(env, bin_term, pos, size); return wrap_new(env, process_independent_env, enif_make_copy(process_independent_env, sub_bin)); } char* wrap_enif_make_new_binary(ErlNifEnv* env, size_t size, ERL_NIF_TERM* termp) { ErlNifEnv* process_independent_env = enif_alloc_env(); ERL_NIF_TERM bin; char* chrbuf = (char*) enif_make_new_binary(process_independent_env, size, &bin); *termp = wrap_new(env, process_independent_env, bin); return chrbuf; } int unwrap(ErlNifEnv* env, ERL_NIF_TERM wrapper_resource, ERL_NIF_TERM* bin_term_p) { jiffy_st* st = (jiffy_st*) enif_priv_data(env); Wrapper* wrapper_p = NULL; if(!enif_get_resource(env, wrapper_resource, st->res_wrapper, (void**) &wrapper_p)) { return 0; } *bin_term_p = enif_make_copy(env, wrapper_p->bin); return 1; } void wrapper_destroy(ErlNifEnv* env, void* obj) { Wrapper* wrapper_p = (Wrapper*) obj; enif_free_env(wrapper_p->env); }