Explorar el Código

Use a resource for the encoder structure

This is ground work to allow Jiffy to yield back to the scheduler.
Creating an encoder resource will allow for the necessary state to be
carried across NIF function invocations.
pull/65/head
Paul J. Davis hace 11 años
padre
commit
5ccff57ade
Se han modificado 4 ficheros con 100 adiciones y 39 borrados
  1. +79
    -34
      c_src/encoder.c
  2. +11
    -1
      c_src/jiffy.c
  3. +4
    -1
      c_src/jiffy.h
  4. +6
    -3
      src/jiffy.erl

+ 79
- 34
c_src/encoder.c Ver fichero

@ -36,6 +36,7 @@ typedef struct {
int iolen;
ERL_NIF_TERM iolist;
ErlNifBinary bin;
ErlNifBinary* curr;
@ -60,39 +61,24 @@ static char* shifts[NUM_SHIFTS] = {
};
int
enc_init(Encoder* e, ErlNifEnv* env, ERL_NIF_TERM opts, ErlNifBinary* bin)
Encoder*
enc_new(ErlNifEnv* env)
{
ERL_NIF_TERM val;
jiffy_st* st = (jiffy_st*) enif_priv_data(env);
Encoder* e = enif_alloc_resource(st->res_enc, sizeof(Encoder));
e->env = env;
e->atoms = enif_priv_data(env);
e->atoms = st;
e->uescape = 0;
e->pretty = 0;
e->shiftcnt = 0;
e->count = 0;
if(!enif_is_list(env, opts)) {
return 0;
}
while(enif_get_list_cell(env, opts, &val, &opts)) {
if(enif_compare(val, e->atoms->atom_uescape) == 0) {
e->uescape = 1;
} else if(enif_compare(val, e->atoms->atom_pretty) == 0) {
e->pretty = 1;
} else if(enif_compare(val, e->atoms->atom_force_utf8) == 0) {
// Ignore, handled in Erlang
} else {
return 0;
}
}
e->iolen = 0;
e->iolist = enif_make_list(env, 0);
e->curr = bin;
e->curr = &(e->bin);
if(!enif_alloc_binary(BIN_INC_SIZE, e->curr)) {
return 0;
e->curr = NULL;
enif_release_resource(e);
return NULL;
}
memset(e->curr->data, 0, e->curr->size);
@ -101,12 +87,21 @@ enc_init(Encoder* e, ErlNifEnv* env, ERL_NIF_TERM opts, ErlNifBinary* bin)
e->u = (unsigned char*) e->curr->data;
e->i = 0;
return e;
}
int
enc_init(Encoder* e, ErlNifEnv* env)
{
e->env = env;
return 1;
}
void
enc_destroy(Encoder* e)
enc_destroy(ErlNifEnv* env, void* obj)
{
Encoder* e = (Encoder*) obj;
if(e->curr != NULL) {
enif_release_binary(e->curr);
}
@ -494,13 +489,57 @@ enc_comma(Encoder* e)
}
ERL_NIF_TERM
encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
encode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
Encoder enc;
Encoder* e = &enc;
jiffy_st* st = (jiffy_st*) enif_priv_data(env);
Encoder* e;
ErlNifBinary bin;
ERL_NIF_TERM ret;
ERL_NIF_TERM opts;
ERL_NIF_TERM val;
ERL_NIF_TERM tmp_argv[3];
if(argc != 2) {
return enif_make_badarg(env);
}
e = enc_new(env);
if(e == NULL) {
return make_error(st, env, "internal_error");
}
tmp_argv[0] = enif_make_resource(env, e);
tmp_argv[1] = enif_make_list(env, 1, argv[0]);
tmp_argv[2] = enif_make_list(env, 0);
enif_release_resource(e);
opts = argv[1];
if(!enif_is_list(env, opts)) {
return enif_make_badarg(env);
}
while(enif_get_list_cell(env, opts, &val, &opts)) {
if(enif_compare(val, e->atoms->atom_uescape) == 0) {
e->uescape = 1;
} else if(enif_compare(val, e->atoms->atom_pretty) == 0) {
e->pretty = 1;
} else if(enif_compare(val, e->atoms->atom_force_utf8) == 0) {
// Ignore, handled in Erlang
} else {
return enif_make_badarg(env);
}
}
return encode_iter(env, 3, tmp_argv);
}
ERL_NIF_TERM
encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
Encoder* e;
jiffy_st* st = (jiffy_st*) enif_priv_data(env);
ERL_NIF_TERM ret = 0;
ERL_NIF_TERM stack;
ERL_NIF_TERM curr;
@ -510,15 +549,22 @@ encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
ErlNifSInt64 lval;
double dval;
if(argc != 2) {
if(argc != 3) {
return enif_make_badarg(env);
} else if(!enif_get_resource(env, argv[0], st->res_enc, (void**) &e)) {
return enif_make_badarg(env);
} else if(!enif_is_list(env, argv[1])) {
return enif_make_badarg(env);
} else if(!enif_is_list(env, argv[2])) {
return enif_make_badarg(env);
}
if(!enc_init(e, env, argv[1], &bin)) {
if(!enc_init(e, env)) {
return enif_make_badarg(env);
}
stack = enif_make_list(env, 1, argv[0]);
stack = argv[1];
e->iolist = argv[2];
while(!enif_is_empty_list(env, stack)) {
if(!enif_get_list_cell(env, stack, &curr, &stack)) {
@ -704,6 +750,5 @@ encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}
done:
enc_destroy(e);
return ret;
}

+ 11
- 1
c_src/jiffy.c Ver fichero

@ -37,6 +37,15 @@ load(ErlNifEnv* env, void** priv, ERL_NIF_TERM info)
NULL
);
st->res_enc = enif_open_resource_type(
env,
NULL,
"encoder",
enc_destroy,
ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER,
NULL
);
*priv = (void*) st;
return 0;
@ -65,7 +74,8 @@ static ErlNifFunc funcs[] =
{
{"nif_decode_init", 1, decode_init},
{"nif_decode_iter", 4, decode_iter},
{"nif_encode", 2, encode}
{"nif_encode_init", 2, encode_init},
{"nif_encode_iter", 3, encode_iter}
};
ERL_NIF_INIT(jiffy, funcs, &load, &reload, &upgrade, &unload);

+ 4
- 1
c_src/jiffy.h Ver fichero

@ -24,6 +24,7 @@ typedef struct {
ERL_NIF_TERM ref_array;
ErlNifResourceType* res_dec;
ErlNifResourceType* res_enc;
} jiffy_st;
ERL_NIF_TERM make_atom(ErlNifEnv* env, const char* name);
@ -32,9 +33,11 @@ ERL_NIF_TERM make_error(jiffy_st* st, ErlNifEnv* env, const char* error);
ERL_NIF_TERM decode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM decode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM encode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
void dec_destroy(ErlNifEnv* env, void* obj);
void enc_destroy(ErlNifEnv* env, void* obj);
int int_from_hex(const unsigned char* p);
int int_to_hex(int val, char* p);

+ 6
- 3
src/jiffy.erl Ver fichero

@ -26,7 +26,7 @@ encode(Data) ->
encode(Data, Options) ->
ForceUTF8 = lists:member(force_utf8, Options),
case nif_encode(Data, Options) of
case nif_encode_init(Data, Options) of
{error, invalid_string} when ForceUTF8 == true ->
FixedData = jiffy_utf8:fix(Data),
encode(FixedData, Options -- [force_utf8]);
@ -106,6 +106,9 @@ nif_decode_init(_Data) ->
nif_decode_iter(_Data, _Decoder, _, _) ->
?NOT_LOADED.
nif_encode(_Data, _Options) ->
?NOT_LOADED.
nif_encode_init(_Data, _Options) ->
?NOT_LOADED,
nif_encode_iter(x, y, z).
nif_encode_iter(_Encoder, _Stack, _IoList) ->
?NOT_LOADED.

Cargando…
Cancelar
Guardar