int compare_props(int depth, couch_ejson_ctx_t* ctx, ERL_NIF_TERM a, ERL_NIF_TERM b) { ERL_NIF_TERM headA, tailA; ERL_NIF_TERM headB, tailB; int aArity, bArity; const ERL_NIF_TERM *aKV, *bKV; ErlNifBinary keyA, keyB; int aIsEmpty, bIsEmpty; int keyCompResult, valueCompResult; while (1) { aIsEmpty = !enif_get_list_cell(ctx->env, a, &headA, &tailA); bIsEmpty = !enif_get_list_cell(ctx->env, b, &headB, &tailB); if (aIsEmpty) { if (bIsEmpty) { return 0; } return -1; } if (bIsEmpty) { return 1; } if (!enif_get_tuple(ctx->env, headA, &aArity, &aKV)) { ctx->error = 1; return 0; } if ((aArity != 2) || !enif_inspect_binary(ctx->env, aKV[0], &keyA)) { ctx->error = 1; return 0; } if (!enif_get_tuple(ctx->env, headB, &bArity, &bKV)) { ctx->error = 1; return 0; } if ((bArity != 2) || !enif_inspect_binary(ctx->env, bKV[0], &keyB)) { ctx->error = 1; return 0; } keyCompResult = compare_strings(ctx, keyA, keyB); if (ctx->error || keyCompResult != 0) { return keyCompResult; } valueCompResult = less_ejson(depth + 1, ctx, aKV[1], bKV[1]); if (ctx->error || valueCompResult != 0) { return valueCompResult; } a = tailA; b = tailB; } return 0; }
static ERL_NIF_TERM nif_scheduler_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary frameworkInfo_binary; ErlNifBinary credentials_binary; char masterUrl[MAXBUFLEN]; state_ptr state = (state_ptr) enif_priv_data(env); if(state->initilised == 1) { return enif_make_tuple2(env, enif_make_atom(env, "state_error"), enif_make_atom(env, "scheduler_already_inited")); } ErlNifPid* pid = (ErlNifPid*) enif_alloc(sizeof(ErlNifPid)); if(!enif_get_local_pid(env, argv[0], pid)) { return enif_make_tuple3(env, enif_make_atom(env, "argument_error"), enif_make_atom(env, "invalid_or_corrupted_parameter"), enif_make_atom(env, "pid")); } if (!enif_inspect_binary(env, argv[1], &frameworkInfo_binary)) { return enif_make_tuple3(env, enif_make_atom(env, "argument_error"), enif_make_atom(env, "invalid_or_corrupted_parameter"), enif_make_atom(env, "framework_info")); } if(!enif_get_string(env, argv[2], masterUrl , MAXBUFLEN, ERL_NIF_LATIN1 )) { return enif_make_tuple3(env, enif_make_atom(env, "argument_error"), enif_make_atom(env, "invalid_or_corrupted_parameter"), enif_make_atom(env, "master_info")); } if(argc == 4 ) { if(!enif_inspect_binary(env,argv[3], &credentials_binary)) { return enif_make_tuple3(env, enif_make_atom(env, "argument_error"), enif_make_atom(env, "invalid_or_corrupted_parameter"), enif_make_atom(env, "credential")); } state->scheduler_state = scheduler_init(pid, &frameworkInfo_binary, masterUrl, 1, &credentials_binary); } else { state->scheduler_state = scheduler_init(pid, &frameworkInfo_binary, masterUrl, 0, &credentials_binary); } state->initilised = 1; return enif_make_atom(env, "ok"); }
ERL_NIF_TERM nif_process_trends(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary trends_bin; unsigned char trends_buffer[MAX_LIST_BUFFER_LEN]; unsigned int trends_len = 0; if (enif_inspect_binary(env, argv[0], &trends_bin)) { memcpy((char *)trends_buffer, trends_bin.data, trends_bin.size); trends_buffer[trends_bin.size] = '\0'; trends_len = trends_bin.size; #ifdef ERLANG_R14B02 enif_release_binary(&trends_bin); #else enif_release_binary(env, &trends_bin); #endif } else { #ifndef TRENDS_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_invalid_trends_bin"); #endif } unsigned int trends_count = 0; if (ProcessTrends(trends_buffer, &trends_len, &trends_count) < 0) { #ifndef TRENDS_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_GetTrends"); #endif } ERL_NIF_TERM processed_trends_list = enif_make_list(env, 0); if (strlen(trends_buffer) > 0) { char* start = (char*) trends_buffer; char* end = strstr(start, "|"); unsigned int len = 0; ErlNifBinary processed_trends_bin; int ret_val = 0; unsigned int i=0; while (start && end && *end != '\0') { end = strstr(start, "|"); if (!end) break; *end = '\0'; len = end - start; #ifdef ERLANG_R14B02 ret_val = enif_alloc_binary(len, &processed_trends_bin); #else ret_val = enif_alloc_binary(env, len, &processed_trends_bin); #endif if (ret_val < 0) { #ifndef TRENDS_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_processed_trends_bin_alloc"); #endif } for (i=0; i<len; i++) { processed_trends_bin.data[i] = *(start + i); } processed_trends_list = enif_make_list_cell(env, enif_make_binary(env, &processed_trends_bin), processed_trends_list); *end = '|'; start = end + 1; } } return processed_trends_list; }
/* For OpenSSL >= 1.1.1 the hmac_nif and cmac_nif could be integrated into poly1305 (with 'type' as parameter) */ ERL_NIF_TERM poly1305_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key, Text) */ #ifdef HAVE_POLY1305 ErlNifBinary key_bin, text, ret_bin; ERL_NIF_TERM ret; EVP_PKEY *key = NULL; EVP_MD_CTX *mctx = NULL; EVP_PKEY_CTX *pctx = NULL; const EVP_MD *md = NULL; size_t size; int ret_bin_alloc = 0; ASSERT(argc == 2); if (!enif_inspect_binary(env, argv[0], &key_bin)) goto bad_arg; if (key_bin.size != 32) goto bad_arg; if (!enif_inspect_binary(env, argv[1], &text)) goto bad_arg; if ((key = EVP_PKEY_new_raw_private_key(EVP_PKEY_POLY1305, /*engine*/ NULL, key_bin.data, key_bin.size)) == NULL) goto err; if ((mctx = EVP_MD_CTX_new()) == NULL) goto err; if (EVP_DigestSignInit(mctx, &pctx, md, /*engine*/ NULL, key) != 1) goto err; if (EVP_DigestSignUpdate(mctx, text.data, text.size) != 1) goto err; if (EVP_DigestSignFinal(mctx, NULL, &size) != 1) goto err; if (!enif_alloc_binary(size, &ret_bin)) goto err; ret_bin_alloc = 1; if (EVP_DigestSignFinal(mctx, ret_bin.data, &size) != 1) goto err; if (size != ret_bin.size) { if (!enif_realloc_binary(&ret_bin, size)) goto err; } ret = enif_make_binary(env, &ret_bin); ret_bin_alloc = 0; goto done; bad_arg: return enif_make_badarg(env); err: if (ret_bin_alloc) enif_release_binary(&ret_bin); ret = atom_error; done: if (mctx) EVP_MD_CTX_free(mctx); if (key) EVP_PKEY_free(key); return ret; #else return enif_raise_exception(env, atom_notsup); #endif }
static ERL_NIF_TERM mmap_open(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { Mmap *desc; ERL_NIF_TERM f; ErlNifBinary bin_path; char path[PATH_SIZE]; int fd; struct stat st; int debug = 0; ERL_NIF_TERM opt, opts; if (!enif_inspect_binary(env, argv[0], &bin_path)) { return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, "Should pass binary filename", ERL_NIF_LATIN1)); } if (!enif_is_list(env, argv[1])) { return enif_make_badarg(env); } bzero(path, PATH_SIZE); strncpy(path, (const char *)bin_path.data, bin_path.size >= PATH_SIZE ? PATH_SIZE - 1 : bin_path.size); opts = argv[1]; while(enif_get_list_cell(env, opts, &opt, &opts)) { if(!enif_compare(opt, enif_make_atom(env, "debug"))) { debug = 1; } } fd = open(path, O_RDONLY); if(fd == -1) { if(errno == ENOENT) return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env, "enoent")); return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, strerror(errno), ERL_NIF_LATIN1)); } if(fstat(fd, &st)) { close(fd); return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, strerror(errno), ERL_NIF_LATIN1)); } if (debug) fprintf(stderr, "Opened file %s %ld\r\n", path, (ssize_t)st.st_size); desc = (Mmap *)enif_alloc_resource(MmapResource, sizeof(Mmap)); if(!desc) { close(fd); return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, "Couldn't allocate mmap resource", ERL_NIF_LATIN1)); } desc->fd = fd; desc->size = st.st_size; if (debug) fprintf(stderr, "Mmaping file: %p\r\n", desc); desc->ptr = mmap(NULL, desc->size, PROT_READ, MAP_FILE | MAP_PRIVATE, desc->fd, 0); close(fd); if(desc->ptr == MAP_FAILED) { enif_release_resource(desc); return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, "Couldn't mmap", ERL_NIF_LATIN1)); } if (debug) fprintf(stderr, "Mmaped file to %p\r\n", desc->ptr); f = enif_make_resource_binary(env, (void *)desc, desc->ptr, desc->size); enif_release_resource(desc); desc->debug = debug; return enif_make_tuple2(env, enif_make_atom(env, "ok"), f); }
ERL_NIF_TERM nif_test_twitter_timeline(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { char tweets_buffer[MAX_LIST_BUFFER_LEN]; memset(tweets_buffer, 0, MAX_LIST_BUFFER_LEN); int out_length = 0; if (argc == 1) { char user_name_str[MAX_NAME_LEN]; memset(user_name_str, 0, MAX_NAME_LEN); ErlNifBinary user_name; if (enif_inspect_binary(env, argv[0], &user_name)) { memcpy(user_name_str, user_name.data, user_name.size); user_name_str[user_name.size] = '\0'; #ifdef ERLANG_R14B02 enif_release_binary(&user_name); #else enif_release_binary(env, &user_name); #endif } else { #ifdef ERLANG_R14B02 enif_release_binary(&user_name); #else enif_release_binary(env, &user_name); #endif #ifndef TRENDS_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_user_name"); #endif } if (GetTestTweets(user_name_str, MAX_LIST_BUFFER_LEN, tweets_buffer, &out_length) < 0) { #ifndef TRENDS_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_get_test_tweets_for_user"); #endif } } else { if (GetTestTweets(NULL, MAX_LIST_BUFFER_LEN, tweets_buffer, &out_length) < 0) { #ifndef TRENDS_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_get_test_tweets_for_null_user"); #endif } } if (0 == out_length || out_length > MAX_LIST_BUFFER_LEN) { #ifndef TRENDS_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_out_length"); #endif } ErlNifBinary tweets_bin; unsigned int tweets_len = out_length; int ret_val = 0; unsigned int i = 0; ERL_NIF_TERM arg_array[1]; ERL_NIF_TERM trends_list = enif_make_list(env, 0); #ifdef ERLANG_R14B02 ret_val = enif_alloc_binary(tweets_len, &tweets_bin); #else ret_val = enif_alloc_binary(env, tweets_len, &tweets_bin); #endif if (ret_val < 0) { #ifndef TRENDS_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_tweet_len"); #endif } for (i=0; i<tweets_len; i++) { tweets_bin.data[i] = *(tweets_buffer + i); } arg_array[0] = enif_make_binary(env, &tweets_bin); trends_list = nif_get_trends(env, 1, arg_array); if (enif_is_atom(env, trends_list)) { return enif_make_atom(env, "error_nif_get_trends"); } return trends_list; }
static ERL_NIF_TERM _send (ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { CAN_handle* handle; unsigned int i = 0, length, total_size = 0; ERL_NIF_TERM result; if (!enif_get_resource(env, argv[0], CAN_handle_type, (void**) &handle)) return enif_make_int(env, -2000); if (!enif_get_list_length(env, argv[1], &length)) return enif_make_int(env, -2001); canmsg_t* buffer = enif_alloc(length * sizeof(canmsg_t)); memset(buffer, 0, length * sizeof(canmsg_t)); ERL_NIF_TERM list = argv[1]; ERL_NIF_TERM head, tail; while (enif_get_list_cell(env, list, &head, &tail)) { canmsg_t* can_msg = &buffer[i++]; int arity; canmsg_id_t target; ErlNifBinary msg; const ERL_NIF_TERM* items; list = tail; if (!enif_get_tuple(env, head, &arity, &items)) { result = enif_make_int(env, -1000); goto end; } if (arity != 2) { result = enif_make_int(env, -1001); goto end; } if (!enif_get_ulong(env, items[0], &target)) { result = enif_make_int(env, -1002); goto end; } if (!enif_inspect_binary(env, items[1], &msg)) { result = enif_make_int(env, -1003); goto end; } if (msg.size > CAN_MSG_LENGTH) { result = enif_make_int(env, -1005); goto end; } can_msg->id = target; memcpy(&can_msg->data[0], msg.data, msg.size); can_msg->length = msg.size; total_size += msg.size; } { int status = write(handle->device, buffer, length * sizeof(canmsg_t)); if (status != length * sizeof(canmsg_t)) status = errno; result = enif_make_tuple2(env, enif_make_int(env, status), enif_make_int(env, total_size)); } end: enif_free(buffer); return result; }
/* 0: list */ static ERL_NIF_TERM nif_alloc(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM head = {0}; ERL_NIF_TERM tail = {0}; int arity = 0; char key[MAXATOMLEN+1]; /* Includes terminating NULL */ const ERL_NIF_TERM *array = NULL; ERL_NIF_TERM resources = {0}; ErlNifBinary req = {0}; if (!enif_is_list(env, argv[0]) || enif_is_empty_list(env, argv[0])) return enif_make_badarg(env); resources = enif_make_list(env, 0); if (!enif_alloc_binary(0, &req)) return error_tuple(env, ENOMEM); tail = argv[0]; /* [binary(), {ptr, integer()}, {ptr, binary()}, ...] */ while (enif_get_list_cell(env, tail, &head, &tail)) { int index = req.size; ErlNifBinary bin = {0}; if (enif_inspect_binary(env, head, &bin)) { enif_realloc_binary(&req, req.size+bin.size); (void)memcpy(req.data+index, bin.data, bin.size); } else if (enif_get_tuple(env, head, &arity, &array)) { ALLOC_STATE *p = NULL; ERL_NIF_TERM res = {0}; size_t val = 0; ErlNifBinary initial = {0}; if ( (arity != 2) || !enif_get_atom(env, array[0], key, sizeof(key), ERL_NIF_LATIN1) || (strcmp(key, "ptr") != 0)) return enif_make_badarg(env); if ( !(enif_get_ulong(env, array[1], (unsigned long *)&val) && val > 0) && !(enif_inspect_binary(env, array[1], &initial) && initial.size > 0)) return enif_make_badarg(env); val = (initial.size > 0) ? initial.size : val; p = enif_alloc_resource(PROCKET_ALLOC_RESOURCE, sizeof(ALLOC_STATE)); if (p == NULL) return error_tuple(env, ENOMEM); p->size = val; p->buf = calloc(val, 1); if (p->buf == NULL) { enif_release_resource(p); return error_tuple(env, ENOMEM); } if (initial.size > 0) (void)memcpy(p->buf, initial.data, p->size); if (!enif_realloc_binary(&req, req.size+sizeof(void *))) return error_tuple(env, ENOMEM); (void)memcpy(req.data+index, &p->buf, sizeof(void *)); res = enif_make_resource(env, p); enif_release_resource(p); resources = enif_make_list_cell(env, res, resources); } else return enif_make_badarg(env); } return enif_make_tuple3(env, atom_ok, enif_make_binary(env, &req), resources); }
ERL_NIF_TERM nif_detect_lang(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { if (argc != 1) { #ifndef LD_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_invalid_argc"); #endif } ErlNifBinary tweet_bin; char tweet_str[MAX_BUFFER_LEN]; ERL_NIF_TERM tweet_term; bool success = enif_inspect_binary(env, argv[0], &tweet_bin); int tweet_len = tweet_bin.size; if (success && tweet_len > 1 && tweet_len < MAX_BUFFER_LEN) { memcpy(tweet_str, tweet_bin.data, tweet_len); tweet_str[tweet_len] = '\0'; tweet_term = enif_make_binary(env, &tweet_bin); //enif_release_binary(env, &tweet_bin); } else { #ifdef ERLANG_R14B02 enif_release_binary(&tweet_bin); #else enif_release_binary(env, &tweet_bin); #endif #ifndef LD_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_invalid_input_binary"); #endif } char lang_buffer[MAX_BUFFER_LEN]; lang_buffer[0] = '\0'; if (CallClassify(tweet_str, tweet_len, lang_buffer, MAX_BUFFER_LEN) < 0) { #ifndef LD_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_call_classify_failed"); #endif } unsigned int len = 0; unsigned int i = 0; int ret_val = 0; ErlNifBinary lang_bin; ERL_NIF_TERM lang_term; len = strlen(lang_buffer); if (len < 2) { strcpy(lang_buffer, "00"); len = 2; lang_buffer[2] = '\0'; } #ifdef ERLANG_R14B02 ret_val = enif_alloc_binary(len, &lang_bin); #else ret_val = enif_alloc_binary(env, len, &lang_bin); #endif if (ret_val < 0) { #ifndef LD_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_lang_bin_alloc"); #endif } for (i=0; i<len; i++) { lang_bin.data[i] = *(lang_buffer + i); } lang_term = enif_make_binary(env, &lang_bin); return enif_make_tuple2(env, tweet_term, lang_term); }
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 nif_test_twitter_timeline(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { char tweets_buffer[MAX_LIST_BUFFER_LEN]; memset(tweets_buffer, 0, MAX_LIST_BUFFER_LEN); int out_length = 0; if (argc == 1) { char user_name_str[MAX_NAME_LEN]; memset(user_name_str, 0, MAX_NAME_LEN); ErlNifBinary user_name; if (enif_inspect_binary(env, argv[0], &user_name)) { memcpy(user_name_str, user_name.data, user_name.size); user_name_str[user_name.size] = '\0'; #ifdef ERLANG_R14B02 enif_release_binary(&user_name); #else enif_release_binary(env, &user_name); #endif } else { #ifdef ERLANG_R14B02 enif_release_binary(&user_name); #else enif_release_binary(env, &user_name); #endif #ifndef LD_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_user_name"); #endif } if (GetTestTweets(user_name_str, MAX_LIST_BUFFER_LEN, tweets_buffer, &out_length) < 0) { #ifndef LD_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_get_test_tweets_for_user"); #endif } } else { if (GetTestTweets(NULL, MAX_LIST_BUFFER_LEN, tweets_buffer, &out_length) < 0) { #ifndef LD_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_get_test_tweets_for_null_user"); #endif } } if (0 == out_length || out_length > MAX_LIST_BUFFER_LEN) { #ifndef LD_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_out_length"); #endif } ErlNifBinary tweet; char *tweet_start = tweets_buffer; char *tweet_end = strstr(tweet_start, "|"); int ret_val = 0; unsigned int i = 0; unsigned int tweet_len = 0; ERL_NIF_TERM arg_array[1]; ERL_NIF_TERM tuple2_list = enif_make_list(env, 0); while (tweet_start && tweet_end && *tweet_end != '\0') { tweet_end = strstr(tweet_start, "|"); if (!tweet_end) break; *tweet_end = '\0'; tweet_len = tweet_end - tweet_start; if (tweet_len <= 0 || tweet_len >= MAX_BUFFER_LEN) { #ifndef LD_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_tweet_length"); #endif } #ifdef ERLANG_R14B02 ret_val = enif_alloc_binary(tweet_len, &tweet); #else ret_val = enif_alloc_binary(env, tweet_len, &tweet); #endif if (ret_val < 0) { #ifndef LD_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_alloc_bin_failed_for_tweet"); #endif } for (i=0; i<tweet_len; i++) { tweet.data[i] = *(tweet_start + i); } arg_array[0] = enif_make_binary(env, &tweet); ERL_NIF_TERM tuple2 = nif_detect_lang(env, 1, arg_array); if (enif_is_atom(env, tuple2)) { #ifndef LD_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_not_a_tuple2"); #endif //} else if (enif_is_tuple(env, tuple2)) { } else { tuple2_list = enif_make_list_cell(env, tuple2, tuple2_list); /* #ifndef LD_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_undefined_detect_lang_output"); #endif */ } *tweet_end = '|'; tweet_start = tweet_end + 1; } tweet_start = NULL; tweet_end = NULL; return tuple2_list; }
static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info) { #ifdef OPENSSL_THREADS ErlNifSysInfo sys_info; #endif get_crypto_callbacks_t* funcp; struct crypto_callbacks* ccb; int nlocks = 0; int tpl_arity; const ERL_NIF_TERM* tpl_array; int vernum; ErlNifBinary lib_bin; char lib_buf[1000]; #ifdef HAVE_DYNAMIC_CRYPTO_LIB void *handle; #endif if (!verify_lib_version()) return __LINE__; /* load_info: {302, <<"/full/path/of/this/library">>,true|false} */ if (!enif_get_tuple(env, load_info, &tpl_arity, &tpl_array)) return __LINE__; if (tpl_arity != 3) return __LINE__; if (!enif_get_int(env, tpl_array[0], &vernum)) return __LINE__; if (vernum != 302) return __LINE__; if (!enif_inspect_binary(env, tpl_array[1], &lib_bin)) return __LINE__; if (!init_hmac_ctx(env)) { return __LINE__; } if (!init_hash_ctx(env)) { return __LINE__; } if (!init_cipher_ctx(env)) { return __LINE__; } if (!init_engine_ctx(env)) { return __LINE__; } if (library_initialized) { /* Repeated loading of this library (module upgrade). * Atoms and callbacks are already set, we are done. */ return 0; } if (!init_atoms(env, tpl_array[2], load_info)) { return __LINE__; } #ifdef HAVE_DYNAMIC_CRYPTO_LIB if (!change_basename(&lib_bin, lib_buf, sizeof(lib_buf), crypto_callback_name)) return __LINE__; if ((handle = enif_dlopen(lib_buf, &error_handler, NULL)) == NULL) return __LINE__; if ((funcp = (get_crypto_callbacks_t*) enif_dlsym(handle, "get_crypto_callbacks", &error_handler, NULL)) == NULL) return __LINE__; #else /* !HAVE_DYNAMIC_CRYPTO_LIB */ funcp = &get_crypto_callbacks; #endif #ifdef OPENSSL_THREADS enif_system_info(&sys_info, sizeof(sys_info)); if (sys_info.scheduler_threads > 1) { nlocks = CRYPTO_num_locks(); } /* else no need for locks */ #endif ccb = (*funcp)(nlocks); if (!ccb || ccb->sizeof_me != sizeof(*ccb)) { PRINTF_ERR0("Invalid 'crypto_callbacks'"); return __LINE__; } #ifdef HAS_CRYPTO_MEM_FUNCTIONS if (!CRYPTO_set_mem_functions(ccb->crypto_alloc, ccb->crypto_realloc, ccb->crypto_free)) return __LINE__; #endif #ifdef OPENSSL_THREADS if (nlocks > 0) { CRYPTO_set_locking_callback(ccb->locking_function); CRYPTO_set_id_callback(ccb->id_function); CRYPTO_set_dynlock_create_callback(ccb->dyn_create_function); CRYPTO_set_dynlock_lock_callback(ccb->dyn_lock_function); CRYPTO_set_dynlock_destroy_callback(ccb->dyn_destroy_function); } #endif /* OPENSSL_THREADS */ init_digest_types(env); init_cipher_types(env); init_algorithms_types(env); library_initialized = 1; return 0; }
ERL_NIF_TERM geef_index_add(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { geef_index *index; const ERL_NIF_TERM *eentry; int arity; unsigned int tmp; ErlNifBinary path, id; git_index_entry entry; if (!enif_get_resource(env, argv[0], geef_index_type, (void **) &index)) return enif_make_badarg(env); if (!enif_get_tuple(env, argv[1], &arity, &eentry)) return enif_make_badarg(env); memset(&entry, 0, sizeof(entry)); if (enif_compare(eentry[1], atoms.undefined) && !enif_get_int64(env, eentry[1], &entry.ctime.seconds)) return enif_make_badarg(env); if (enif_compare(eentry[2], atoms.undefined) && !enif_get_int64(env, eentry[2], &entry.mtime.seconds)) return enif_make_badarg(env); if (enif_compare(eentry[3], atoms.undefined) && !enif_get_uint(env, eentry[3], &entry.dev)) return enif_make_badarg(env); if (enif_compare(eentry[4], atoms.undefined) && !enif_get_uint(env, eentry[4], &entry.ino)) return enif_make_badarg(env); if (!enif_get_uint(env, eentry[5], &entry.mode)) return enif_make_badarg(env); if (enif_compare(eentry[6], atoms.undefined) && !enif_get_uint(env, eentry[6], &entry.uid)) return enif_make_badarg(env); if (enif_compare(eentry[7], atoms.undefined) && !enif_get_uint(env, eentry[7], &entry.gid)) return enif_make_badarg(env); if (!enif_get_int64(env, eentry[8], &entry.file_size)) return enif_make_badarg(env); /* [9] comes later */ tmp = 0; if (enif_compare(eentry[10], atoms.undefined) && !enif_get_uint(env, eentry[10], &tmp)) return enif_make_badarg(env); entry.flags = tmp; tmp = 0; if (enif_compare(eentry[11], atoms.undefined) && !enif_get_uint(env, eentry[11], &tmp)) return enif_make_badarg(env); entry.flags_extended = tmp; if (!enif_inspect_iolist_as_binary(env, eentry[12], &path)) return enif_make_badarg(env); if (!geef_terminate_binary(&path)) return geef_oom(env); entry.path = (char *) path.data; if (!enif_inspect_binary(env, eentry[9], &id)) return enif_make_badarg(env); git_oid_fromraw(&entry.id, id.data); if (git_index_add(index->index, &entry) < 0) return geef_error(env); return atoms.ok; }
// Feed scanner a binary data block ERL_NIF_TERM yang_scan_next_token(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { yang_scanner_t* obj; token_t* t; uint8_t* ptr; uint8_t* ptr_end; ErlNifBinary bin; state_t state; #define STATE(st) state_##st: case STATE_##st #define GOTO(st) state = STATE_##st; goto state_##st #define SET_STATE(st) state = STATE_##st if (!enif_get_resource(env, argv[0], yang_scan_resource, (void**) &obj)) { DBG("argv[0] not a resource\r\n"); return enif_make_badarg(env); } state = obj->state; if (argc == 2) { if (!enif_inspect_binary(env, argv[1], &bin)) { DBG("argv[1] not a binary\r\n"); return enif_make_badarg(env); } ptr = bin.data; ptr_end = ptr + bin.size; // now scan the data and push tokens switch (state) { STATE(WSP_SLASH): DBG("WSP_SLASH remain=%ld\r\n", ptr_end - ptr); if (ptr >= ptr_end) goto out; else { if (*ptr == '/') { ptr++; GOTO(LINE_COMMENT); } else if (*ptr == '*') { ptr++; GOTO(BLOCK_COMMENT); } else { obj->t_line = obj->line; add_char('/', obj); GOTO(WORD); } } SET_STATE(WSP); // FALL THROUGH STATE(WSP): DBG("WSP remain=%ld\r\n", ptr_end - ptr); while(ptr < ptr_end) { int c = *ptr++; switch(c) { case '/': GOTO(WSP_SLASH); break; case ' ': obj->column += 1; break; case '\t': obj->column += 8; break; case '\r': break; case '\n': obj->line += 1; obj->column = 1; break; case '\"': obj->t_column = obj->column; // save column obj->t_line = obj->line; // save start line obj->t_skip = false; obj->column++; GOTO(DQUOTE_STRING); case '\'': obj->t_column = obj->column; // save column obj->t_line = obj->line; // save start line obj->column++; GOTO(SQUOTE_STRING); case '{': case '}': case ';': enq_char(obj, c); break; default: obj->t_line = obj->line; add_char(c, obj); GOTO(WORD); } } break; STATE(LINE_COMMENT): DBG("LINE_COMMENT remain=%ld\r\n", ptr_end - ptr); while(ptr < ptr_end) { int c = *ptr++; if (c == '\n') { obj->line++; obj->column = 1; GOTO(WSP); } } break; STATE(BLOCK_COMMENT_STAR): DBG("BLOCK_COMMENT_STAR remain=%ld\r\n", ptr_end - ptr); if (ptr >= ptr_end) goto out; else if (*ptr == '/') { ptr++; obj->column += 2; GOTO(WSP); } SET_STATE(BLOCK_COMMENT); // FALL TROUGH STATE(BLOCK_COMMENT): DBG("BLOCK_COMMENT remain=%ld\r\n", ptr_end - ptr); while(ptr < ptr_end) { int c = *ptr++; if (c == '\n') { obj->line++; obj->column = 1; } else if (c == '*') { GOTO(BLOCK_COMMENT_STAR); } else { obj->column++; } } break; STATE(WORD_SLASH): DBG("WORD_SLASH remain=%ld\r\n", ptr_end - ptr); if (ptr >= ptr_end) goto out; else { if (*ptr == '/') { enq_word(obj); ptr++; GOTO(LINE_COMMENT); } else if (*ptr == '*') { enq_word(obj); ptr++; GOTO(BLOCK_COMMENT); } else { add_char('/', obj); } } SET_STATE(WORD); // FALL THROUGH STATE(WORD): DBG("WORD remain=%ld\r\n", ptr_end - ptr); while(ptr < ptr_end) { int c = *ptr++; switch(c) { case '/': GOTO(WORD_SLASH); case ' ': enq_word(obj); obj->column += 1; GOTO(WSP); case '\t': enq_word(obj); obj->column += 8; GOTO(WSP); case '\r': enq_word(obj); GOTO(WSP); case '\n': case ';': case '{': case '}': enq_word(obj); ptr--; GOTO(WSP); default: obj->column++; add_char(c, obj); } } break; STATE(DQUOTE_STRING_BSLASH): DBG("DQUOTE_STRING_BSLASH remain=%ld\r\n", ptr_end - ptr); if (ptr >= ptr_end) goto out; else { int c = *ptr++; switch(c) { case 'n': add_char('\n', obj); break; case 't': add_char('\t', obj); break; case '"': add_char(c, obj); break; case '\\': add_char(c, obj); break; default: add_char('\\', obj); add_char(c, obj); break; } obj->t_skip = false; } SET_STATE(DQUOTE_STRING); // FALL THROUGH STATE(DQUOTE_STRING): DBG("DQUOTE_STRING remain=%ld\r\n", ptr_end - ptr); while(ptr < ptr_end) { int c = *ptr++; switch(c) { case '\\': GOTO(DQUOTE_STRING_BSLASH); case '\"': enq_string(obj); obj->column++; GOTO(WSP); case '\n': trim_wsp(obj); // remove trailing wsp obj->line++; obj->column = 1; obj->t_skip = true; add_char(c, obj); break; case ' ': if (obj->t_skip && (obj->column <= obj->t_column)) obj->column += 1; else { add_char(' ', obj); obj->t_skip = false; obj->column += 1; } break; case '\t': if (obj->t_skip && (obj->column <= obj->t_column)) obj->column += 8; else { add_char('\t', obj); obj->t_skip = false; obj->column += 8; } break; default: add_char(c, obj); obj->column += 1; obj->t_skip = false; break; } } break; STATE(SQUOTE_STRING): DBG("SQUOTE_STRING remain=%ld\r\n", ptr_end - ptr); while(ptr < ptr_end) { int c = *ptr++; switch(c) { case '\'': enq_string(obj); obj->column++; GOTO(WSP); case '\n': obj->line++; obj->column = 1; // FALL TROUGH default: add_char(c, obj); break; } } break; default: DBG("STATE = %d, remain=%ld\r\n", state, ptr_end - ptr); return enif_make_badarg(env); } } out: obj->state = state; t = deq_token(obj); if (t == NULL) { DBG("deq_token return NULL\r\n"); return atm_more; } else { ERL_NIF_TERM r; r = make_token(env, t); release_token(env, t); return r; } }
static ERL_NIF_TERM binary_to_libyaml_event_stream_rev(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary bin; ERL_NIF_TERM tail; yaml_parser_t parser; yaml_event_t event; yaml_error_type_t error; int done = 0; char msg[200]; if (!enif_inspect_binary(env, argv[0], &bin)) { return enif_make_badarg(env); } tail = enif_make_list(env,0); /* Create the Parser object. */ yaml_parser_initialize(&parser); yaml_parser_set_input_string(&parser, bin.data, bin.size); /* Read the event sequence. */ while (!done) { /* Get the next event. */ if (!yaml_parser_parse(&parser, &event)) goto parser_error; // convert and add to list tail = enif_make_list_cell(env, event_to_term(env,&event), tail); /* Are we finished? */ done = (event.type == YAML_STREAM_END_EVENT); /* The application is responsible for destroying the event object. */ yaml_event_delete(&event); } /* Destroy the Parser object. */ yaml_parser_delete(&parser); return enif_make_tuple2(env, enif_make_atom(env, "ok"), tail); /* On error. */ parser_error: memset(msg,0, sizeof(msg)); error = parser.error; switch (error) { case YAML_MEMORY_ERROR: snprintf(msg, sizeof(msg), "Memory error: Not enough memory for parsing\n"); break; case YAML_READER_ERROR: if (parser.problem_value != -1) { snprintf(msg, sizeof(msg), "Reader error: %s: #%X at %zu\n", parser.problem, parser.problem_value, parser.problem_offset); } else { fprintf(stderr, "Reader error: %s at %zu\n", parser.problem, parser.problem_offset); } break; case YAML_SCANNER_ERROR: if (parser.context) { snprintf(msg, sizeof(msg), "Scanner error: %s at line %zu, column %zu\n" "%s at line %zu, column %zu\n", parser.context, parser.context_mark.line+1, parser.context_mark.column+1, parser.problem, parser.problem_mark.line+1, parser.problem_mark.column+1); } else { snprintf(msg, sizeof(msg), "Scanner error: %s at line %zu, column %zu\n", parser.problem, parser.problem_mark.line+1, parser.problem_mark.column+1); } break; case YAML_PARSER_ERROR: if (parser.context) { snprintf(msg, sizeof(msg), "Parser error: %s at line %zu, column %zu\n" "%s at line %zu, column %zu\n", parser.context, parser.context_mark.line+1, parser.context_mark.column+1, parser.problem, parser.problem_mark.line+1, parser.problem_mark.column+1); } else { snprintf(msg, sizeof(msg), "Parser error: %s at line %zu, column %zu\n", parser.problem, parser.problem_mark.line+1, parser.problem_mark.column+1); } break; default: break; } /* Destroy the Parser object. */ yaml_parser_delete(&parser); return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_tuple2(env, enum_to_atom(env, error, error_type_atoms), cstr_to_binary(env,msg))); }
static ERL_NIF_TERM nif_sendmsg(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { int sockfd = -1; int flags = 0; ssize_t n = 0; ErlNifBinary buf = {0}; ErlNifBinary sa = {0}; ERL_NIF_TERM cdata_list, head, tail; char *cdata = NULL; struct iovec iov[1]; struct msghdr message; struct cmsghdr *cmsg; size_t cdata_size = 0; if (!enif_get_int(env, argv[0], &sockfd)) return enif_make_badarg(env); if (!enif_inspect_binary(env, argv[1], &buf)) return enif_make_badarg(env); if (!enif_get_int(env, argv[2], &flags)) return enif_make_badarg(env); if (!enif_is_list(env, argv[3])) return enif_make_badarg(env); if (!enif_inspect_binary(env, argv[4], &sa)) return enif_make_badarg(env); cdata_list = argv[3]; // figure out how much control data we'll need to send while(enif_get_list_cell(env, cdata_list, &head, &tail)) { const ERL_NIF_TERM* fields; int arity; int level, type; ErlNifBinary cdata_field = {0}; if (!enif_get_tuple(env, head, &arity, &fields) || arity != 3) { return enif_make_badarg(env); } if (!enif_get_int(env, fields[0], &level)) { return enif_make_badarg(env); } if (!enif_get_int(env, fields[1], &type)) { return enif_make_badarg(env); } if (!enif_inspect_binary(env, fields[2], &cdata_field)) { return enif_make_badarg(env); } cdata_size += CMSG_SPACE(cdata_field.size); cdata_list = tail; } if (cdata_size > 0) { // allocate enough control data space, if any // freebsd throws einval if the cdata length is 0 // but the pointer isn't NULL if (!(cdata = malloc(cdata_size))) { return error_tuple(env, ENOMEM); } } // set up the iov and msghdr stuff iov[0].iov_base=(buf.size == 0 ? NULL : buf.data); iov[0].iov_len=buf.size; message.msg_name=(sa.size == 0 ? NULL : sa.data); message.msg_namelen=sa.size; message.msg_iov=iov; message.msg_iovlen=1; message.msg_control=cdata; message.msg_controllen=cdata_size; // loop over the control data again, this time filling in the data in the // msghdr cdata_list = argv[3]; cmsg = CMSG_FIRSTHDR(&message); while(cmsg && enif_get_list_cell(env, cdata_list, &head, &tail)) { const ERL_NIF_TERM* fields; int arity; unsigned char *cmsg_data; ErlNifBinary cdata_field = {0}; // don't need to check here, we'd have crashed in the last loop if // things were wrong enif_get_tuple(env, head, &arity, &fields); enif_get_int(env, fields[0], &cmsg->cmsg_level); enif_get_int(env, fields[1], &cmsg->cmsg_type); enif_inspect_binary(env, fields[2], &cdata_field); cmsg_data = CMSG_DATA(cmsg); // copy the control data into the cdata struct memcpy(cmsg_data, cdata_field.data, cdata_field.size); // set the length cmsg->cmsg_len=CMSG_LEN(cdata_field.size); cdata_list = tail; cmsg = CMSG_NXTHDR(&message,cmsg); } n = sendmsg(sockfd, &message, flags); if (n < 0) return error_tuple(env, errno); return enif_make_tuple2(env, atom_ok, enif_make_int64(env, n)); }
static ERL_NIF_TERM mpegts_decode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary bin; Mpegts *ts; int eof = 0; if(argc != 2) return enif_make_badarg(env); char eof_str[10]; if(!enif_inspect_binary(env, argv[0], &bin)) { if(!enif_get_atom(env, argv[0], eof_str, sizeof(eof_str), ERL_NIF_LATIN1)) return enif_make_badarg(env); if(!strcmp(eof_str, "eof")) eof = 1; } if(eof) return enif_make_tuple3(env, enif_make_atom(env, "ok"), argv[1], enif_make_list(env, 0)); if(!enif_get_resource(env, argv[1], MpegtsResource, (void **)&ts)) { return enif_make_badarg(env); } // fprintf(stderr, "Decode %d bytes, %d in buffer, %d going to leave \r\n", (int)bin.size, ts->last_ts_size, (bin.size - ts->last_ts_size) % 188); uint8_t *pkt = bin.data; uint32_t size = bin.size; if(ts->last_ts_size > 0) { if(ts->last_ts_size + size < TS_BUFFERED) { memcpy(ts->last_ts + ts->last_ts_size, pkt, size); ts->last_ts_size += bin.size; size = 0; } else { uint32_t size1 = TS_BUFFERED - ts->last_ts_size; memcpy(ts->last_ts + ts->last_ts_size, pkt, size1); pkt += size1; size -= size1; ts->last_ts_size += size1; size1 = 0; while(size1 <= ts->last_ts_size - 188) { handle_ts(ts, ts->last_ts+size1); size1 += 188; } ts->last_ts_size = 0; } } while(size >= TS_BUFFERED) { while(size >= TS_BUFFERED && (pkt[0] != 0x47 || pkt[188] != 0x47 || pkt[2*188] != 0x47)) { pkt++; size--; } if(size >= TS_BUFFERED) { handle_ts(ts, pkt); pkt+=188; size-=188; } } if(size > 0) { assert(size <= TS_BUFFERED); ts->last_ts_size = size; memcpy(ts->last_ts, pkt, ts->last_ts_size); } return enif_make_tuple3(env, enif_make_atom(env, "ok"), argv[1], enif_make_list(env, 0)); }
static inline int enc_string(Encoder* e, ERL_NIF_TERM val) { ErlNifBinary bin; char atom[512]; unsigned char* data; size_t size; int esc_extra = 0; int ulen; int uval; int i; if(enif_is_binary(e->env, val)) { if(!enif_inspect_binary(e->env, val, &bin)) { return 0; } data = bin.data; size = bin.size; } else if(enif_is_atom(e->env, val)) { if(!enif_get_atom(e->env, val, atom, 512, ERL_NIF_LATIN1)) { return 0; } data = (unsigned char*) atom; size = strlen(atom); } else { return 0; } i = 0; while(i < size) { switch((char) data[i]) { case '\"': case '\\': case '/': case '\b': case '\f': case '\n': case '\r': case '\t': esc_extra += 1; i++; continue; default: if(data[i] < 0x20) { esc_extra += 5; i++; continue; } else if(data[i] < 0x80) { i++; continue; } ulen = utf8_validate(&(data[i]), size - i); if(ulen < 0) { return 0; } if(e->uescape) { uval = utf8_to_unicode(&(data[i]), ulen); if(uval < 0) { return 0; } ulen = utf8_esc_len(uval); if(ulen < 0) { return 0; } } i += ulen; } } if(!enc_ensure(e, size + esc_extra + 2)) { return 0; } e->p[e->i++] = '\"'; i = 0; while(i < size) { switch((char) data[i]) { case '\"': case '\\': case '/': e->p[e->i++] = '\\'; e->u[e->i++] = data[i]; i++; continue; case '\b': e->p[e->i++] = '\\'; e->p[e->i++] = 'b'; i++; continue; case '\f': e->p[e->i++] = '\\'; e->p[e->i++] = 'f'; i++; continue; case '\n': e->p[e->i++] = '\\'; e->p[e->i++] = 'n'; i++; continue; case '\r': e->p[e->i++] = '\\'; e->p[e->i++] = 'r'; i++; continue; case '\t': e->p[e->i++] = '\\'; e->p[e->i++] = 't'; i++; continue; default: if(data[i] < 0x20) { ulen = unicode_uescape(data[i], &(e->p[e->i])); if(ulen < 0) { return 0; } e->i += ulen; i++; } else if((data[i] & 0x80) && e->uescape) { uval = utf8_to_unicode(&(data[i]), size-i); if(uval < 0) { return 0; } ulen = unicode_uescape(uval, &(e->p[e->i])); if(ulen < 0) { return 0; } e->i += ulen; ulen = utf8_len(uval); if(ulen < 0) { return 0; } i += ulen; } else { e->u[e->i++] = data[i++]; } } } e->p[e->i++] = '\"'; e->count++; return 1; }
ERL_NIF_TERM nif_test_from_file(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { char tweets_buffer[MAX_LIST_BUFFER_LEN]; memset(tweets_buffer, 0, MAX_LIST_BUFFER_LEN); int out_length = 0; if (argc != 1) { #ifndef SENTIMENT_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_invalid_argc"); #endif } else { char file_name_str[MAX_NAME_LEN]; memset(file_name_str, 0, MAX_NAME_LEN); ErlNifBinary file_name; if (enif_inspect_binary(env, argv[0], &file_name)) { memcpy(file_name_str, file_name.data, file_name.size); file_name_str[file_name.size] = '\0'; #ifdef ERLANG_R14B02 enif_release_binary(&file_name); #else enif_release_binary(env, &file_name); #endif } else { #ifdef ERLANG_R14B02 enif_release_binary(&file_name); #else enif_release_binary(env, &file_name); #endif #ifndef SENTIMENT_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_file_name"); #endif } if (GetTestTweetsFromFile(file_name_str, MAX_LIST_BUFFER_LEN, tweets_buffer, &out_length) < 0) { #ifndef SENTIMENT_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_get_test_tweets_for_user"); #endif } } if (0 == out_length || out_length > MAX_LIST_BUFFER_LEN) { #ifndef SENTIMENT_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_out_length"); #endif } ErlNifBinary tweet; char *tweet_start = tweets_buffer; char *tweet_end = strstr(tweet_start, "|"); int ret_val = 0; unsigned int i = 0; unsigned int tweet_len = 0; ERL_NIF_TERM arg_array[1]; ERL_NIF_TERM tuple6; ERL_NIF_TERM tuple6_list = enif_make_list(env, 0); unsigned int error_count = 0; while (tweet_start && tweet_end && *tweet_end != '\0') { tweet_end = strstr(tweet_start, "|"); if (!tweet_end) break; *tweet_end = '\0'; tweet_len = tweet_end - tweet_start; if (tweet_len <= 0 || tweet_len >= MAX_BUFFER_LEN) { #ifndef SENTIMENT_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_out_length"); #endif } #ifdef ERLANG_R14B02 ret_val = enif_alloc_binary(tweet_len, &tweet); #else ret_val = enif_alloc_binary(env, tweet_len, &tweet); #endif if (ret_val < 0) { #ifndef SENTIMENT_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_tweet_len"); #endif } for (i=0; i<tweet_len; i++) { tweet.data[i] = *(tweet_start + i); } arg_array[0] = enif_make_binary(env, &tweet); tuple6 = nif_get_sentiment(env, 1, arg_array); if (enif_is_atom(env, tuple6)) { error_count++; } else { tuple6_list = enif_make_list_cell(env, tuple6, tuple6_list); } *tweet_end = '|'; tweet_start = tweet_end + 1; } tweet_start = NULL; tweet_end = NULL; return tuple6_list; }
ERL_NIF_TERM blake2sp_hash(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES]; blake2s_state S[PARALLELISM_DEGREE][1]; blake2s_state FS[1]; ErlNifBinary input, key, salt, personal; uint8_t out[BLAKE2S_OUTBYTES] = {0}; unsigned int outlen; int i; ERL_NIF_TERM tmphash[BLAKE2S_OUTBYTES]; if (argc != 5 || !enif_inspect_binary(env, argv[0], &input) || !enif_inspect_binary(env, argv[1], &key) || !enif_get_uint(env, argv[2], &outlen) || !enif_inspect_binary(env, argv[3], &salt) || !enif_inspect_binary(env, argv[4], &personal)) return enif_make_badarg(env); if (!outlen || outlen > BLAKE2S_OUTBYTES) return -1; if( key.size > BLAKE2S_KEYBYTES ) return -1; for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) if( blake2sp_init_leaf( S[i], outlen, key.size, i, salt.data, personal.data, salt.size, personal.size) < 0 ) return -1; S[PARALLELISM_DEGREE - 1]->last_node = 1; // mark last node if( key.size > 0 ) { uint8_t block[BLAKE2S_BLOCKBYTES]; memset( block, 0, BLAKE2S_BLOCKBYTES ); memcpy( block, key.data, key.size ); for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES ); secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ } #if defined(_OPENMP) #pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE) #else for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ ) #endif { #if defined(_OPENMP) size_t id__ = omp_get_thread_num(); #endif uint64_t inlen__ = input.size; const uint8_t *in__ = ( const uint8_t * )input.data; in__ += id__ * BLAKE2S_BLOCKBYTES; while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ) { blake2s_update( S[id__], in__, BLAKE2S_BLOCKBYTES ); in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; } if( inlen__ > id__ * BLAKE2S_BLOCKBYTES ) { const size_t left = inlen__ - id__ * BLAKE2S_BLOCKBYTES; const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES; blake2s_update( S[id__], in__, len ); } blake2s_final( S[id__], hash[id__], BLAKE2S_OUTBYTES ); } if( blake2sp_init_root( FS, outlen, key.size, salt.data, personal.data, salt.size, personal.size) < 0 ) return -1; FS->last_node = 1; // Mark as last node for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES ); blake2s_final( FS, out, outlen );; for (i = 0; i < outlen; i++) { tmphash[i] = enif_make_uint(env, out[i]); } return enif_make_list_from_array(env, tmphash, outlen); }
ERL_NIF_TERM nif_get_sentiment(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { if (argc != 1) { #ifndef SENTIMENT_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_invalid_argc"); #endif } ErlNifBinary text; unsigned char text_str[MAX_BUFFER_LEN]; unsigned int text_buffer_len = MAX_BUFFER_LEN; memset(text_str, 0, MAX_BUFFER_LEN); bool success = enif_inspect_binary(env, argv[0], &text); int text_len = text.size; if (success && text_len > 1 && text_len < MAX_BUFFER_LEN) { memcpy(text_str, text.data, text_len); text_str[text_len] = '\0'; #ifdef ERLANG_R14B02 enif_release_binary(&text); #else enif_release_binary(env, &text); #endif } else { #ifdef ERLANG_R14B02 enif_release_binary(&text); #else enif_release_binary(env, &text); #endif #ifndef SENTIMENT_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_invalid_tweet_len"); #endif } char safe_status[10]; memset(safe_status, 0, 10); char script[4]; memset(script, 0, 4); int sentiment_valence = 0; int ret_value = 0; if ((ret_value = GetSentiment((unsigned char *) text_str, text_buffer_len, text_len, (char *) safe_status, 10, (char *) script, 4, &sentiment_valence)) < 0) { #ifndef SENTIMENT_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_GetSentiment"); #endif } unsigned int len = 0; unsigned int i = 0; int ret_val = 0; ErlNifBinary safe_status_bin; ErlNifBinary script_bin; ERL_NIF_TERM safe_status_term; ERL_NIF_TERM script_term; len = strlen(safe_status); if (len < 4 || len > 6) { strcpy(safe_status, "ERROR"); len = 5; } #ifdef ERLANG_R14B02 ret_val = enif_alloc_binary(len, &safe_status_bin); #else ret_val = enif_alloc_binary(env, len, &safe_status_bin); #endif if (ret_val < 0) { #ifndef SENTIMENT_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_safe_status_bin_alloc"); #endif } for (i=0; i<len; i++) { safe_status_bin.data[i] = *(safe_status + i); } safe_status_term = enif_make_binary(env, &safe_status_bin); len = strlen(script); if (len != 2 && len != 3) { strcpy(script, "00"); len = 2; } #ifdef ERLANG_R14B02 ret_val = enif_alloc_binary(len, &script_bin); #else ret_val = enif_alloc_binary(env, len, &script_bin); #endif if (ret_val < 0) { #ifndef SENTIMENT_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_script_bin_alloc"); #endif } for (i=0; i<len; i++) { script_bin.data[i] = *(script + i); } script_term = enif_make_binary(env, &script_bin); ERL_NIF_TERM sentiment_term; sentiment_term = enif_make_int(env, sentiment_valence); return enif_make_tuple3(env, safe_status_term, script_term, sentiment_term); }
ERL_NIF_TERM nif_test_from_file(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { if (argc != 1) { #ifndef TRENDS_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_invalid_argc"); #endif } ErlNifBinary file_path; char trends_file_path[MAX_NAME_LEN]; bool success = enif_inspect_binary(env, argv[0], &file_path); if (success && (file_path.size < MAX_NAME_LEN)) { memcpy(trends_file_path, file_path.data, file_path.size); trends_file_path[file_path.size] = '\0'; #ifdef ERLANG_R14B02 enif_release_binary(&file_path); #else enif_release_binary(env, &file_path); #endif } else { #ifdef ERLANG_R14B02 enif_release_binary(&file_path); #else enif_release_binary(env, &file_path); #endif #ifndef TRENDS_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_trends_file_path_inspect_bin"); #endif } unsigned char trends_buffer[MAX_LIST_BUFFER_LEN]; unsigned int trends_len = 0; unsigned int trends_count = 0; if (GetTestTrendsFromFile(trends_file_path, trends_buffer, MAX_LIST_BUFFER_LEN, &trends_len, &trends_count) < 0) { #ifndef TRENDS_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_get_test_trends_failed"); #endif } if (trends_len <= 0 || trends_len >= MAX_LIST_BUFFER_LEN) { #ifndef TRENDS_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_invalid_trends_len"); #endif } ErlNifBinary trends_bin; int ret_val = 0; #ifdef ERLANG_R14B02 ret_val = enif_alloc_binary(trends_len, &trends_bin); #else ret_val = enif_alloc_binary(env, trends_len, &trends_bin); #endif if (ret_val < 0) { #ifndef TRENDS_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_tweet_len"); #endif } unsigned int i=0; for (i=0; i<trends_len; i++) { trends_bin.data[i] = *(trends_buffer + i); } ERL_NIF_TERM arg_array[1]; arg_array[0] = enif_make_binary(env, &trends_bin); ERL_NIF_TERM trends_list = nif_get_trends(env, 1, arg_array); if (enif_is_atom(env, trends_list)) { #ifndef TRENDS_DEBUG return enif_make_atom(env, "error"); #else return enif_make_atom(env, "error_get_trends_failed"); #endif } return trends_list; }
static int exmagick_get_utf8str (ErlNifEnv *env, const ERL_NIF_TERM arg, ErlNifBinary *utf8) { return(enif_inspect_binary(env, arg, utf8)); }
ERL_NIF_TERM final_encode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM head = argv[0]; ERL_NIF_TERM term; double number; encode_ctx ctx; ctx.env = env; ctx.fill_offset = 0; ctx.error = 0; if (!enif_alloc_binary_compat(env, 100, &ctx.bin)) { return no_mem_error(env); } while(enif_get_list_cell(env, head, &term, &head)) { ErlNifBinary termbin; const ERL_NIF_TERM* array; int arity; int code; // We scan the list, looking for things to write into the binary, or // encode and then write into the binary. We encode values that are // tuples tagged with a type and a value: {Type, Value} where Type // is a an Integer and Value is what is to be encoded if (enif_get_tuple(env, term, &arity, &array)) { // It's a tuple to encode and copy if (arity != 2 || !enif_get_int(env, array[0], &code)) { // not arity 2 or the first element isn't an int ctx.error = BADARG; goto done; } if (code == 0) { // {0, String} if (encode_string(&ctx, array[1]) != SUCCESS) { goto done; } } else { // {1, Double} if(!enif_get_double(env, array[1], &number)) { ctx.error = BADARG; goto done; } // We can't encode these. if (isnan(number) || isinf(number)) { ctx.error = BADARG; goto done; } if ((ctx.error = ensure_buffer(&ctx, 32)) != SUCCESS) { goto done; } // write the string into the buffer snprintf((char*)ctx.bin.data+ctx.fill_offset, 32, "%.16g", number); // increment the length ctx.fill_offset += strlen((char*)ctx.bin.data+ctx.fill_offset); } } else if (enif_inspect_binary(env, term, &termbin)) { // this is a regular binary, copy the contents into the buffer fill_buffer(&ctx, (char*)termbin.data, termbin.size); if (ctx.error) { goto done; } } else { //not a binary, not a tuple, wtf! ctx.error = BADARG; goto done; } } done: if (ctx.error == NOMEM) { enif_release_binary_compat(env, &ctx.bin); return no_mem_error(env); } else if (ctx.error == BADARG) { enif_release_binary_compat(env, &ctx.bin); return enif_make_badarg(env); } // Resize the binary to our exact final size if(!enif_realloc_binary_compat(env, &(ctx.bin), ctx.fill_offset)) { enif_release_binary_compat(env, &ctx.bin); return no_mem_error(env); } // make the binary term which transfers ownership return enif_make_binary(env, &ctx.bin); }
static ERL_NIF_TERM nif_scheduler_launchTasks(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { unsigned int length ; ErlNifBinary offerId_binary; ErlNifBinary filters_binary; state_ptr state = (state_ptr) enif_priv_data(env); if(state->initilised == 0 ) { return enif_make_tuple2(env, enif_make_atom(env, "state_error"), enif_make_atom(env, "scheduler_not_inited")); } if (!enif_inspect_binary(env, argv[0], &offerId_binary)) { return enif_make_tuple3(env, enif_make_atom(env, "argument_error"), enif_make_atom(env, "invalid_or_corrupted_parameter"), enif_make_atom(env, "offer_id")); } if(!enif_is_list(env, argv[1])) { return enif_make_tuple3(env, enif_make_atom(env, "argument_error"), enif_make_atom(env, "invalid_or_corrupted_parameter"), enif_make_atom(env, "task_info_array")); }; if(!enif_get_list_length(env, argv[1], &length)) { return enif_make_tuple3(env, enif_make_atom(env, "argument_error"), enif_make_atom(env, "invalid_or_corrupted_parameter"), enif_make_atom(env, "task_info_array")); } ErlNifBinary task_info_binary_arr[length]; if(!inspect_array_of_binary_objects(env, argv[1], &task_info_binary_arr )) { return enif_make_tuple3(env, enif_make_atom(env, "argument_error"), enif_make_atom(env, "invalid_or_corrupted_parameter"), enif_make_atom(env, "task_info_array")); } if (!enif_inspect_binary(env, argv[2], &filters_binary)) { return enif_make_tuple3(env, enif_make_atom(env, "argument_error"), enif_make_atom(env, "invalid_or_corrupted_parameter"), enif_make_atom(env, "filters")); } BinaryNifArray binaryNifArrayHolder ; binaryNifArrayHolder.length = length; binaryNifArrayHolder.obj = &task_info_binary_arr[0]; SchedulerDriverStatus status = scheduler_launchTasks(state->scheduler_state, &offerId_binary, &binaryNifArrayHolder, &filters_binary); return get_return_value_from_status(env, status); }
ERL_NIF_TERM make_encoder_resource_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]){ unsigned rs_len, fs_len, bin_sz; enif_get_uint(env, argv[0], &rs_len); enif_get_uint(env, argv[1], &fs_len); enif_get_uint(env, argv[4], &bin_sz); PrivData* priv = (PrivData*)enif_priv_data(env); unsigned resource_sz = enc_resource_size(rs_len, fs_len); EncEntry *enc_entry = (EncEntry*)enif_alloc_resource(priv->encoder_RSTYPE, resource_sz); //memset(enc_entry, 0, resource_sz); enc_entry->records_cnt = rs_len; enc_entry->fields_cnt = fs_len; if(!enif_alloc_binary(bin_sz + 1, &enc_entry->bin)) goto error; //memset(enc_entry->bin.data, 0, bin_sz + 1); ErlNifBinary ebin; enif_inspect_binary(env, argv[5], &ebin); memcpy(enc_entry->bin.data, ebin.data , ebin.size); ERL_NIF_TERM list, head, tail; list = argv[2]; int i = 0; while(enif_get_list_cell(env, list, &head, &tail)){ const ERL_NIF_TERM *tuple; int arity; unsigned ip; enif_get_tuple(env, head, &arity, &tuple); EncRecord *records = enc_records_base(enc_entry); records[i].tag = tuple[0]; enif_get_uint(env, tuple[1], &ip); records[i].fds_offset = ip; enif_get_uint(env, tuple[2], &ip); records[i].arity = ip; i++; list = tail; } list = argv[3]; i = 0; while(enif_get_list_cell(env, list, &head, &tail)){ const ERL_NIF_TERM *tuple; int arity; unsigned ip; enif_get_tuple(env, head, &arity, &tuple); EncField *fields = enc_fields_base(enc_entry); enif_get_uint(env, tuple[0], &ip); fields[i].offset = ip; enif_get_uint(env, tuple[1], &ip); fields[i].size = ip; i++; list = tail; } list = argv[6]; if(!enif_get_list_length(env, list, &(enc_entry->ignored_len))) goto error; enc_entry->ignored = (ERL_NIF_TERM*)enif_alloc(enc_entry->ignored_len*sizeof(ERL_NIF_TERM)); i = 0; while(enif_get_list_cell(env, list, &head, &tail)){ // ignored term should be atoms if(enif_is_atom(env, head)){ enc_entry->ignored[i] = head; }else{ enif_free(enc_entry->ignored); goto error; } i++; list = tail; } ERL_NIF_TERM ret = enif_make_resource(env, (void *)enc_entry); enif_release_resource(enc_entry); return ret; error: enif_release_resource(enc_entry); return enif_make_badarg(env); }
int less_ejson(int depth, couch_ejson_ctx_t* ctx, ERL_NIF_TERM a, ERL_NIF_TERM b) { int aIsAtom, bIsAtom; int aIsBin, bIsBin; int aIsNumber, bIsNumber; int aIsList, bIsList; int aArity, bArity; const ERL_NIF_TERM *aProps, *bProps; /* * Avoid too much recursion. Normally there isn't more than a few levels * of recursion, as in practice view keys do not go beyond 1 to 3 levels * of nesting. In case of too much recursion, signal it to the Erlang land * via an exception and do the EJSON comparison in Erlang land. */ if (depth > MAX_DEPTH) { ctx->error = 1; return 0; } aIsAtom = enif_is_atom(ctx->env, a); bIsAtom = enif_is_atom(ctx->env, b); if (aIsAtom) { if (bIsAtom) { int aSortOrd, bSortOrd; if ((aSortOrd = atom_sort_order(ctx->env, a)) == -1) { ctx->error = 1; return 0; } if ((bSortOrd = atom_sort_order(ctx->env, b)) == -1) { ctx->error = 1; return 0; } return aSortOrd - bSortOrd; } return -1; } if (bIsAtom) { return 1; } aIsNumber = term_is_number(ctx->env, a); bIsNumber = term_is_number(ctx->env, b); if (aIsNumber) { if (bIsNumber) { return enif_compare_compat(ctx->env, a, b); } return -1; } if (bIsNumber) { return 1; } aIsBin = enif_is_binary(ctx->env, a); bIsBin = enif_is_binary(ctx->env, b); if (aIsBin) { if (bIsBin) { ErlNifBinary binA, binB; enif_inspect_binary(ctx->env, a, &binA); enif_inspect_binary(ctx->env, b, &binB); return compare_strings(ctx, binA, binB); } return -1; } if (bIsBin) { return 1; } aIsList = enif_is_list(ctx->env, a); bIsList = enif_is_list(ctx->env, b); if (aIsList) { if (bIsList) { return compare_lists(depth, ctx, a, b); } return -1; } if (bIsList) { return 1; } if (!enif_get_tuple(ctx->env, a, &aArity, &aProps)) { ctx->error = 1; return 0; } if ((aArity != 1) || !enif_is_list(ctx->env, aProps[0])) { ctx->error = 1; return 0; } if (!enif_get_tuple(ctx->env, b, &bArity, &bProps)) { ctx->error = 1; return 0; } if ((bArity != 1) || !enif_is_list(ctx->env, bProps[0])) { ctx->error = 1; return 0; } return compare_props(depth, ctx, aProps[0], bProps[0]); }