ERL_NIF_TERM decode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { Decoder* d; jiffy_st* st = (jiffy_st*) enif_priv_data(env); ERL_NIF_TERM tmp_argv[5]; ERL_NIF_TERM opts; ERL_NIF_TERM val; if(argc != 2) { return enif_make_badarg(env); } d = dec_new(env); if(d == NULL) { return make_error(st, env, "internal_error"); } tmp_argv[0] = argv[0]; tmp_argv[1] = enif_make_resource(env, d); tmp_argv[2] = st->atom_error; tmp_argv[3] = enif_make_list(env, 0); tmp_argv[4] = enif_make_list(env, 0); enif_release_resource(d); opts = argv[1]; if(!enif_is_list(env, opts)) { return enif_make_badarg(env); } while(enif_get_list_cell(env, opts, &val, &opts)) { if(get_bytes_per_iter(env, val, &(d->bytes_per_red))) { continue; } else if(get_bytes_per_red(env, val, &(d->bytes_per_red))) { continue; } else if(enif_compare(val, d->atoms->atom_return_maps) == 0) { #if MAP_TYPE_PRESENT d->return_maps = 1; #else return enif_make_badarg(env); #endif } else if(enif_compare(val, d->atoms->atom_return_trailer) == 0) { d->return_trailer = 1; } else if(enif_compare(val, d->atoms->atom_dedupe_keys) == 0) { d->dedupe_keys = 1; } else if(enif_compare(val, d->atoms->atom_use_nil) == 0) { d->null_term = d->atoms->atom_nil; } else if(get_null_term(env, val, &(d->null_term))) { continue; } else { return enif_make_badarg(env); } } return decode_iter(env, 5, tmp_argv); }
void decode (FILE *fin, int size, FILE *fout) { Decoder *dec = dec_new (); List *word, *entry; unsigned int code; uchar chr; chr = fgetc (fin); fputc (chr, fout); word = list_new (chr); for (; size > 1; size--) { chr = fgetc (fin); if (dec->nbits > MAX_BITS) { dec = dec_reset (dec); list_destroy (word); word = list_new (chr); fputc (chr, fout); } else { /* Se agrega el nuevo caracter al buffer. */ dec->bitbuffer.buffer = (dec->bitbuffer.buffer << 8) | chr; dec->bitbuffer.length += 8; while (dec->bitbuffer.length >= dec->nbits) { dec->bitbuffer.length -= dec->nbits; code = dec->bitbuffer.buffer >> dec->bitbuffer.length; dec->bitbuffer.buffer &= (1 << dec->bitbuffer.length) - 1; if (code < dec->charbuffer.nelem) { /* El código está en el diccionario. */ entry = dec->charbuffer.buffer[code]; fputl (entry, fout); /* Agrega word + entry[0] al diccionario. */ word = list_prepend (word, entry->data); dec_add_word (dec, word); list_destroy (word); word = NULL; for (; entry != NULL; entry = entry->next) word = list_prepend (word, entry->data); } else { /* Agrega word + word[0] al diccionario. */ word = list_prepend (word, list_last (word)); dec_add_word (dec, word); fputl (dec->charbuffer.buffer[dec->charbuffer.nelem-1], fout); } } } } list_destroy (word); dec_destroy (dec); }
Decoder *dec_reset (Decoder *dec) { dec_destroy (dec); return dec_new (); }