From 2dbf89f51c547914e994f51457140df9e9a1ca83 Mon Sep 17 00:00:00 2001 From: Stanislav Vishnevskiy Date: Tue, 19 Aug 2014 11:44:49 -0700 Subject: [PATCH] Improved Elixir compatibility This implements the `use_nil` option as discussed on issue #64. Passing the atom `use_nil` as an option to both encode and decode will replace the atom `null` with `nil` when decoding and encode `nil` as `null` when encoding values. Fixes #64 Fixes #68 --- c_src/decoder.c | 6 +++++- c_src/encoder.c | 9 +++++++-- c_src/jiffy.c | 2 ++ c_src/jiffy.h | 2 ++ test/jiffy_02_literal_tests.erl | 6 ++++++ 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/c_src/decoder.c b/c_src/decoder.c index 7cc74bd..e7dc48b 100644 --- a/c_src/decoder.c +++ b/c_src/decoder.c @@ -52,6 +52,7 @@ typedef struct { size_t bytes_per_iter; int is_partial; int return_maps; + int use_nil; char* p; unsigned char* u; @@ -79,6 +80,7 @@ dec_new(ErlNifEnv* env) d->bytes_per_iter = DEFAULT_BYTES_PER_ITER; d->is_partial = 0; d->return_maps = 0; + d->use_nil = 0; d->p = NULL; d->u = NULL; @@ -707,6 +709,8 @@ decode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) #else return enif_make_badarg(env); #endif + } else if(enif_compare(val, d->atoms->atom_use_nil) == 0) { + d->use_nil = 1; } else { return enif_make_badarg(env); } @@ -777,7 +781,7 @@ decode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ret = dec_error(d, "invalid_literal"); goto done; } - val = d->atoms->atom_null; + val = d->use_nil ? d->atoms->atom_nil : d->atoms->atom_null; dec_pop(d, st_value); d->i += 4; break; diff --git a/c_src/encoder.c b/c_src/encoder.c index fff9752..b6ea141 100644 --- a/c_src/encoder.c +++ b/c_src/encoder.c @@ -33,6 +33,7 @@ typedef struct { int uescape; int pretty; + int use_nil; int shiftcnt; int count; @@ -75,6 +76,7 @@ enc_new(ErlNifEnv* env) e->bytes_per_iter = DEFAULT_BYTES_PER_ITER; e->uescape = 0; e->pretty = 0; + e->use_nil = 0; e->shiftcnt = 0; e->count = 0; @@ -578,6 +580,8 @@ encode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) e->uescape = 1; } else if(enif_compare(val, e->atoms->atom_pretty) == 0) { e->pretty = 1; + } else if(enif_compare(val, e->atoms->atom_use_nil) == 0) { + e->use_nil = 1; } else if(enif_compare(val, e->atoms->atom_force_utf8) == 0) { // Ignore, handled in Erlang } else if(get_bytes_per_iter(env, val, &(e->bytes_per_iter))) { @@ -708,11 +712,12 @@ encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) stack = enif_make_list_cell(env, curr, stack); stack = enif_make_list_cell(env, e->atoms->ref_array, stack); stack = enif_make_list_cell(env, item, stack); - } else if(enif_compare(curr, e->atoms->atom_null) == 0) { + } else if(enif_compare(curr, e->atoms->atom_null) == 0 + || (e->use_nil && enif_compare(curr, e->atoms->atom_nil) == 0)) { if(!enc_literal(e, "null", 4)) { ret = enc_error(e, "null"); goto done; - } + } } else if(enif_compare(curr, e->atoms->atom_true) == 0) { if(!enc_literal(e, "true", 4)) { ret = enc_error(e, "true"); diff --git a/c_src/jiffy.c b/c_src/jiffy.c index b3b4ba4..205de91 100644 --- a/c_src/jiffy.c +++ b/c_src/jiffy.c @@ -26,6 +26,8 @@ load(ErlNifEnv* env, void** priv, ERL_NIF_TERM info) st->atom_iter = make_atom(env, "iter"); st->atom_bytes_per_iter = make_atom(env, "bytes_per_iter"); st->atom_return_maps = make_atom(env, "return_maps"); + st->atom_nil = make_atom(env, "nil"); + st->atom_use_nil = make_atom(env, "use_nil"); // Markers used in encoding st->ref_object = make_atom(env, "$object_ref$"); diff --git a/c_src/jiffy.h b/c_src/jiffy.h index 90f364c..34dff75 100644 --- a/c_src/jiffy.h +++ b/c_src/jiffy.h @@ -28,6 +28,8 @@ typedef struct { ERL_NIF_TERM atom_iter; ERL_NIF_TERM atom_bytes_per_iter; ERL_NIF_TERM atom_return_maps; + ERL_NIF_TERM atom_nil; + ERL_NIF_TERM atom_use_nil; ERL_NIF_TERM ref_object; ERL_NIF_TERM ref_array; diff --git a/test/jiffy_02_literal_tests.erl b/test/jiffy_02_literal_tests.erl index 4c50a34..a5ff576 100644 --- a/test/jiffy_02_literal_tests.erl +++ b/test/jiffy_02_literal_tests.erl @@ -26,3 +26,9 @@ null_test_() -> {"Decode", ?_assertEqual(null, jiffy:decode(<<"null">>))}, {"Encode", ?_assertEqual(<<"null">>, jiffy:encode(null))} ]}. + +nil_test_() -> + {"null", [ + {"Decode", ?_assertEqual(nil, jiffy:decode(<<"null">>, [use_nil]))}, + {"Encode", ?_assertEqual(<<"null">>, jiffy:encode(nil, [use_nil]))} + ]}.