|
|
@ -53,6 +53,7 @@ typedef struct { |
|
|
|
int is_partial; |
|
|
|
int return_maps; |
|
|
|
int return_trailer; |
|
|
|
int attempt_atom; |
|
|
|
ERL_NIF_TERM null_term; |
|
|
|
|
|
|
|
char* p; |
|
|
@ -82,6 +83,7 @@ dec_new(ErlNifEnv* env) |
|
|
|
d->is_partial = 0; |
|
|
|
d->return_maps = 0; |
|
|
|
d->return_trailer = 0; |
|
|
|
d->attempt_atom = 0; |
|
|
|
d->null_term = d->atoms->atom_null; |
|
|
|
|
|
|
|
d->p = NULL; |
|
|
@ -623,20 +625,41 @@ make_empty_object(ErlNifEnv* env, int ret_map) |
|
|
|
return enif_make_tuple1(env, enif_make_list(env, 0)); |
|
|
|
} |
|
|
|
|
|
|
|
ERL_NIF_TERM |
|
|
|
key_attempt_atom(ErlNifEnv* env, ERL_NIF_TERM key) { |
|
|
|
ERL_NIF_TERM keyatom; |
|
|
|
ErlNifBinary keybin; |
|
|
|
// maximum atom length is 255 bytes |
|
|
|
char keybuf[256]; |
|
|
|
|
|
|
|
if(enif_inspect_binary(env, key, &keybin) && keybin.size < sizeof(keybuf)) { |
|
|
|
memcpy(keybuf, keybin.data, keybin.size); |
|
|
|
keybuf[keybin.size] = 0; |
|
|
|
if(enif_make_existing_atom(env, keybuf, &keyatom, ERL_NIF_LATIN1)) { |
|
|
|
return keyatom; |
|
|
|
} |
|
|
|
} |
|
|
|
return key; |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
make_object(ErlNifEnv* env, ERL_NIF_TERM pairs, ERL_NIF_TERM* out, int ret_map) |
|
|
|
make_object(ErlNifEnv* env, ERL_NIF_TERM pairs, ERL_NIF_TERM* out, int ret_map, int attempt_atom) |
|
|
|
{ |
|
|
|
ERL_NIF_TERM ret; |
|
|
|
ERL_NIF_TERM key; |
|
|
|
ERL_NIF_TERM val; |
|
|
|
|
|
|
|
#if MAP_TYPE_PRESENT |
|
|
|
|
|
|
|
if(ret_map) { |
|
|
|
ret = enif_make_new_map(env); |
|
|
|
while(enif_get_list_cell(env, pairs, &val, &pairs)) { |
|
|
|
if(!enif_get_list_cell(env, pairs, &key, &pairs)) { |
|
|
|
assert(0 == 1 && "Unbalanced object pairs."); |
|
|
|
} |
|
|
|
if(attempt_atom) { |
|
|
|
key = key_attempt_atom(env, key); |
|
|
|
} |
|
|
|
if(!enif_make_map_put(env, ret, key, val, &ret)) { |
|
|
|
return 0; |
|
|
|
} |
|
|
@ -651,6 +674,9 @@ make_object(ErlNifEnv* env, ERL_NIF_TERM pairs, ERL_NIF_TERM* out, int ret_map) |
|
|
|
if(!enif_get_list_cell(env, pairs, &key, &pairs)) { |
|
|
|
assert(0 == 1 && "Unbalanced object pairs."); |
|
|
|
} |
|
|
|
if(attempt_atom) { |
|
|
|
key = key_attempt_atom(env, key); |
|
|
|
} |
|
|
|
val = enif_make_tuple2(env, key, val); |
|
|
|
ret = enif_make_list_cell(env, val, ret); |
|
|
|
} |
|
|
@ -720,6 +746,8 @@ decode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) |
|
|
|
d->null_term = d->atoms->atom_nil; |
|
|
|
} else if(get_null_term(env, val, &(d->null_term))) { |
|
|
|
continue; |
|
|
|
} else if(enif_compare(val, d->atoms->atom_attempt_atom) == 0) { |
|
|
|
d->attempt_atom = 1; |
|
|
|
} else { |
|
|
|
return enif_make_badarg(env); |
|
|
|
} |
|
|
@ -984,7 +1012,7 @@ decode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) |
|
|
|
} |
|
|
|
dec_pop(d, st_object); |
|
|
|
dec_pop(d, st_value); |
|
|
|
if(!make_object(env, curr, &val, d->return_maps)) { |
|
|
|
if(!make_object(env, curr, &val, d->return_maps, d->attempt_atom)) { |
|
|
|
ret = dec_error(d, "internal_object_error"); |
|
|
|
goto done; |
|
|
|
} |
|
|
|