ERL_NIF_TERM finish(ErlNifEnv *env, ERL_NIF_TERM *path, ERL_NIF_TERM *step, int length) { int i; ERL_NIF_TERM list = enif_make_list(env, 0); for (i = length - 1; i >= 0; i--) { list = enif_make_list_cell(env, path[i], list); } free(step); free(path); return list; }
static ERL_NIF_TERM to_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { /* to_term(Matrix) -> [[first row], [second row], ...,[last row]] */ unsigned i, j; ERL_NIF_TERM res; mx_t mx; mx.p = NULL; if (!enif_get_resource(env, argv[0], resource_type, &mx.vp)) { return enif_make_badarg(env); } res = enif_make_list(env, 0); for (i = mx.p->nrows; i-- > 0; ) { ERL_NIF_TERM row = enif_make_list(env, 0); for (j = mx.p->ncols; j-- > 0; ) { row = enif_make_list_cell(env, enif_make_double(env, POS(mx.p,i,j)), row); } res = enif_make_list_cell(env, row, res); } return res; }
static void *character_data_handler(expat_parser *parser_data, const XML_Char *s, int len) { ErlNifBinary cdata; enif_alloc_binary(len, &cdata); strncpy((char *)cdata.data, (const char *)s, len); ERL_NIF_TERM event = enif_make_tuple(parser_data->env, 2, XML_CDATA, enif_make_binary(parser_data->env, &cdata)); parser_data->result = enif_make_list_cell(parser_data->env, event, parser_data->result); return NULL; };
ERL_NIF_TERM vert_virNodeListDevices(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { VERT_RESOURCE *vp = NULL; ErlNifBinary cap = {0}; char **names = NULL; int maxnames = 0; u_int32_t flags = 0; int n = 0; int rv = 0; ERL_NIF_TERM dev = {0}; VERT_GET_RESOURCE(0, vp, VERT_RES_CONNECT); VERT_GET_IOLIST(1, cap); VERT_GET_INT(2, maxnames); VERT_GET_UINT(3, flags); if (cap.size > 0) VERT_BIN_APPEND_NULL(cap); names = calloc(maxnames, sizeof(char *)); if (names == NULL) return error_tuple(env, atom_enomem); rv = virNodeListDevices(vp->res, (cap.size == 0 ? NULL : (char *)cap.data), names, maxnames, flags); if (rv < 0) goto ERR; dev = enif_make_list(env, 0); for (n = 0; n < rv; n++) { dev = enif_make_list_cell(env, enif_make_string(env, names[n], ERL_NIF_LATIN1), dev); } free(names); return enif_make_tuple2(env, atom_ok, dev); ERR: free(names); return verterr(env); }
static ERL_NIF_TERM list_seq(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM list; int n; if (!enif_get_int(env, argv[0], &n)) { return enif_make_badarg(env); } list = enif_make_list(env, 0); /* NIL */ while (n > 0) { list = enif_make_list_cell(env, enif_make_int(env,n), list); n--; } return list; }
static ERL_NIF_TERM tuple_2_list(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int arity = -1; const ERL_NIF_TERM* ptr; ERL_NIF_TERM list = enif_make_list(env,0); if (argc!=1 || !enif_get_tuple(env,argv[0],&arity,&ptr)) { return enif_make_badarg(env); } while (--arity >= 0) { list = enif_make_list_cell(env,ptr[arity],list); } return list; }
static ERL_NIF_TERM do_multi_step(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt, const ERL_NIF_TERM arg) { ERL_NIF_TERM status; ERL_NIF_TERM rows = enif_make_list_from_array(env, NULL, 0); ERL_NIF_TERM *rowBuffer = NULL; int rowBufferSize = 0; int chunk_size = 0; enif_get_int(env, arg, &chunk_size); int rc = sqlite3_step(stmt); while (rc == SQLITE_ROW && chunk_size-- > 0) { if (!rowBufferSize) rowBufferSize = sqlite3_column_count(stmt); if (rowBuffer == NULL) rowBuffer = (ERL_NIF_TERM *) enif_alloc(sizeof(ERL_NIF_TERM)*rowBufferSize); rows = enif_make_list_cell(env, make_row(env, stmt, rowBuffer, rowBufferSize), rows); if (chunk_size > 0) rc = sqlite3_step(stmt); } switch(rc) { case SQLITE_ROW: status = make_atom(env, "rows"); break; case SQLITE_BUSY: status = make_atom(env, "$busy"); break; case SQLITE_DONE: /* * Automatically reset the statement after a done so * column_names will work after the statement is done. * * Not resetting the statement can lead to vm crashes. */ sqlite3_reset(stmt); status = make_atom(env, "$done"); break; default: /* We use prepare_v2, so any error code can be returned. */ return make_sqlite3_error_tuple(env, rc, db); } enif_free(rowBuffer); return enif_make_tuple2(env, status, rows); }
static ERL_NIF_TERM make_hash(ErlNifEnv* env, mrb_state* mrb, mrb_value o) { mrb_value keys = mrb_hash_keys(mrb, o); size_t len = (int) RARRAY(keys)->len; ERL_NIF_TERM list = enif_make_list_from_array(env, NULL, 0); for(int i = len; i>0; --i) { mrb_value k = mrb_ary_ref(mrb, keys, (mrb_int)i - 1); ERL_NIF_TERM key = mruby2erl(env, mrb, k); ERL_NIF_TERM value = mruby2erl(env, mrb, mrb_hash_get(mrb, o, k)); list = enif_make_list_cell(env, enif_make_tuple2(env, key, value), list); } return enif_make_tuple1(env, list); }
static ERL_NIF_TERM grow_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { union { void* vp; struct make_term_info* p; }mti; ERL_NIF_TERM term; if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp) || (argc>2 && !enif_get_uint(env,argv[2], &mti.p->n))) { return enif_make_badarg(env); } mti.p->caller_env = env; mti.p->other_term = argv[1]; mti.p->n %= num_of_make_funcs(); make_term_n(mti.p, mti.p->n++, &term); mti.p->blob = enif_make_list_cell(mti.p->dst_env, term, mti.p->blob); return atom_ok; }
ERL_NIF_TERM PCudaFloatBuffer::intersect(ErlNifEnv *env, PCudaBuffer *otherBuffer) { ERL_NIF_TERM retval = enif_make_list(env, 0); std::vector<double> intersection; if (otherBuffer->type() == BUF_TYPE_FLOAT) { PCudaFloatBuffer *other = (PCudaFloatBuffer *) otherBuffer; pcuda_float_intersection(this->data, other->data, &intersection); if (intersection.size() > 0) { for (std::vector<double>::iterator iter = intersection.end(); iter != intersection.begin();) { --iter; retval = enif_make_list_cell(env, enif_make_double(env, *iter), retval); } } } return retval; }
ERL_NIF_TERM split_index(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary in; cloner* ptr; UBreakIterator* iter; int pos; UErrorCode status = U_ZERO_ERROR; ERL_NIF_TERM head, tail; if (argc != 2) return enif_make_badarg(env); /* Last argument must be a binary */ if (!(enif_inspect_binary(env, argv[1], &in) && enif_get_resource(env, argv[0], iterator_type, (void**) &ptr))) { return enif_make_badarg(env); } iter = (UBreakIterator*) cloner_get(ptr); CHECK_RES(env, iter); if (iter == NULL) { return enif_make_badarg(env); } ubrk_setText(iter, (UChar*) in.data, TO_ULEN(in.size), &status); CHECK(env, status); tail = enif_make_list(env, 0); pos = (int) ubrk_last(iter); while ((pos != UBRK_DONE) && (pos != 0)) { if (is_valid_elem(ptr, iter)) { head = enif_make_int(env, pos); tail = enif_make_list_cell(env, head, tail); } /* get the next elem. */ pos = (int) ubrk_previous(iter); }; return tail; }
/** * Generate a list if locales. */ ERL_NIF_TERM generate_available(ErlNifEnv* env, avail_fun fun, int32_t i) { ERL_NIF_TERM head, tail; const char* locale; tail = enif_make_list(env, 0); while (i) { i--; locale = fun(i); head = enif_make_atom(env, locale); tail = enif_make_list_cell(env, head, tail); } return tail; }
static ERL_NIF_TERM i18n_info(ErlNifEnv* env, int /*argc*/, const ERL_NIF_TERM /*argv*/[]) { #if I18N_INFO ERL_NIF_TERM head, tail; tail = enif_make_list(env, 0); #if I18N_SEARCH head = enif_make_tuple2(env, ATOM_SEARCH, i18n_search_info(env)); tail = enif_make_list_cell(env, head, tail); #endif return tail; #else return enif_make_list(env, 0); #endif }
static ERL_NIF_TERM xfer2_1(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int status, val, i; struct spi_ioc_transfer xfer; uint8_t *txbuf, *rxbuf; unsigned int length; ERL_NIF_TERM cell, head, tail, res, list; if (state.fd == -1) return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, "device closed", ERL_NIF_LATIN1)); if (argc != 1 || !enif_is_list(env, argv[0])) return enif_make_badarg(env); if (!enif_get_list_length(env, argv[0], &length)) return enif_make_badarg(env); txbuf = (uint8_t *) enif_alloc(sizeof(uint8_t) * length); rxbuf = (uint8_t *) enif_alloc(sizeof(uint8_t) * length); list = argv[0]; for (i = 0; enif_get_list_cell(env, list, &head, &tail); ++i, list = tail) { if (!enif_get_int(env, head, &val)) { return enif_make_badarg(env); } txbuf[i] = val; } xfer.tx_buf = (unsigned long) txbuf; xfer.rx_buf = (unsigned long) rxbuf; xfer.len = length; status = ioctl(state.fd, SPI_IOC_MESSAGE(1), &xfer); if (status < 0) { enif_free(txbuf); enif_free(rxbuf); return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, "spi ioc message", ERL_NIF_LATIN1)); } list = enif_make_list(env, 0); for (i = length - 1; i >= 0; --i) { cell = enif_make_uint(env, (unsigned int) rxbuf[i]); list = enif_make_list_cell(env, cell, list); } res = enif_make_tuple2(env, enif_make_atom(env, "ok"), list); enif_free(txbuf); enif_free(rxbuf); return res; }
ERL_NIF_TERM date_get_fields(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { UErrorCode status = U_ZERO_ERROR; UCalendar* cal; cloner* ptr; double date; ERL_NIF_TERM res; ERL_NIF_TERM head, tail, out; unsigned int count; if(!((argc == 3) && enif_get_resource(env, argv[0], calendar_type, (void**) &ptr) && enif_get_double(env, argv[1], &date) && enif_get_list_length(env, argv[2], &count))) { return enif_make_badarg(env); } cal = (UCalendar*) cloner_get(ptr); CHECK_RES(env, cal); ucal_setMillis(cal, (UDate) date, &status); CHECK(env, status); tail = argv[2]; out = enif_make_list(env, 0); while (enif_get_list_cell(env, tail, &head, &tail)) { /* Set an attribute start */ res = do_date_get_field(env, cal, head, status); CHECK(env, status); out = enif_make_list_cell(env, enif_make_tuple2(env, head, res), out); /* Set an attribute end */ } return out; }
ERL_NIF_TERM vert_virNodeDeviceListCaps(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { VERT_RESOURCE *dp = NULL; char **names = NULL; int maxnames = 0; int n = 0; int rv = 0; ERL_NIF_TERM cap = {0}; VERT_GET_RESOURCE(0, dp, VERT_RES_NODEDEVICE); VERT_GET_INT(1, maxnames); names = calloc(maxnames, sizeof(char *)); if (names == NULL) return error_tuple(env, atom_enomem); rv = virNodeDeviceListCaps(dp->res, names, maxnames); if (rv < 0) goto ERR; cap = enif_make_list(env, 0); for (n = 0; n < rv; n++) { cap = enif_make_list_cell(env, enif_make_string(env, names[n], ERL_NIF_LATIN1), cap); } free(names); return enif_make_tuple2(env, atom_ok, cap); ERR: free(names); return verterr(env); }
static ERL_NIF_TERM make_blob(ErlNifEnv* caller_env, ErlNifEnv* dst_env, ERL_NIF_TERM other_term) { PrivData* priv = (PrivData*) enif_priv_data(caller_env); ERL_NIF_TERM term, list; int n = 0; struct make_term_info mti; mti.caller_env = caller_env; mti.dst_env = dst_env; mti.reuse_push = 0; mti.reuse_pull = 0; mti.resource_type = priv->rt_arr[0].t; mti.other_term = other_term; list = enif_make_list(dst_env, 0); while (make_term_n(&mti, n++, &term)) { list = enif_make_list_cell(dst_env, term, list); } return list; }
static ERL_NIF_TERM nif_socket_levels(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { const struct procket_define *p = NULL; ERL_NIF_TERM list = {0}; list = enif_make_list(env, 0); for (p = procket_socket_level; p->key != NULL; p++) { list = enif_make_list_cell( env, enif_make_tuple2( env, enif_make_atom(env, p->key), enif_make_uint(env, p->val) ), list); } return list; }
int enc_done(Encoder* e, ERL_NIF_TERM* value) { ERL_NIF_TERM last; if(e->iolen == 0) { return enc_result(e, value); } if(e->i > 0 ) { if(!enc_result(e, &last)) { return 0; } e->iolist = enif_make_list_cell(e->env, last, e->iolist); e->iolen++; } *value = e->iolist; return 1; }
int enc_map_to_ejson(ErlNifEnv* env, ERL_NIF_TERM map, ERL_NIF_TERM* out) { ErlNifMapIterator iter; size_t size; ERL_NIF_TERM list; ERL_NIF_TERM tuple; ERL_NIF_TERM key; ERL_NIF_TERM val; if(!enif_get_map_size(env, map, &size)) { return 0; } list = enif_make_list(env, 0); if(size == 0) { *out = enif_make_tuple1(env, list); return 1; } if(!enif_map_iterator_create(env, map, &iter, ERL_NIF_MAP_ITERATOR_HEAD)) { return 0; } do { if(!enif_map_iterator_get_pair(env, &iter, &key, &val)) { enif_map_iterator_destroy(env, &iter); return 0; } tuple = enif_make_tuple2(env, key, val); list = enif_make_list_cell(env, tuple, list); } while(enif_map_iterator_next(env, &iter)); enif_map_iterator_destroy(env, &iter); *out = enif_make_tuple1(env, list); return 1; }
static enum CXChildVisitResult visitor_struct_cb(CXCursor cursor, CXCursor parent, CXClientData client_data) { ERL_NIF_TERM name; ERL_NIF_TERM typename; CXString tmp; CXType type; ERL_NIF_TERM etmp; unsigned len; SubData *data = (SubData*)client_data; ErlNifEnv *env = data->env; switch (clang_getCursorKind(cursor)) { case CXCursor_FieldDecl: { enif_get_list_length(env, data->data, &len); tmp = clang_getCursorSpelling(cursor); name = enif_make_string(env, clang_getCString(tmp), ERL_NIF_LATIN1); clang_disposeString(tmp); type = clang_getCursorType(cursor); tmp = clang_getTypeSpelling(type); typename = enif_make_string(env, clang_getCString(tmp), ERL_NIF_LATIN1); data->types = enif_make_list_cell(env, typename, data->types); clang_disposeString(tmp); etmp = enif_make_tuple4(env, enif_make_atom(env, "field"), name, typename, enif_make_uint(env, len)); data->data = enif_make_list_cell(env, etmp, data->data); return CXChildVisit_Continue; } default: { return CXChildVisit_Continue; } } }
static ERL_NIF_TERM nif_constants(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { const struct SERCTL_DEF *p = NULL; ERL_NIF_TERM list = {0}; list = enif_make_list(env, 0); for (p = serctl_const; p->key != NULL; p++) { list = enif_make_list_cell( env, enif_make_tuple2( env, enif_make_atom(env, p->key), enif_make_uint(env, p->val) ), list); } return list; }
static ERL_NIF_TERM xfer_2(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { unsigned int channel, length; int result, i, val; uint8_t *buffer; ERL_NIF_TERM cell, head, tail, list; if (argc < 2 || !enif_is_number(env, argv[0]) || !enif_is_list(env, argv[1])) { return enif_make_badarg(env); } if (!enif_get_uint(env, argv[0], &channel) || channel < 0 || channel > 1) { return enif_make_badarg(env); } if (!enif_get_list_length(env, argv[1], &length) || length == 0) { return enif_make_badarg(env); } buffer = (uint8_t *) enif_alloc(sizeof(uint8_t) * length); list = argv[1]; for (i = 0; enif_get_list_cell(env, list, &head, &tail); ++i, list = tail) { if (!enif_get_int(env, head, &val)) { return enif_make_badarg(env); } buffer[i] = val; } result = wiringPiSPIDataRW(channel, buffer, length); if (result == -1) { result = errno; enif_free(buffer); return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_int(env, result)); } list = enif_make_list(env, 0); for (i = length - 1; i >= 0; --i) { cell = enif_make_uint(env, (unsigned int) buffer[i]); list = enif_make_list_cell(env, cell, list); } enif_free(buffer); return enif_make_tuple2(env, enif_make_atom(env, "ok"), list); }
int on_message_begin (http_parser *parser) { parser_data *data = (parser_data *)parser->data; ERL_NIF_TERM method = k_atom_error; switch(parser->method) { case HTTP_DELETE: method = k_atom_method_delete; break; case HTTP_GET: method = k_atom_method_get; break; case HTTP_HEAD: method = k_atom_method_head; break; case HTTP_POST: method = k_atom_method_post; break; case HTTP_PUT: method = k_atom_method_put; break; case HTTP_CONNECT: method = k_atom_method_connect; break; case HTTP_OPTIONS: method = k_atom_method_options; break; case HTTP_TRACE: method = k_atom_method_trace; break; case HTTP_COPY: method = k_atom_method_copy; break; case HTTP_LOCK: method = k_atom_method_lock; break; case HTTP_MKCOL: method = k_atom_method_mkcol; break; case HTTP_MOVE: method = k_atom_method_move; break; case HTTP_PROPFIND: method = k_atom_method_propfind; break; case HTTP_PROPPATCH: method = k_atom_method_proppatch; break; case HTTP_SEARCH: method = k_atom_method_search; break; case HTTP_UNLOCK: method = k_atom_method_unlock; break; case HTTP_REPORT: method = k_atom_method_report; break; case HTTP_MKACTIVITY: method = k_atom_method_mkactivity; break; case HTTP_CHECKOUT: method = k_atom_method_checkout; break; case HTTP_MERGE: method = k_atom_method_merge; break; case HTTP_MSEARCH: method = k_atom_method_msearch; break; case HTTP_NOTIFY: method = k_atom_method_notify; break; case HTTP_SUBSCRIBE: method = k_atom_method_subscribe; break; case HTTP_UNSUBSCRIBE: method = k_atom_method_unsubscribe; break; case HTTP_PATCH: method = k_atom_method_patch; break; case HTTP_PURGE: method = k_atom_method_purge; break; } data->result = enif_make_list_cell(data->env, enif_make_tuple2(data->env, k_atom_method, method), data->result); return 0; }
posix_errno_t efile_list_dir(ErlNifEnv *env, const efile_path_t *path, ERL_NIF_TERM *result) { ERL_NIF_TERM list_head; struct dirent *dir_entry; DIR *dir_stream; dir_stream = opendir((const char*)path->data); if(dir_stream == NULL) { posix_errno_t saved_errno = errno; *result = enif_make_list(env, 0); return saved_errno; } list_head = enif_make_list(env, 0); dir_entry = readdir(dir_stream); while(dir_entry != NULL) { int name_length = strlen(dir_entry->d_name); if(!is_ignored_name(name_length, dir_entry->d_name)) { unsigned char *name_bytes; ERL_NIF_TERM name_term; name_bytes = enif_make_new_binary(env, name_length, &name_term); sys_memcpy(name_bytes, dir_entry->d_name, name_length); list_head = enif_make_list_cell(env, name_term, list_head); } dir_entry = readdir(dir_stream); } (*result) = list_head; closedir(dir_stream); return 0; }
static ERL_NIF_TERM make_call_history(ErlNifEnv* env, CallInfo** headp) { ERL_NIF_TERM list = enif_make_list(env, 0); /* NIL */ while (*headp != NULL) { CallInfo* call = *headp; ERL_NIF_TERM func_term = enif_make_atom(env,call->func_name); ERL_NIF_TERM tpl; if (call->arg != NULL) { ERL_NIF_TERM arg_bin; memcpy(enif_make_new_binary(env, call->arg_sz, &arg_bin), call->arg, call->arg_sz); func_term = enif_make_tuple2(env, func_term, arg_bin); } tpl = enif_make_tuple4(env, func_term, enif_make_int(env,call->lib_ver), enif_make_int(env,call->static_cntA), enif_make_int(env,call->static_cntB)); list = enif_make_list_cell(env, tpl, list); *headp = call->next; enif_free(call); } return list; }
static ERL_NIF_TERM nif_pcap_findalldevs(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { pcap_if_t *alldevsp = NULL; char errbuf[PCAP_ERRBUF_SIZE] = {0}; ERL_NIF_TERM dev = {0}; if (pcap_findalldevs(&alldevsp, errbuf) < 0) return enif_make_tuple2(env, atom_error, enif_make_string(env, errbuf, ERL_NIF_LATIN1)); dev = enif_make_list(env, 0); /* similar to inet:getifaddrs/0, except return binaries * for addresses: * [{"lo", [ * {description, "..."}, * {flag, [loopback]}, * {address, <<>>}, * {netmask, <<>>}, * {broaddr, <<>>}, * {dstaddr, <<>>} * ]}] */ for ( ; alldevsp != NULL; alldevsp = alldevsp->next) { ERL_NIF_TERM attr = {0}; ERL_NIF_TERM flags = {0}; pcap_addr_t *sa = NULL; /* interface attributes */ attr = enif_make_list(env, 0); /* interface flags */ flags = enif_make_list(env, 0); if (alldevsp->description) attr = enif_make_list_cell(env, enif_make_tuple2(env, atom_description, enif_make_string(env, alldevsp->description, ERL_NIF_LATIN1)), attr); if (alldevsp->flags & PCAP_IF_LOOPBACK) { flags = enif_make_list_cell(env, atom_loopback, flags); attr = enif_make_list_cell(env, enif_make_tuple2(env, atom_flag, flags), attr); } for (sa = alldevsp->addresses; sa != NULL; sa = sa->next) { if (sa->addr == NULL) continue; switch (sa->addr->sa_family) { case PF_INET: case PF_INET6: break; default: /* unsupported */ continue; } /* address */ MAKE_ADDR(env, attr, addr, sa); /* netmask */ MAKE_ADDR(env, attr, netmask, sa); /* broadaddr */ MAKE_ADDR(env, attr, broadaddr, sa); /* dstaddr */ MAKE_ADDR(env, attr, dstaddr, sa); } dev = enif_make_list_cell(env, enif_make_tuple2(env, enif_make_string(env, alldevsp->name, ERL_NIF_LATIN1), attr), dev); } pcap_freealldevs(alldevsp); return enif_make_tuple2(env, atom_ok, dev); ERR: pcap_freealldevs(alldevsp); /* MAKE_ADDR macro */ return enif_make_tuple2(env, atom_error, atom_enomem); }
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); }
static ERL_NIF_TERM gencall(ErlNifEnv *env, lua_State *L, const ERL_NIF_TERM arg_func, const ERL_NIF_TERM arg_fmt, const ERL_NIF_TERM arg_list) { char buff_str[STACK_STRING_BUFF]; char buff_fmt[STACK_STRING_BUFF]; char buff_fun[STACK_STRING_BUFF/2]; unsigned input_len=0; unsigned output_len=0; if(enif_get_string(env, arg_func, buff_fun, STACK_STRING_BUFF/2, ERL_NIF_LATIN1)<=0){ return enif_make_badarg(env); } if(enif_get_string(env, arg_fmt, buff_fmt, STACK_STRING_BUFF, ERL_NIF_LATIN1)<=0){ return enif_make_badarg(env); } if(!enif_is_list(env, arg_list)){ return enif_make_badarg(env); } input_len = strchr(buff_fmt, ':') - buff_fmt; output_len = strlen(buff_fmt) - input_len -1; // printf("input args %d output args %d fun %s\n", input_len, output_len, buff_fun); ERL_NIF_TERM head,tail,list; list=arg_list; int i=0, status = 0, ret; ERL_NIF_TERM return_list = enif_make_list(env, 0); lua_getglobal(L, buff_fun); const char *error; while(buff_fmt[i]!='\0') { // printf("i:%d %c\n", i, buff_fmt[i]); if(status==0 && buff_fmt[i]!=':') { ret = enif_get_list_cell(env, list, &head, &tail); if(!ret) { error = FMT_AND_LIST_NO_MATCH; goto error; } list=tail; } switch(buff_fmt[i]) { case ':' : status=1; if(lua_pcall(L, input_len, output_len,0) != LUA_OK) { error = lua_tostring(L, -1); lua_pop(L,1); return enif_make_tuple2(env, atom_error, enif_make_string(env, error, ERL_NIF_LATIN1)); } //output_len = - 1; break; case 'i': if( status == 0) { int input_int; ret = enif_get_int(env, head, &input_int); // printf("input %d\n", input_int); if(!ret) { error = FMT_AND_LIST_NO_MATCH; goto error; } lua_pushinteger(L, input_int); } else if ( status==1 ){ int isnum; int n = lua_tointegerx(L, -1, &isnum); if(!isnum){ error = FMT_AND_LIST_NO_MATCH; goto error; } // printf("output %d %d\n", output_len, n); return_list = enif_make_list_cell(env, enif_make_int(env, n), return_list); lua_pop(L,1); output_len--; } break; case 's': if( status == 0) { ret = enif_get_string(env, head, buff_str, STACK_STRING_BUFF, ERL_NIF_LATIN1); if(ret<=0) { error = FMT_AND_LIST_NO_MATCH; goto error; } lua_pushstring(L, buff_str); } else if ( status==1 ) { const char *s = lua_tostring(L, -1); if (s==NULL) { error = FMT_AND_RET_NO_MATCH; goto error; } // printf("output %d %s\n", output_len, s); return_list = enif_make_list_cell(env, enif_make_string(env, s, ERL_NIF_LATIN1), return_list); lua_pop(L,1); output_len--; } break; /* case 'd': */ /* break; */ /* case 'b': */ /* break; */ default: error = FMT_WRONG; goto error; break; } i++; } return enif_make_tuple2(env, atom_ok, return_list); error: // printf("in error \n"); // @fix clean the heap var. // before call, pop the call if(status ==0 ) { lua_pop(L, 1); } else if(output_len>0) { lua_pop(L, output_len); } return make_error_tuple(env, error); }
ERL_NIF_TERM encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { Encoder enc; Encoder* e = &enc; ErlNifBinary bin; ERL_NIF_TERM ret; ERL_NIF_TERM stack; ERL_NIF_TERM curr; ERL_NIF_TERM item; const ERL_NIF_TERM* tuple; int arity; ErlNifSInt64 lval; double dval; if(argc != 2) { return enif_make_badarg(env); } if(!enc_init(e, env, argv[1], &bin)) { return enif_make_badarg(env); } stack = enif_make_list(env, 1, argv[0]); while(!enif_is_empty_list(env, stack)) { if(!enif_get_list_cell(env, stack, &curr, &stack)) { ret = enc_error(e, "internal_error"); goto done; } if(enif_is_identical(curr, e->atoms->ref_object)) { if(!enif_get_list_cell(env, stack, &curr, &stack)) { ret = enc_error(e, "internal_error"); goto done; } if(enif_is_empty_list(env, curr)) { if(!enc_end_object(e)) { ret = enc_error(e, "internal_error"); goto done; } continue; } if(!enif_get_list_cell(env, curr, &item, &curr)) { ret = enc_error(e, "internal_error"); goto done; } if(!enif_get_tuple(env, item, &arity, &tuple)) { ret = enc_error(e, "invalid_object_pair"); goto done; } if(arity != 2) { ret = enc_error(e, "invalid_object_pair"); goto done; } if(!enc_comma(e)) { ret = enc_error(e, "internal_error"); goto done; } if(!enc_string(e, tuple[0])) { ret = enc_error(e, "invalid_object_key"); goto done; } if(!enc_colon(e)) { ret = enc_error(e, "internal_error"); goto done; } stack = enif_make_list_cell(env, curr, stack); stack = enif_make_list_cell(env, e->atoms->ref_object, stack); stack = enif_make_list_cell(env, tuple[1], stack); } else if(enif_is_identical(curr, e->atoms->ref_array)) { if(!enif_get_list_cell(env, stack, &curr, &stack)) { ret = enc_error(e, "internal_error"); goto done; } if(enif_is_empty_list(env, curr)) { if(!enc_end_array(e)) { ret = enc_error(e, "internal_error"); goto done; } continue; } if(!enc_comma(e)) { ret = enc_error(e, "internal_error"); goto done; } if(!enif_get_list_cell(env, curr, &item, &curr)) { ret = enc_error(e, "internal_error"); goto done; } 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) { 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"); goto done; } } else if(enif_compare(curr, e->atoms->atom_false) == 0) { if(!enc_literal(e, "false", 5)) { ret = enc_error(e, "false"); goto done; } } else if(enif_is_binary(env, curr)) { if(!enc_string(e, curr)) { ret = enc_error(e, "invalid_string"); goto done; } } else if(enif_is_atom(env, curr)) { if(!enc_string(e, curr)) { ret = enc_error(e, "invalid_string"); goto done; } } else if(enif_get_int64(env, curr, &lval)) { if(!enc_long(e, lval)) { ret = enc_error(e, "internal_error"); goto done; } } else if(enif_get_double(env, curr, &dval)) { if(!enc_double(e, dval)) { ret = enc_error(e, "internal_error"); goto done; } } else if(enif_get_tuple(env, curr, &arity, &tuple)) { if(arity != 1) { ret = enc_error(e, "invalid_ejson"); goto done; } if(!enif_is_list(env, tuple[0])) { ret = enc_error(e, "invalid_object"); goto done; } if(!enc_start_object(e)) { ret = enc_error(e, "internal_error"); goto done; } if(enif_is_empty_list(env, tuple[0])) { if(!enc_end_object(e)) { ret = enc_error(e, "internal_error"); goto done; } continue; } if(!enif_get_list_cell(env, tuple[0], &item, &curr)) { ret = enc_error(e, "internal_error"); goto done; } if(!enif_get_tuple(env, item, &arity, &tuple)) { ret = enc_error(e, "invalid_object_member"); goto done; } if(arity != 2) { ret = enc_error(e, "invalid_object_member_arity"); goto done; } if(!enc_string(e, tuple[0])) { ret = enc_error(e, "invalid_object_member_key"); goto done; } if(!enc_colon(e)) { ret = enc_error(e, "internal_error"); goto done; } stack = enif_make_list_cell(env, curr, stack); stack = enif_make_list_cell(env, e->atoms->ref_object, stack); stack = enif_make_list_cell(env, tuple[1], stack); } else if(enif_is_list(env, curr)) { if(!enc_start_array(e)) { ret = enc_error(e, "internal_error"); goto done; } if(enif_is_empty_list(env, curr)) { if(!enc_end_array(e)) { ret = enc_error(e, "internal_error"); goto done; } continue; } if(!enif_get_list_cell(env, curr, &item, &curr)) { ret = enc_error(e, "internal_error"); goto done; } 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(!enc_unknown(e, curr)) { ret = enc_error(e, "internal_error"); goto done; } } } if(!enc_done(e, &item)) { ret = enc_error(e, "internal_error"); goto done; } if(e->iolen == 0) { ret = item; } else { ret = enif_make_tuple2(env, e->atoms->atom_partial, item); } done: enc_destroy(e); return ret; }