static nif_term_t salt_box(nif_heap_t *hp, int argc, const nif_term_t argv[]) { /* salt_box(Plain_text, Nonce, Public_key, Secret_key) -> Cipher_text. */ nif_bin_t pt; nif_bin_t nc; nif_bin_t pk; nif_bin_t sk; nif_bin_t ct; nif_term_t raw; nif_term_t sub; if (argc != 4) return (BADARG); /* Unpack arguments ensuring they're suitably typed. */ if (! enif_inspect_iolist_as_binary(hp, argv[0], &pt)) return (BADARG); if (! enif_inspect_binary(hp, argv[1], &nc)) return (BADARG); if (! enif_inspect_binary(hp, argv[2], &pk)) return (BADARG); if (! enif_inspect_binary(hp, argv[3], &sk)) return (BADARG); /* Check constraints on size and zero prefixing. */ if (pt.size < crypto_box_ZEROBYTES || pt.size > SALT_MAX_MESSAGE_SIZE) return (BADARG); if (memcmp((const void *)pt.data, &salt_box_zerobytes[0], crypto_box_ZEROBYTES) != 0) return (BADARG); if (nc.size != crypto_box_NONCEBYTES) return (BADARG); if (pk.size != crypto_box_PUBLICKEYBYTES) return (BADARG); if (sk.size != crypto_box_SECRETKEYBYTES) return (BADARG); /* Allocate space for cipher text. NB: Passing ENOMEM as BADARG. */ if (! enif_alloc_binary(pt.size, &ct)) return (BADARG); /* Perform the crypto, strip leading zeros. */ (void)crypto_box(ct.data, pt.data, pt.size, nc.data, pk.data, sk.data); raw = enif_make_binary(hp, &ct); sub = enif_make_sub_binary(hp, raw, crypto_box_BOXZEROBYTES, ct.size - crypto_box_BOXZEROBYTES); return (sub); }
static nif_term_t salt_secretbox_open(nif_heap_t *hp, int argc, const nif_term_t argv[]) { /* salt_secretbox_open(Cipher_text, Nonce, Secret_key) -> {ok, Plain_text} | forged_or_garbled. */ nif_bin_t ct; nif_bin_t nc; nif_bin_t sk; nif_bin_t pt; nif_term_t raw; nif_term_t sub; nif_term_t tag; if (argc != 3) return (BADARG); /* Unpack arguments ensuring they're suitably typed. */ if (! enif_inspect_iolist_as_binary(hp, argv[0], &ct)) return (BADARG); if (! enif_inspect_binary(hp, argv[1], &nc)) return (BADARG); if (! enif_inspect_binary(hp, argv[2], &sk)) return (BADARG); /* Check constraints on size and zero prefixing. */ if (ct.size < crypto_secretbox_BOXZEROBYTES || ct.size > SALT_MAX_MESSAGE_SIZE) return (BADARG); if (memcmp((const void *)ct.data, &salt_secretbox_boxzerobytes[0], crypto_secretbox_BOXZEROBYTES) != 0) return (BADARG); if (nc.size != crypto_secretbox_NONCEBYTES) return (BADARG); if (sk.size != crypto_secretbox_KEYBYTES) return (BADARG); /* Allocate space for plain text. NB: Passing ENOMEM as BADARG. */ if (! enif_alloc_binary(ct.size, &pt)) return (BADARG); /* Perform the crypto, strip leading zeros. */ if (crypto_secretbox_open(pt.data, ct.data, ct.size, nc.data, sk.data) != 0) { enif_release_binary(&pt); return (enif_make_atom(hp, "forged_or_garbled")); } raw = enif_make_binary(hp, &pt); sub = enif_make_sub_binary(hp, raw, crypto_secretbox_ZEROBYTES, ct.size - crypto_secretbox_ZEROBYTES); tag = enif_make_atom(hp, "ok"); return (enif_make_tuple2(hp, tag, sub)); }
vector<ERL_NIF_TERM> LiberationCoding::doRepair(vector<ERL_NIF_TERM> blockList, vector<int> blockIdList, vector<int> repairList) { set<int> availSet(blockIdList.begin(), blockIdList.end()); if (availSet.size() < (unsigned int)k) throw std::invalid_argument("Not Enough Blocks"); else if (availSet.size() < blockIdList.size()) { throw std::invalid_argument("Blocks should be unique"); } size_t blockSize; ErlNifBinary blocks[k + m]; for(size_t i = 0; i < blockIdList.size(); ++i) { int blockId = blockIdList[i]; enif_inspect_binary(env, blockList[i], &blocks[blockId]); blockSize = blocks[blockId].size; } char* dataBlocks[k]; char* codeBlocks[m]; int erasures[k + m]; ErlNifBinary tmpBin; enif_alloc_binary(blockSize * (k + m), &tmpBin); char* tmpMemory = (char*)tmpBin.data; int j = 0; for(int i = 0; i < k + m; ++i) { i < k ? dataBlocks[i] = tmpMemory + i * blockSize : codeBlocks[i - k] = tmpMemory + i * blockSize; if (availSet.count(i) == 0) { erasures[j++] = i; } else { memcpy(tmpMemory + i * blockSize, blocks[i].data, blockSize); } } erasures[j] = -1; repairList.push_back(-1); int *selected = &repairList[0]; int *bitmatrix = liberation_coding_bitmatrix(k, w); jerasure_schedule_decode_selected_lazy(k, m, w, bitmatrix, erasures, selected, dataBlocks, codeBlocks, blockSize, blockSize / w, 0); vector<ERL_NIF_TERM> repairBlocks; int repairId; ERL_NIF_TERM allBlocksBin = enif_make_binary(env, &tmpBin); for(size_t i = 0; i < repairList.size() - 1; ++i) { repairId = repairList[i]; ERL_NIF_TERM block = enif_make_sub_binary(env, allBlocksBin, repairId * blockSize, blockSize); repairBlocks.push_back(block); } free(bitmatrix); return repairBlocks; }
static nif_term_t salt_box_afternm(nif_heap_t *hp, int argc, const nif_term_t argv[]) { /* salt_box_afternm(Plain_text, Nonce, Context) -> Cipher_text. */ nif_bin_t pt; nif_bin_t nc; nif_bin_t bn; nif_bin_t ct; nif_term_t raw; nif_term_t sub; if (argc != 3) return (BADARG); /* Unpack arguments ensuring they're suitably typed. */ if (! enif_inspect_iolist_as_binary(hp, argv[0], &pt)) return (BADARG); if (! enif_inspect_binary(hp, argv[1], &nc)) return (BADARG); if (! enif_inspect_binary(hp, argv[2], &bn)) return (BADARG); /* Check constraints on size and zero prefixing. */ if (pt.size < crypto_box_ZEROBYTES || pt.size > SALT_MAX_MESSAGE_SIZE) return (BADARG); if (memcmp((const void *)pt.data, &salt_box_zerobytes[0], crypto_box_ZEROBYTES) != 0) return (BADARG); if (nc.size != crypto_box_NONCEBYTES) return (BADARG); if (bn.size != crypto_box_BEFORENMBYTES) return (BADARG); /* Allocate space for precomputed context. NB: Passing ENOMEM as BADARG. */ if (! enif_alloc_binary(pt.size, &ct)) return (BADARG); /* Perform the crypto, strip leading zeros. */ (void)crypto_box_afternm(ct.data, pt.data, pt.size, nc.data, bn.data); raw = enif_make_binary(hp, &ct); sub = enif_make_sub_binary(hp, raw, crypto_box_BOXZEROBYTES, ct.size - crypto_box_BOXZEROBYTES); return (sub); }
static nif_term_t salt_sign_open(nif_heap_t *hp, int argc, const nif_term_t argv[]) { /* salt_sign_open(Signed_msg, Public_key) -> {ok, Verified_msg} | forged_or_garbled. */ unsigned long long len; nif_bin_t sm; nif_bin_t pk; nif_bin_t pm; nif_term_t raw; nif_term_t sub; nif_term_t tag; if (argc != 2) return (BADARG); /* Unpack arguments ensuring they're suitably typed. */ if (! enif_inspect_iolist_as_binary(hp, argv[0], &sm)) return (BADARG); if (! enif_inspect_binary(hp, argv[1], &pk)) return (BADARG); /* Check constraints on size. */ if (sm.size < 1 || sm.size > SALT_MAX_MESSAGE_SIZE) return (BADARG); if (pk.size != crypto_sign_PUBLICKEYBYTES) return (BADARG); /* Perform the crypto, potentially adjust signed message size. */ if (! enif_alloc_binary(sm.size + crypto_sign_BYTES, &pm)) return (BADARG); if (crypto_sign_open(pm.data, &len, sm.data, sm.size, pk.data) != 0) { enif_release_binary(&pm); return (enif_make_atom(hp, "forged_or_garbled")); } raw = enif_make_binary(hp, &pm); tag = enif_make_atom(hp, "ok"); if (len != sm.size) sub = enif_make_sub_binary(hp, raw, 0, len); else sub = raw; return (enif_make_tuple2(hp, tag, sub)); }
/*-----------------------------------------------------------------------------------------------------------------------*/ static ERL_NIF_TERM binary_to_msg(ErlNifEnv* env, int32_t argc, ERL_NIF_TERM const argv[]) { ERL_NIF_TERM parser_res; ParserRes* parser = NULL; ERL_NIF_TERM res = get_parser(env, argv[0], &parser_res, &parser); if (res != ok_atom) { return res; } int32_t delimiter = 0; if (!enif_get_int(env, argv[1], &delimiter) || delimiter <= 0 || delimiter >= 255) { return make_error(env, FIX_FAILED, "Wrong delimiter."); } ErlNifBinary bin; if (!enif_inspect_binary(env, argv[2], &bin)) { return make_error(env, FIX_FAILED, "Wrong binary."); } char const* stop = NULL; FIXError* error = NULL; pthread_rwlock_wrlock(&parser->lock); FIXMsg* fix_msg = fix_parser_str_to_msg(parser->ptr, (char const*)bin.data, bin.size, delimiter, &stop, &error); pthread_rwlock_unlock(&parser->lock); if (!fix_msg) { ERL_NIF_TERM ret = make_parser_error(env, fix_error_get_code(error), fix_error_get_text(error)); fix_error_free(error); return ret; } MsgRes* msg_res = (MsgRes*)enif_alloc_resource(message_res, sizeof(MsgRes)); msg_res->msg = fix_msg; msg_res->lock = &parser->lock; ERL_NIF_TERM msg_term = enif_make_resource(env, msg_res); enif_release_resource(msg_res); uint32_t pos = stop - (char const*)bin.data + 1; char const* msgType = fix_msg_get_type(fix_msg); return enif_make_tuple3( env, ok_atom, enif_make_tuple3(env, msg_atom, enif_make_string(env, msgType, ERL_NIF_LATIN1), enif_make_tuple2(env, parser_res, msg_term)), enif_make_sub_binary(env, argv[2], pos, bin.size - pos)); }
static ERL_NIF_TERM mmap_pread(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary bin; ERL_NIF_TERM sub; unsigned long offset, size; if(!enif_inspect_binary(env, argv[0], &bin)) { return enif_make_badarg(env); } if(!enif_get_ulong(env, argv[1], &offset)) { return enif_make_badarg(env); } if(!enif_get_ulong(env, argv[2], &size)) { return enif_make_badarg(env); } if((sub = enif_make_sub_binary(env, argv[0], offset, size))) { return enif_make_tuple2(env, enif_make_atom(env, "ok"), sub); } return enif_make_ulong(env, 42); }
static nif_term_t salt_sign(nif_heap_t *hp, int argc, const nif_term_t argv[]) { /* salt_sign(Message, Secret_key) -> Signed_msg. */ unsigned long long len; nif_bin_t pm; nif_bin_t sk; nif_bin_t sm; nif_term_t raw; if (argc != 2) return (BADARG); /* Unpack arguments ensuring they're suitably typed. */ if (! enif_inspect_iolist_as_binary(hp, argv[0], &pm)) return (BADARG); if (! enif_inspect_binary(hp, argv[1], &sk)) return (BADARG); /* Check constraints on size. */ if (pm.size < 1 || pm.size > SALT_MAX_MESSAGE_SIZE) return (BADARG); if (sk.size != crypto_sign_SECRETKEYBYTES) return (BADARG); /* Perform the crypto, potentially adjust signed message size. */ if (! enif_alloc_binary(pm.size + crypto_sign_BYTES, &sm)) return (BADARG); (void)crypto_sign(sm.data, &len, pm.data, pm.size, sk.data); raw = enif_make_binary(hp, &sm); if (len != sm.size) return (enif_make_sub_binary(hp, raw, 0, len)); else return (raw); }
static ERL_NIF_TERM nacl_box_open_padded(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary padded_ciphertext; ErlNifBinary nonce; ErlNifBinary pk; ErlNifBinary sk; ErlNifBinary result; if (!enif_inspect_iolist_as_binary(env, argv[0], &padded_ciphertext)) return enif_make_badarg(env); if (!enif_inspect_iolist_as_binary(env, argv[1], &nonce)) return enif_make_badarg(env); if (!enif_inspect_iolist_as_binary(env, argv[2], &pk)) return enif_make_badarg(env); if (!enif_inspect_iolist_as_binary(env, argv[3], &sk)) return enif_make_badarg(env); if (nonce.size != crypto_box_NONCEBYTES) return enif_make_badarg(env); if (pk.size != crypto_box_PUBLICKEYBYTES) return enif_make_badarg(env); if (sk.size != crypto_box_SECRETKEYBYTES) return enif_make_badarg(env); if (padded_ciphertext.size < crypto_box_BOXZEROBYTES) return enif_make_badarg(env); if (!enif_alloc_binary(padded_ciphertext.size, &result)) return nacl_error_tuple(env, "alloc_failed"); if (crypto_box_open(result.data, padded_ciphertext.data, padded_ciphertext.size, nonce.data, pk.data, sk.data)) { return nacl_error_tuple(env, "crypto_failed"); } return enif_make_sub_binary(env, enif_make_binary(env, &result), crypto_box_ZEROBYTES, padded_ciphertext.size - crypto_box_ZEROBYTES); }
static ERL_NIF_TERM nacl_secretbox_padded(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) { ErlNifBinary key; ErlNifBinary nonce; ErlNifBinary padded_message; ErlNifBinary padded_ciphertext; if (!enif_inspect_iolist_as_binary(env, argv[0], &padded_message)) return enif_make_badarg(env); if (!enif_inspect_iolist_as_binary(env, argv[1], &nonce)) return enif_make_badarg(env); if (!enif_inspect_iolist_as_binary(env, argv[2], &key)) return enif_make_badarg(env); if (key.size != crypto_secretbox_KEYBYTES) return enif_make_badarg(env); if (nonce.size != crypto_secretbox_NONCEBYTES) return enif_make_badarg(env); if (padded_message.size < crypto_secretbox_ZEROBYTES) return enif_make_badarg(env); if (!enif_alloc_binary(padded_message.size, &padded_ciphertext)) return nacl_error_tuple(env, "alloc_failed"); crypto_secretbox( padded_ciphertext.data, padded_message.data, padded_message.size, nonce.data, key.data ); return enif_make_sub_binary(env, enif_make_binary(env, &padded_ciphertext), crypto_secretbox_BOXZEROBYTES, padded_message.size - crypto_secretbox_BOXZEROBYTES); }
int dec_string(Decoder* d, ERL_NIF_TERM* value) { int has_escape = 0; int num_escapes = 0; int st; int ulen; int ui; int hi; int lo; char* chrbuf; int chrpos; if(d->p[d->i] != '\"') { return 0; } d->i++; st = d->i; while(d->i < d->len) { if(d->u[d->i] < 0x20) { return 0; } else if(d->p[d->i] == '\"') { d->i++; goto parse; } else if(d->p[d->i] == '\\') { if(d->i+1 >= d->len) { return 0; } has_escape = 1; num_escapes += 1; d->i++; switch(d->p[d->i]) { case '\"': case '\\': case '/': case 'b': case 'f': case 'n': case 'r': case 't': d->i++; break; case 'u': hi = 0; lo = 0; d->i++; if(d->i + 4 >= d->len) { return 0; } hi = int_from_hex(&(d->u[d->i])); if(hi < 0) { return 0; } d->i += 4; if(hi >= 0xD800 && hi < 0xDC00) { if(d->i + 6 >= d->len) { return 0; } if(d->p[d->i++] != '\\') { return 0; } else if(d->p[d->i++] != 'u') { return 0; } lo = int_from_hex(&(d->u[d->i])); if(lo < 0) { return 0; } hi = unicode_from_pair(hi, lo); if(hi < 0) { return 0; } } hi = utf8_len(hi); if(hi < 0) { return 0; } if(lo == 0) { num_escapes += 5 - hi; } else { num_escapes += 11 - hi; } break; default: return 0; } } else if(d->u[d->i] < 0x80) { d->i++; } else { ulen = utf8_validate(&(d->u[d->i]), d->len - d->i); if(ulen < 0) { return 0; } d->i += ulen; } } // The goto above ensures that we only // hit this when a string is not terminated // correctly. return 0; parse: if(!has_escape) { *value = enif_make_sub_binary(d->env, d->arg, st, (d->i - st - 1)); return 1; } hi = 0; lo = 0; ulen = (d->i - 1) - st - num_escapes; chrbuf = (char*) enif_make_new_binary(d->env, ulen, value); chrpos = 0; ui = st; while(ui < d->i - 1) { if(d->p[ui] != '\\') { chrbuf[chrpos++] = d->p[ui++]; continue; } ui++; switch(d->p[ui]) { case '\"': case '\\': case '/': chrbuf[chrpos++] = d->p[ui]; ui++; break; case 'b': chrbuf[chrpos++] = '\b'; ui++; break; case 'f': chrbuf[chrpos++] = '\f'; ui++; break; case 'n': chrbuf[chrpos++] = '\n'; ui++; break; case 'r': chrbuf[chrpos++] = '\r'; ui++; break; case 't': chrbuf[chrpos++] = '\t'; ui++; break; case 'u': ui++; hi = int_from_hex(&(d->u[ui])); if(hi < 0) { return 0; } if(hi >= 0xD800 && hi < 0xDC00) { lo = int_from_hex(&(d->u[ui+6])); if(lo < 0) { return 0; } hi = unicode_from_pair(hi, lo); ui += 10; } else { ui += 4; } hi = unicode_to_utf8(hi, (unsigned char*) chrbuf+chrpos); if(hi < 0) { return 0; } chrpos += hi; break; default: return 0; } } return 1; }
void emit(parser_data *data, const char *at, size_t length, ERL_NIF_TERM name) { size_t pos = ((void *)at) - ((void *)data->buf_bin->data); ERL_NIF_TERM term = enif_make_sub_binary(data->env, data->buf_term, pos, length); data->result = enif_make_list_cell(data->env, enif_make_tuple2(data->env, name, term), data->result); }
ERL_NIF_TERM decode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { Decoder* d; jiffy_st* st = (jiffy_st*) enif_priv_data(env); ErlNifBinary bin; ERL_NIF_TERM objs; ERL_NIF_TERM curr; ERL_NIF_TERM val = argv[2]; ERL_NIF_TERM trailer; ERL_NIF_TERM ret; size_t bytes_read = 0; if(argc != 5) { return enif_make_badarg(env); } else if(!enif_inspect_binary(env, argv[0], &bin)) { return enif_make_badarg(env); } else if(!enif_get_resource(env, argv[1], st->res_dec, (void**) &d)) { return enif_make_badarg(env); } else if(!enif_is_list(env, argv[3])) { return enif_make_badarg(env); } else if(!enif_is_list(env, argv[4])) { return enif_make_badarg(env); } dec_init(d, env, argv[0], &bin); objs = argv[3]; curr = argv[4]; while(d->i < bin.size) { if(should_yield(env, &bytes_read, d->bytes_per_red)) { return enif_make_tuple5( env, st->atom_iter, argv[1], val, objs, curr ); } bytes_read += 1; switch(dec_curr(d)) { case st_value: switch(d->p[d->i]) { case ' ': case '\n': case '\r': case '\t': d->i++; break; case 'n': if(d->i + 3 >= d->len) { ret = dec_error(d, "invalid_literal"); goto done; } if(memcmp(&(d->p[d->i]), "null", 4) != 0) { ret = dec_error(d, "invalid_literal"); goto done; } val = d->null_term; dec_pop(d, st_value); d->i += 4; break; case 't': if(d->i + 3 >= d->len) { ret = dec_error(d, "invalid_literal"); goto done; } if(memcmp(&(d->p[d->i]), "true", 4) != 0) { ret = dec_error(d, "invalid_literal"); goto done; } val = d->atoms->atom_true; dec_pop(d, st_value); d->i += 4; break; case 'f': if(d->i + 4 >= bin.size) { ret = dec_error(d, "invalid_literal"); goto done; } if(memcmp(&(d->p[d->i]), "false", 5) != 0) { ret = dec_error(d, "invalid_literal"); goto done; } val = d->atoms->atom_false; dec_pop(d, st_value); d->i += 5; break; case '\"': if(!dec_string(d, &val)) { ret = dec_error(d, "invalid_string"); goto done; } dec_pop(d, st_value); break; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if(!dec_number(d, &val)) { ret = dec_error(d, "invalid_number"); goto done; } dec_pop(d, st_value); break; case '{': dec_push(d, st_object); dec_push(d, st_key); objs = enif_make_list_cell(env, curr, objs); curr = enif_make_list(env, 0); d->i++; break; case '[': dec_push(d, st_array); dec_push(d, st_value); objs = enif_make_list_cell(env, curr, objs); curr = enif_make_list(env, 0); d->i++; break; case ']': if(!enif_is_empty_list(env, curr)) { ret = dec_error(d, "invalid_json"); goto done; } dec_pop(d, st_value); if(dec_curr(d) != st_array) { ret = dec_error(d, "invalid_json"); goto done; } dec_pop(d, st_array); dec_pop(d, st_value); val = curr; // curr is [] if(!enif_get_list_cell(env, objs, &curr, &objs)) { ret = dec_error(d, "internal_error"); goto done; } d->i++; break; default: ret = dec_error(d, "invalid_json"); goto done; } if(dec_top(d) == 0) { dec_push(d, st_done); } else if(dec_curr(d) != st_value && dec_curr(d) != st_key) { dec_push(d, st_comma); curr = enif_make_list_cell(env, val, curr); } break; case st_key: switch(d->p[d->i]) { case ' ': case '\n': case '\r': case '\t': d->i++; break; case '\"': if(!dec_string(d, &val)) { ret = dec_error(d, "invalid_string"); goto done; } dec_pop(d, st_key); dec_push(d, st_colon); curr = enif_make_list_cell(env, val, curr); break; case '}': if(!enif_is_empty_list(env, curr)) { ret = dec_error(d, "invalid_json"); goto done; } dec_pop(d, st_key); dec_pop(d, st_object); dec_pop(d, st_value); val = make_empty_object(env, d->return_maps); if(!enif_get_list_cell(env, objs, &curr, &objs)) { ret = dec_error(d, "internal_error"); goto done; } if(dec_top(d) == 0) { dec_push(d, st_done); } else { dec_push(d, st_comma); curr = enif_make_list_cell(env, val, curr); } d->i++; break; default: ret = dec_error(d, "invalid_json"); goto done; } break; case st_colon: switch(d->p[d->i]) { case ' ': case '\n': case '\r': case '\t': d->i++; break; case ':': dec_pop(d, st_colon); dec_push(d, st_value); d->i++; break; default: ret = dec_error(d, "invalid_json"); goto done; } break; case st_comma: switch(d->p[d->i]) { case ' ': case '\n': case '\r': case '\t': d->i++; break; case ',': dec_pop(d, st_comma); switch(dec_curr(d)) { case st_object: dec_push(d, st_key); break; case st_array: dec_push(d, st_value); break; default: ret = dec_error(d, "internal_error"); goto done; } d->i++; break; case '}': dec_pop(d, st_comma); if(dec_curr(d) != st_object) { ret = dec_error(d, "invalid_json"); goto done; } dec_pop(d, st_object); dec_pop(d, st_value); if(!make_object(env, curr, &val, d->return_maps, d->dedupe_keys)) { ret = dec_error(d, "internal_object_error"); goto done; } if(!enif_get_list_cell(env, objs, &curr, &objs)) { ret = dec_error(d, "internal_error"); goto done; } if(dec_top(d) > 0) { dec_push(d, st_comma); curr = enif_make_list_cell(env, val, curr); } else { dec_push(d, st_done); } d->i++; break; case ']': dec_pop(d, st_comma); if(dec_curr(d) != st_array) { ret = dec_error(d, "invalid_json"); goto done; } dec_pop(d, st_array); dec_pop(d, st_value); val = make_array(env, curr); if(!enif_get_list_cell(env, objs, &curr, &objs)) { ret = dec_error(d, "internal_error"); goto done; } if(dec_top(d) > 0) { dec_push(d, st_comma); curr = enif_make_list_cell(env, val, curr); } else { dec_push(d, st_done); } d->i++; break; default: ret = dec_error(d, "invalid_json"); goto done; } break; case st_done: switch(d->p[d->i]) { case ' ': case '\n': case '\r': case '\t': d->i++; break; default: goto decode_done; } break; default: ret = dec_error(d, "invalid_internal_state"); goto done; } } decode_done: if(d->i < bin.size && d->return_trailer) { trailer = enif_make_sub_binary(env, argv[0], d->i, bin.size - d->i); val = enif_make_tuple3(env, d->atoms->atom_has_trailer, val, trailer); } else if(d->i < bin.size) { ret = dec_error(d, "invalid_trailing_data"); goto done; } if(dec_curr(d) != st_done) { ret = dec_error(d, "truncated_json"); } else if(d->is_partial) { ret = enif_make_tuple2(env, d->atoms->atom_partial, val); } else { ret = val; } done: return ret; }
ERL_NIF_TERM parse_buffer(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { Parser par; Parser* parser = ∥ ErlNifBinary buffer; if(!enif_inspect_binary(env, argv[0], &buffer)) return enif_make_badarg(env); if(!init_parser(parser, env, argv[0], &buffer, argv[1])) return enif_make_badarg(env); ERL_NIF_TERM reply = argv[2]; ERL_NIF_TERM return_value; parser->remaining_length = buffer.size; parser->pointer = buffer.data + parser->frame_start; while (parser->frame_start < parser->buffer_size) { parser->frame_size = D3I(parser->pointer); parser->pointer += 3; unsigned long seg_num = D1(parser->pointer); parser->pointer += 1; parser->remaining_length -= (parser->frame_size + 4); if (parser->remaining_length < 0) { return_value = enif_make_tuple3(env, parser->atoms->atom_incomplete, reply, enif_make_sub_binary(env, parser->raw, parser->frame_start, parser->buffer_size - parser->frame_start)); break; } if (*parser->pointer == MYSQL_RESP_EOF) { ERL_NIF_TERM remaining_buffer = enif_make_sub_binary(env, parser->raw, parser->frame_start + parser->frame_size + 4, parser->remaining_length); if (parser->frame_size == 5) { unsigned long server_status = D2I(parser->pointer + 3); return_value = enif_make_tuple5(env, parser->atoms->atom_eof, enif_make_uint(env, server_status), enif_make_uint(env, seg_num), reply, remaining_buffer); } else return_value = enif_make_tuple4(env, parser->atoms->atom_eof, enif_make_uint(env, seg_num), reply, remaining_buffer); break; } parser->frame_start += 4; ERL_NIF_TERM row = parse_line(parser); reply = enif_make_list_cell(env, row, reply); parser->frame_start += parser->frame_size; parser->pointer += parser->frame_size; } if (parser->frame_start >= parser->buffer_size) return_value = enif_make_tuple3(env, parser->atoms->atom_incomplete, reply, parser->atoms->atom_empty); destroy_parser(parser); return return_value; }
ERL_NIF_TERM LiberationCoding::doDecode(vector<ERL_NIF_TERM> blockList, vector<int> blockIdList, size_t dataSize) { set<int> availSet(blockIdList.begin(), blockIdList.end()); if (availSet.size() < (unsigned int)k) throw std::invalid_argument("Not Enough Blocks"); else if (availSet.size() < blockIdList.size()) { throw std::invalid_argument("Blocks should be unique"); } size_t blockSize; ErlNifBinary blocks[k + m]; for(size_t i = 0; i < blockIdList.size(); ++i) { int blockId = blockIdList[i]; enif_inspect_binary(env, blockList[i], &blocks[blockId]); blockSize = blocks[blockId].size; } bool needFix = false; for(int i = 0; i < k; ++i) if (availSet.count(i) == 0) { needFix = true; } if (!needFix) { ErlNifBinary file; enif_alloc_binary(dataSize, &file); size_t copySize, offset = 0; for(int i = 0; i < k; ++i) { offset = i * blockSize; copySize = min(dataSize - offset, blockSize); memcpy(file.data + offset, blocks[i].data, copySize); } ERL_NIF_TERM bin = enif_make_binary(env, &file); return bin; } char* dataBlocks[k]; char* codeBlocks[m]; int erasures[k + m]; ErlNifBinary tmpBin; enif_alloc_binary(blockSize * (k + m), &tmpBin); char* tmpMemory = (char*)tmpBin.data; int j = 0; for(int i = 0; i < k + m; ++i) { i < k ? dataBlocks[i] = tmpMemory + i * blockSize : codeBlocks[i - k] = tmpMemory + i * blockSize; if (availSet.count(i) == 0) { erasures[j++] = i; } else { memcpy(tmpMemory + i * blockSize, blocks[i].data, blockSize); } } erasures[j] = -1; int *bitmatrix = liberation_coding_bitmatrix(k, w); jerasure_schedule_decode_data_lazy(k, m, w, bitmatrix, erasures, dataBlocks, codeBlocks, blockSize, blockSize / w, 0); ERL_NIF_TERM allBlocksBin = enif_make_binary(env, &tmpBin); ERL_NIF_TERM bin = enif_make_sub_binary(env, allBlocksBin, 0, dataSize); free(bitmatrix); return bin; }
int dec_number(Decoder* d, ERL_NIF_TERM* value) { ERL_NIF_TERM num_type = d->atoms->atom_error; char state = nst_init; char nbuf[NUM_BUF_LEN]; int st = d->i; int has_frac = 0; int has_exp = 0; double dval; long lval; while(d->i < d->len) { switch(state) { case nst_init: switch(d->p[d->i]) { case '-': state = nst_sign; d->i++; break; case '0': state = nst_frac0; d->i++; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': state = nst_mantissa; d->i++; break; default: return 0; } break; case nst_sign: switch(d->p[d->i]) { case '0': state = nst_frac0; d->i++; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': state = nst_mantissa; d->i++; break; default: return 0; } break; case nst_mantissa: switch(d->p[d->i]) { case '.': state = nst_frac1; d->i++; break; case 'e': case 'E': state = nst_esign; d->i++; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': d->i++; break; default: goto parse; } break; case nst_frac0: switch(d->p[d->i]) { case '.': state = nst_frac1; d->i++; break; case 'e': case 'E': state = nst_esign; d->i++; break; default: goto parse; } break; case nst_frac1: has_frac = 1; switch(d->p[d->i]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': state = nst_frac; d->i++; break; default: goto parse; } break; case nst_frac: switch(d->p[d->i]) { case 'e': case 'E': state = nst_esign; d->i++; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': d->i++; break; default: goto parse; } break; case nst_esign: has_exp = 1; switch(d->p[d->i]) { case '-': case '+': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': state = nst_edigit; d->i++; break; default: return 0; } break; case nst_edigit: switch(d->p[d->i]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': d->i++; break; default: goto parse; } break; default: return 0; } } parse: switch(state) { case nst_init: case nst_sign: case nst_frac1: case nst_esign: return 0; default: break; } errno = 0; if(d->i - st < NUM_BUF_LEN) { memset(nbuf, 0, NUM_BUF_LEN); memcpy(nbuf, &(d->p[st]), d->i - st); if(has_frac || has_exp) { dval = strtod(nbuf, NULL); if(errno != ERANGE) { *value = enif_make_double(d->env, dval); return 1; } } else { lval = strtol(nbuf, NULL, 10); if(errno != ERANGE) { *value = enif_make_int64(d->env, lval); return 1; } } } if(!has_frac && !has_exp) { num_type = d->atoms->atom_bignum; } else if(!has_frac && has_exp) { num_type = d->atoms->atom_bignum_e; } else { num_type = d->atoms->atom_bigdbl; } d->is_partial = 1; *value = enif_make_sub_binary(d->env, d->arg, st, d->i - st); *value = enif_make_tuple2(d->env, num_type, *value); return 1; }
ERL_NIF_TERM parse_line(Parser* parser) { unsigned long idx = parser->frame_start; unsigned col = 0; ERL_NIF_TERM reply[parser->table_width]; while(col < parser->table_width) { unsigned char size_length = (parser->buffer[idx] <= MYSQL_LIMIT_BYTE) ? (1) : (parser->buffer[idx] - MYSQL_LIMIT_BYTE); size_length *= (size_length == 4) ? (2) : (1); unsigned long long content_length = 0; if (parser->buffer[idx] != MYSQL_NULL_RESULT) { switch (size_length) { case 1: content_length = D1(parser->buffer + idx); break; case 2: content_length = D2I(parser->buffer + idx + 1); size_length++; break; case 3: content_length = D3I(parser->buffer + idx + 1); size_length++; break; case 8: content_length = D8I(parser->buffer + idx + 1); size_length++; break; } } else content_length = 0; unsigned char *new_val = parser->buffer + idx + size_length; MYSQL_TIME time_; if (content_length == 0) reply[col] = parser->atoms->atom_undefined; else if (parser->columns[col] == MYSQL_TYPE_BIT || parser->columns[col] == MYSQL_TYPE_TINY_BLOB || parser->columns[col] == MYSQL_TYPE_MEDIUM_BLOB || parser->columns[col] == MYSQL_TYPE_LONG_BLOB || parser->columns[col] == MYSQL_TYPE_BLOB || parser->columns[col] == MYSQL_TYPE_VAR_STRING || parser->columns[col] == MYSQL_TYPE_STRING) reply[col] = enif_make_sub_binary(parser->env, parser->raw, idx + size_length, size_length + content_length - 1); else if (parser->columns[col] == MYSQL_TYPE_TINY || parser->columns[col] == MYSQL_TYPE_SHORT || parser->columns[col] == MYSQL_TYPE_LONG || parser->columns[col] == MYSQL_TYPE_LONGLONG || parser->columns[col] == MYSQL_TYPE_INT24 || parser->columns[col] == MYSQL_TYPE_YEAR) reply[col] = enif_make_int(parser->env, atoi((char *) new_val)); else if (parser->columns[col] == MYSQL_TYPE_DECIMAL || parser->columns[col] == MYSQL_TYPE_NEWDECIMAL || parser->columns[col] == MYSQL_TYPE_FLOAT || parser->columns[col] == MYSQL_TYPE_DOUBLE) reply[col] = enif_make_double(parser->env, strtod((const char *) new_val, NULL)); else if (parser->columns[col] == MYSQL_TYPE_DATE) { sscanf((const char*) new_val, "%d-%d-%d", &time_.year, &time_.month, &time_.day); reply[col] = enif_make_tuple2(parser->env, parser->atoms->atom_date, enif_make_tuple3(parser->env, enif_make_int(parser->env, time_.year), enif_make_int(parser->env, time_.month), enif_make_int(parser->env, time_.day)) ); } else if (parser->columns[col] == MYSQL_TYPE_TIME) { sscanf((const char*) new_val, "%d:%d:%d", &time_.hour, &time_.minute, &time_.second); reply[col] = enif_make_tuple2(parser->env, parser->atoms->atom_time, enif_make_tuple3(parser->env, enif_make_int(parser->env, time_.hour), enif_make_int(parser->env, time_.minute), enif_make_int(parser->env, time_.second)) ); } else if (parser->columns[col] == MYSQL_TYPE_TIMESTAMP || parser->columns[col] == MYSQL_TYPE_DATETIME) { sscanf((const char*) new_val, "%d-%d-%d %d:%d:%d", &time_.year, &time_.month, &time_.day, &time_.hour, &time_.minute, &time_.second); reply[col] = enif_make_tuple2(parser->env, parser->atoms->atom_datetime, enif_make_tuple2(parser->env, enif_make_tuple3(parser->env, enif_make_int(parser->env, time_.year), enif_make_int(parser->env, time_.month), enif_make_int(parser->env, time_.day) ), enif_make_tuple3(parser->env, enif_make_int(parser->env, time_.hour), enif_make_int(parser->env, time_.minute), enif_make_int(parser->env, time_.second) ) ) ); } else if (parser->columns[col] == MYSQL_TYPE_FIELD_EXTRA) { ERL_NIF_TERM default_content; if (content_length > 12) default_content = enif_make_sub_binary(parser->env, parser->raw, idx + size_length + 12, size_length + content_length - 13); else default_content = parser->atoms->atom_undefined; reply[col] = enif_make_tuple6(parser->env, enif_make_int(parser->env, D2I(new_val)), enif_make_int(parser->env, D4I(new_val + 2)), enif_make_int(parser->env, D1(new_val + 6)), enif_make_int(parser->env, D2I(new_val + 7)), enif_make_int(parser->env, D1(new_val + 11)), default_content ); } col++; idx += content_length + size_length; } return enif_make_list_from_array(parser->env, reply, parser->table_width); }