static ERL_NIF_TERM do_write(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { static PortMidiStream ** stream; ErlNifResourceType* streamType = (ErlNifResourceType*)enif_priv_data(env); if(!enif_get_resource(env, argv[0], streamType, (PortMidiStream **) &stream)) { return enif_make_badarg(env); } ERL_NIF_TERM erlMessages = argv[1]; const ERL_NIF_TERM * erlEvent; const ERL_NIF_TERM * erlMessage; ERL_NIF_TERM erlTuple; unsigned int numOfMessages; int tupleSize; enif_get_list_length(env, erlMessages, &numOfMessages); PmEvent events[numOfMessages]; long int status, note, velocity, timestamp; for(unsigned int i = 0; i < numOfMessages; i++) { enif_get_list_cell(env, erlMessages, &erlTuple, &erlMessages); enif_get_tuple(env, erlTuple, &tupleSize, &erlEvent); enif_get_tuple(env, erlEvent[0], &tupleSize, &erlMessage); enif_get_long(env, erlMessage[0], &status); enif_get_long(env, erlMessage[1], ¬e); enif_get_long(env, erlMessage[2], &velocity); enif_get_long(env, erlEvent[1], ×tamp); PmEvent event; event.message = Pm_Message(status, note, velocity); event.timestamp = timestamp; events[i] = event; } PmError writeError; writeError = Pm_Write(*stream, events, numOfMessages); if (writeError == pmNoError) { return enif_make_atom(env, "ok"); } const char * writeErrorMsg; writeErrorMsg = Pm_GetErrorText(writeError); return enif_make_tuple2( env, enif_make_atom(env, "error"), enif_make_string(env, writeErrorMsg, ERL_NIF_LATIN1) ); }
static ERL_NIF_TERM _listener (ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { CAN_handle* handle; ErlNifPid pid = { 0 }; // NOTE: breaking opaque type! enif_get_resource(env, argv[0], CAN_handle_type, (void**) &handle); if (handle->threaded) // there is a thread already and some pid! { pid = handle->receiver; } if (!enif_get_local_pid(env, argv[1], &handle->receiver)) // NOTE: use lock if pid type is structural! { handle->threaded = 0; return enif_make_badarg(env); } else { enif_get_uint(env, argv[2], &handle->chunk_size); enif_get_long(env, argv[3], &handle->timeout); if (!handle->threaded) // a thread was not created already { if (enif_thread_create("can_reading_thread", &handle->tid, _reading_thread, handle, 0)) { handle->threaded = 0; return enif_make_int(env, -1004); } } } return pid.pid ? enif_make_pid(env, &pid) : enif_make_int(env, 0); }
static ERL_NIF_TERM emmap_position(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { mhandle *handle; long position; long relpos; if (argc==3 && enif_get_resource(env, argv[0], MMAP_RESOURCE, (void**)&handle) && enif_get_long(env, argv[2], &relpos) && (argv[1] == ATOM_CUR || argv[1] == ATOM_BOF || argv[1] == ATOM_EOF)) { RW_LOCK; if (argv[1] == ATOM_BOF) { position = 0L + relpos; } else if (argv[1] == ATOM_CUR) { position = handle->position + relpos; } else if (argv[1] == ATOM_EOF) { position = handle->len - relpos; } if (position < 0L || ((unsigned long)position) > handle->len) { RW_UNLOCK; return enif_make_badarg(env); } handle->position = position; RW_UNLOCK; return enif_make_tuple2(env, ATOM_OK, enif_make_ulong(env, position)); } else { return enif_make_badarg(env); } }
static ERL_NIF_TERM make_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { union { void* p; long l; } data; if (!enif_get_long(env, argv[0], &data.l)) { return enif_make_badarg(env); } return enif_make_resource(env, data.p); }
static ERL_NIF_TERM exmagick_crop (ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { Image* cropped_image; RectangleInfo rect; exm_resource_t *resource; EXM_INIT; ErlNifResourceType *type = (ErlNifResourceType *) enif_priv_data(env); if (0 == enif_get_resource(env, argv[0], type, (void **) &resource)) { EXM_FAIL(ehandler, "invalid handle"); } if (resource->image == NULL) { EXM_FAIL(ehandler, "image not loaded"); } /* build rectangle */ if (0 == enif_get_long(env, argv[1], &rect.x)) { EXM_FAIL(ehandler, "x0: bad argument"); } if (0 == enif_get_long(env, argv[2], &rect.y)) { EXM_FAIL(ehandler, "y0: bad argument"); } if (0 == enif_get_ulong(env, argv[3], &rect.width)) { EXM_FAIL(ehandler, "width: bad argument"); } if (0 == enif_get_ulong(env, argv[4], &rect.height)) { EXM_FAIL(ehandler, "height: bad argument"); } /* actually crops image */ cropped_image = CropImage(resource->image, &rect, &resource->e_info); if (cropped_image == NULL) { CatchException(&resource->e_info); EXM_FAIL(ehandler, resource->e_info.reason); } DestroyImage(resource->image); resource->image = cropped_image; return(enif_make_tuple2(env, enif_make_atom(env, "ok"), argv[0])); ehandler: return(enif_make_tuple2(env, enif_make_atom(env, "error"), exmagick_make_utf8str(env, errmsg))); }
static int test_long(ErlNifEnv* env, long i1) { long i2 = 0; ERL_NIF_TERM int_term = enif_make_long(env, i1); if (!enif_get_long(env,int_term, &i2) || i1 != i2) { fprintf(stderr, "test_long(%ld) ...FAILED i2=%ld\r\n", i1, i2); return 0; } return 1; }
static ERL_NIF_TERM hash(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary bin; long seed; int hash; if (enif_inspect_binary(env, argv[0], &bin)) { int res = enif_get_long(env, argv[1], &seed); hash = fnv_hash(bin.data, bin.size, seed); return enif_make_int(env, hash); } return enif_make_atom(env, "badarg"); }
// convert an erlang term to a python object // return None if the type can't be converted static PyObject* pynerl_term_to_obj(ErlNifEnv* env, ERL_NIF_TERM term) { int vint; Py_ssize_t arity, i; long int vlong; double vdouble; char buff[BUFF_SIZE]; PyObject* obj; ERL_NIF_TERM list, head, tail; const ERL_NIF_TERM *terms; // TODO: add more types if (enif_get_long(env, term, &vlong)) { obj = PyLong_FromLong(vlong); } else if (enif_get_double(env, term, &vdouble)) { obj = PyFloat_FromDouble(vlong); } else if (enif_is_empty_list(env, term)) { obj = PyList_New(0); } else if (enif_get_tuple(env, term, &vint, &terms)) { arity = vint; obj = PyTuple_New(arity); for (i = 0; i < arity; i++) { PyTuple_SetItem(obj, i, pynerl_term_to_obj(env, terms[(int)i])); } } else if (enif_is_identical(term, enif_make_atom(env, "true"))) { obj = Py_True; } else if (enif_is_identical(term, enif_make_atom(env, "false"))) { obj = Py_False; } else if (enif_get_string(env, term, buff, BUFF_SIZE, ERL_NIF_LATIN1)) { obj = PyUnicode_FromString(buff); } else if (enif_get_list_cell(env, term, &head, &tail)) { obj = PyList_New(0); list = term; while (enif_get_list_cell(env, list, &head, &tail)) { PyList_Append(obj, pynerl_term_to_obj(env, head)); list = tail; } } else { obj = Py_None; } return obj; }
void PCudaFloatBuffer::write(ErlNifEnv *env, ERL_NIF_TERM data) { ERL_NIF_TERM head; double value; long lvalue; while (enif_get_list_cell(env, data, &head, &data)) { if (enif_get_double(env, head, &value)) { this->data->push_back(value); }else if (enif_get_long(env, head, &lvalue)) { this->data->push_back((double)lvalue); } } }
static ERL_NIF_TERM _recv (ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { CAN_handle* handle; unsigned int chunk_size; long timeout; ERL_NIF_TERM result; enif_get_resource(env, argv[0], CAN_handle_type, (void**) &handle); enif_get_uint(env, argv[1], &chunk_size); enif_get_long(env,argv[2], &timeout); result = _receive_can_messages(env, handle, chunk_size, timeout); return result; }
double fetch_double(ErlNifEnv* env, ERL_NIF_TERM* items) { ERL_NIF_TERM head; // Fetch head if possible if (! enif_get_list_cell(env, *items, &head, items)) return 0.0; long i; double d; if(enif_get_double(env, head, &d)) return d; if(enif_get_long(env, head, &i)) return (double) i; return 0.0; };
static ERL_NIF_TERM alloc_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary data_bin; union { ErlNifResourceType* t; long l;} type; union { void* p; long l;} data; if (!enif_get_long(env, argv[0], &type.l) || !enif_inspect_binary(env, argv[1], &data_bin) || (data.p = enif_alloc_resource(type.t, data_bin.size))==NULL) { return enif_make_badarg(env); } memcpy(data.p, data_bin.data, data_bin.size); return enif_make_long(env, data.l); }
void* cb_mtouch_args(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { mtouch_args_t* args = (mtouch_args_t*)enif_alloc(sizeof(mtouch_args_t)); ERL_NIF_TERM* currKey; ERL_NIF_TERM tail; ErlNifBinary key_binary; if (!enif_get_list_length(env, argv[0], &args->numkeys)) goto error0; args->keys = malloc(sizeof(char*) * args->numkeys); args->nkeys = malloc(sizeof(size_t) * args->numkeys); currKey = malloc(sizeof(ERL_NIF_TERM)); tail = argv[0]; int i = 0; while(0 != enif_get_list_cell(env, tail, currKey, &tail)) { if (!enif_inspect_iolist_as_binary(env, *currKey, &key_binary)) goto error1; args->keys[i] = malloc(sizeof(char) * key_binary.size); memcpy(args->keys[i], key_binary.data, key_binary.size); args->nkeys[i] = key_binary.size; i++; } args->exp = malloc(sizeof(int64_t) * args->numkeys); tail = argv[1]; int i2 = 0; while(0 != enif_get_list_cell(env, tail, currKey, &tail)) { if (!enif_get_long(env, *currKey, &args->exp[i2])) goto error2; i2++; } free(currKey); return (void*)args; int f = 0; error2: free(args->exp); error1: for(f = 0; f < i; f++) { free(args->keys[f]); } free(args->keys); free(args->nkeys); error0: enif_free(args); return NULL; }
static ERL_NIF_TERM exmagick_image_thumb (ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { long width, height; Image* thumb; exm_resource_t *resource; EXM_INIT; ErlNifResourceType *type = (ErlNifResourceType *) enif_priv_data(env); if (0 == enif_get_resource(env, argv[0], type, (void **) &resource)) { EXM_FAIL(ehandler, "invalid handle"); } if (resource->image == NULL) { EXM_FAIL(ehandler, "image not loaded"); } if (0 == enif_get_long(env, argv[1], &width)) { EXM_FAIL(ehandler, "width: bad argument"); } if (0 == enif_get_long(env, argv[2], &height)) { EXM_FAIL(ehandler, "height: bad argument"); } thumb = ThumbnailImage(resource->image, width, height, &resource->e_info); if (thumb == NULL) { CatchException(&resource->e_info); EXM_FAIL(ehandler, resource->e_info.reason); } DestroyImage(resource->image); resource->image = thumb; return(enif_make_tuple2(env, enif_make_atom(env, "ok"), argv[0])); ehandler: return(enif_make_tuple2(env, enif_make_atom(env, "error"), exmagick_make_utf8str(env, errmsg))); }
static ERL_NIF_TERM make_new_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary data_bin; union { ErlNifResourceType* t; long l;} type; void* data; ERL_NIF_TERM ret; if (!enif_get_long(env, argv[0], &type.l) || !enif_inspect_binary(env, argv[1], &data_bin) || (data = enif_alloc_resource(type.t, data_bin.size))==NULL) { return enif_make_badarg(env); } ret = enif_make_resource(env, data); memcpy(data, data_bin.data, data_bin.size); enif_release_resource(data); return ret; }
static inline int push_nif_number(lua_State* lua, ERL_NIF_TERM message, ErlNifEnv* env) { const int top = lua_gettop(lua); int result = 0; int intval; unsigned int uintval; long longval; unsigned long ulongval; double doubleval; luaL_checkstack(lua, 1, ERROR_STACK_MESSAGE); if(enif_get_int(env, message, &intval)) { lua_pushnumber(lua, (double) intval); result = 1; } else if(enif_get_uint(env, message, &uintval)) { lua_pushnumber(lua, (double) uintval); result = 1; } else if(enif_get_long(env, message, &longval)) { lua_pushnumber(lua, (double) longval); result = 1; } else if(enif_get_ulong(env, message, &ulongval)) { lua_pushnumber(lua, (double) ulongval); result = 1; } else if(enif_get_double(env, message, &doubleval)) { lua_pushnumber(lua, (double) doubleval); result = 1; } assert(lua_gettop(lua) == top+result); return result; }
static ERL_NIF_TERM get_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary data_bin; union { ErlNifResourceType* t; long l; } type; union { void* p; long l; } data; type.t = NULL; if (enif_is_identical(argv[0], atom_binary_resource_type)) { type.t = binary_resource_type; } else { enif_get_long(env, argv[0], &type.l); } if (type.t == NULL || !enif_get_resource(env, argv[1], type.t, &data.p)) { return enif_make_badarg(env); } enif_alloc_binary(enif_sizeof_resource(data.p), &data_bin); memcpy(data_bin.data, data.p, data_bin.size); return enif_make_tuple2(env, enif_make_long(env,data.l), enif_make_binary(env, &data_bin)); }
static ERL_NIF_TERM do_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { char deviceName[MAXBUFLEN]; long latency; ERL_NIF_TERM streamTerm; PortMidiStream **streamAlloc; PmError result; ErlNifResourceType* streamType = (ErlNifResourceType*)enif_priv_data(env); streamAlloc = (PortMidiStream**)enif_alloc_resource(streamType, sizeof(PortMidiStream*)); enif_get_string(env, argv[0], deviceName, MAXBUFLEN, ERL_NIF_LATIN1); enif_get_long(env, argv[1], &latency); if((result = findDevice(streamAlloc, deviceName, OUTPUT, latency)) != pmNoError) { ERL_NIF_TERM reason = enif_make_atom(env, makePmErrorAtom(result)); return enif_make_tuple2(env, enif_make_atom(env, "error"), reason); } streamTerm = enif_make_resource(env, streamAlloc); enif_keep_resource(streamAlloc); return enif_make_tuple2(env, enif_make_atom(env, "ok"), streamTerm); }
ERL_NIF_TERM derive_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ihandle* handle; ERL_NIF_TERM head; ERL_NIF_TERM tail; char fmt[4]; if(enif_get_resource(env, argv[0], EIM_IMAGE_RESOURCE, (void**)&handle) && enif_get_atom_compat(env, argv[1], fmt, 4, ERL_NIF_LATIN1) && enif_get_list_cell(env, argv[2], &head, &tail)) { ErlNifBinary new_binary; size_t new_length; unsigned char *new_blob; do { //todo: error handle int tuplec; const ERL_NIF_TERM* tuple; char type[9]; if(!enif_get_tuple(env, head, &tuplec, &tuple) || !enif_get_atom_compat(env, tuple[0], type, 9, ERL_NIF_LATIN1)) { return enif_make_badarg(env); } long x, y; long width, height; long value; int rotate; char dimension[7]; switch(type[0]) { case 's'://scale if(!enif_get_atom_compat(env, tuple[1], dimension, 7, ERL_NIF_LATIN1) || !enif_get_long(env, tuple[2], &value)) { return enif_make_badarg(env); } if(dimension[0]=='w') { handle->image->scale_width(value); } else if(dimension[0]=='h') { handle->image->scale_height(value); } else { return enif_make_badarg(env); } break; case 'c'://crop if(!enif_get_long(env, tuple[1], &width) || !enif_get_long(env, tuple[2], &height) || !enif_get_long(env, tuple[3], &x) || !enif_get_long(env, tuple[4], &y)) { return enif_make_badarg(env); } handle->image->crop(width, height, x, y); break; case 'm'://max if(!enif_get_atom_compat(env, tuple[1], dimension, 7, ERL_NIF_LATIN1) || !enif_get_long(env, tuple[2], &value)) { return enif_make_badarg(env); } if(dimension[0]=='w') { handle->image->max_width(value); } else if(dimension[0]=='h') { handle->image->max_height(value); } else { return enif_make_badarg(env); } break; case 'f'://fit if(!enif_get_long(env, tuple[1], &width) || !enif_get_long(env, tuple[2], &height)) { return enif_make_badarg(env); } handle->image->fit(width, height); break; case 'r'://rotate if(!enif_get_int(env, tuple[1], &rotate)) { return enif_make_badarg(env); } switch(rotate) { case 1: handle->image->rotate(EIM_ROTATE_90); break; case 2: handle->image->rotate(EIM_ROTATE_180); break; case 3: handle->image->rotate(EIM_ROTATE_270); break; default: return enif_make_badarg(env); }; break; case 'b'://box if(!enif_get_long(env, tuple[1], &width) || !enif_get_long(env, tuple[2], &height)) { return enif_make_badarg(env); } char float_x[7], float_y[7]; char floated; if(enif_get_atom_compat(env, tuple[3], float_x, 7, ERL_NIF_LATIN1)) { if(!enif_get_atom_compat(env, tuple[4], float_y, 7, ERL_NIF_LATIN1)) { return enif_make_badarg(env); } // can actually write top,left instead of left,top if you want // just helps with typos like that. Just works. switch(float_x[0]) { case 'l': floated = EIM_FLOAT_LEFT; break; case 'c': floated = EIM_FLOAT_CENTER; break; case 'r': floated = EIM_FLOAT_RIGHT; break; case 't': floated = EIM_FLOAT_TOP; break; case 'b': floated = EIM_FLOAT_BOTTOM; break; default: return enif_make_badarg(env); } switch(float_y[0]) { case 'l': floated ^= EIM_FLOAT_LEFT; break; case 'c': floated ^= EIM_FLOAT_CENTER; break; case 'r': floated ^= EIM_FLOAT_RIGHT; break; case 't': floated ^= EIM_FLOAT_TOP; break; case 'b': floated ^= EIM_FLOAT_BOTTOM; break; default: return enif_make_badarg(env); } } else { floated = EIM_FLOAT_CENTER | EIM_FLOAT_CENTER; } handle->image->box(width, height, floated); break; default: return enif_make_badarg(env); } } while(enif_get_list_cell(env, tail, &head, &tail)); EIM_FORMAT eim_format; switch(fmt[0]) { case 'j': eim_format = EIM_FORMAT_JPG; break; case 'g': eim_format = EIM_FORMAT_GIF; break; case 'p': eim_format = EIM_FORMAT_PNG; break; default: return enif_make_badarg(env); } try { new_blob = handle->image->process(eim_format, &new_length); enif_alloc_binary_compat(env, new_length, &new_binary); memcpy(new_binary.data, new_blob, new_length); return enif_make_binary(env, &new_binary); } catch(const char* msg) { return enif_make_atom(env, "error"); } } else { return enif_make_badarg(env); } }
static int get_number(ErlNifEnv* env, ERL_NIF_TERM term, double* dp) { long i; return enif_get_double(env, term, dp) || (enif_get_long(env, term, &i) && (*dp=(double)i, 1)); }
int enc_json(Encoder* enc, ERL_NIF_TERM term) { int ival; unsigned int uival; long lval; unsigned long ulval; double dval; ERL_NIF_TERM head; ERL_NIF_TERM tail; int arity; const ERL_NIF_TERM* tuple; if(enif_is_atom(enc->env, term)) { return enc_atom(enc, term); } if(enif_is_binary(enc->env, term)) { return enc_binary(enc, term); } if(enif_get_int(enc->env, term, &ival)) { if(yajl_gen_integer(enc->handle, ival) != yajl_gen_status_ok) { enc->error = enif_make_atom(enc->env, "bad_integer"); return ERROR; } return OK; } if(enif_get_uint(enc->env, term, &uival)) { if(yajl_gen_integer(enc->handle, uival) != yajl_gen_status_ok) { enc->error = enif_make_atom(enc->env, "bad_unsigned_integer"); return ERROR; } return OK; } if(enif_get_long(enc->env, term, &lval)) { if(yajl_gen_integer(enc->handle, lval) != yajl_gen_status_ok) { enc->error = enif_make_atom(enc->env, "bad_long"); return ERROR; } return OK; } if(enif_get_ulong(enc->env, term, &ulval)) { if(yajl_gen_integer(enc->handle, ulval) != yajl_gen_status_ok) { enc->error = enif_make_atom(enc->env, "bad_unsigned_long"); return ERROR; } return OK; } if(enif_get_double(enc->env, term, &dval)) { if(yajl_gen_double(enc->handle, dval) != yajl_gen_status_ok) { enc->error = enif_make_atom(enc->env, "bad_double"); return ERROR; } return OK; } if(enif_is_empty_list(enc->env, term)) { if(yajl_gen_array_open(enc->handle) != yajl_gen_status_ok) { enc->error = enif_make_atom(enc->env, "failed_to_open_empty_list"); return ERROR; } if(yajl_gen_array_close(enc->handle) != yajl_gen_status_ok) { enc->error = enif_make_atom(enc->env, "failed_to_close_empty_list"); return ERROR; } return OK; } if(enif_get_list_cell(enc->env, term, &head, &tail)) { return enc_array(enc, head, tail); } if(enif_get_tuple(enc->env, term, &arity, &tuple)) { if(arity == 1) { if(enif_is_empty_list(enc->env, tuple[0])) { if(yajl_gen_map_open(enc->handle) != yajl_gen_status_ok) { enc->error = enif_make_atom(enc->env, "failed_to_open_empty_map"); return ERROR; } if(yajl_gen_map_close(enc->handle) != yajl_gen_status_ok) { enc->error = enif_make_atom(enc->env, "failed_to_close_empty_map"); return ERROR; } return OK; } else if(enif_get_list_cell(enc->env, tuple[0], &head, &tail)) { return enc_map(enc, head, tail); } } } enc->error = enif_make_tuple(enc->env, 2, enif_make_atom(enc->env, "badarg"), term ); return ERROR; }
jsval to_js(ErlNifEnv* env, JSContext* cx, ERL_NIF_TERM term) { int intval; unsigned int uintval; long longval; unsigned long ulongval; double doubleval; ERL_NIF_TERM head; ERL_NIF_TERM tail; const ERL_NIF_TERM* tuple; int arity; if(enif_is_atom(env, term)) { return to_js_special(env, cx, term); } if(enif_is_binary(env, term)) { return to_js_string(env, cx, term); } if(enif_is_empty_list(env, term)) { return to_js_empty_array(cx); } if(enif_get_int(env, term, &intval)) { return to_js_number(cx, (double) intval); } if(enif_get_uint(env, term, &uintval)) { return to_js_number(cx, (double) uintval); } if(enif_get_long(env, term, &longval)) { return to_js_number(cx, (double) longval); } if(enif_get_ulong(env, term, &ulongval)) { return to_js_number(cx, (double) ulongval); } if(enif_get_double(env, term, &doubleval)) { return to_js_number(cx, doubleval); } // enif doesn't seem to have any API to decode bignums, so use lower-level functions: if(is_big(term) && big_to_double(term, &doubleval) == 0) { return to_js_number(cx, doubleval); } if(enif_get_list_cell(env, term, &head, &tail)) { return to_js_array(env, cx, head, tail); } if(enif_get_tuple(env, term, &arity, &tuple)) { if(arity == 1) { return to_js_object(env, cx, tuple[0]); } } return JSVAL_VOID; }