JSBool http_set_hdr(JSContext* cx, JSObject* req, jsval name, jsval val) { HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req); char* keystr = NULL; char* valstr = NULL; char* hdrbuf = NULL; size_t hdrlen = -1; JSBool ret = JS_FALSE; if(!http) { JS_ReportError(cx, "Invalid CouchHTTP instance."); goto done; } if(JSVAL_IS_VOID(name)) { JS_ReportError(cx, "You must speciy a header name."); goto done; } keystr = enc_string(cx, name, NULL); if(!keystr) { JS_ReportError(cx, "Failed to encode header name."); goto done; } if(JSVAL_IS_VOID(val)) { JS_ReportError(cx, "You must specify a header value."); goto done; } valstr = enc_string(cx, val, NULL); if(!valstr) { JS_ReportError(cx, "Failed to encode header value."); goto done; } hdrlen = strlen(keystr) + strlen(valstr) + 3; hdrbuf = (char*) malloc(hdrlen * sizeof(char)); if(!hdrbuf) { JS_ReportError(cx, "Failed to allocate header buffer."); goto done; } snprintf(hdrbuf, hdrlen, "%s: %s", keystr, valstr); http->req_headers = curl_slist_append(http->req_headers, hdrbuf); ret = JS_TRUE; done: if(keystr) free(keystr); if(valstr) free(valstr); if(hdrbuf) free(hdrbuf); return ret; }
JSBool http_send(JSContext* cx, JSObject* req, jsval body) { HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req); char* bodystr = NULL; size_t bodylen = 0; JSBool ret = JS_FALSE; if(!http) { JS_ReportError(cx, "Invalid CouchHTTP instance."); goto done; } if(!JSVAL_IS_VOID(body)) { bodystr = enc_string(cx, body, &bodylen); if(!bodystr) { JS_ReportError(cx, "Failed to encode body."); goto done; } } ret = go(cx, req, http, bodystr, bodylen); done: if(bodystr) free(bodystr); return ret; }
static JSBool sendreq(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval) { HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj); char* body = NULL; size_t bodylen = 0; JSBool ret = JS_FALSE; if(!http) { JS_ReportError(cx, "Invalid CouchHTTP instance."); goto done; } if(argv[0] != JSVAL_VOID && argv[0] != JS_GetEmptyStringValue(cx)) { body = enc_string(cx, argv[0], &bodylen); if(!body) { JS_ReportError(cx, "Failed to encode body."); goto done; } } ret = go(cx, obj, http, body, bodylen); done: if(body) free(body); return ret; }
static JSBool evalcx(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { JSString *str; JSObject *sandbox; JSContext *subcx; const jschar *src; size_t srclen; JSBool ret = JS_FALSE; char *name = NULL; sandbox = NULL; if(!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sandbox)) { return JS_FALSE; } subcx = JS_NewContext(JS_GetRuntime(cx), 8L * 1024L); if(!subcx) { JS_ReportOutOfMemory(cx); return JS_FALSE; } SETUP_REQUEST(subcx); src = JS_GetStringChars(str); srclen = JS_GetStringLength(str); if(!sandbox) { sandbox = JS_NewObject(subcx, NULL, NULL, NULL); if(!sandbox || !JS_InitStandardClasses(subcx, sandbox)) { goto done; } } if(argc > 2) { name = enc_string(cx, argv[2], NULL); } if(srclen == 0) { *rval = OBJECT_TO_JSVAL(sandbox); } else { JS_EvaluateUCScript(subcx, sandbox, src, srclen, name, 1, rval); } ret = JS_TRUE; done: if(name) JS_free(cx, name); FINISH_REQUEST(subcx); JS_DestroyContext(subcx); return ret; }
void couch_print(JSContext* cx, uintN argc, jsval* argv) { char *bytes; uintN i; for(i = 0; i < argc; i++) { bytes = enc_string(cx, argv[i], NULL); if(!bytes) return; fprintf(stdout, "%s%s", i ? " " : "", bytes); JS_free(cx, bytes); } fputc('\n', stdout); fflush(stdout); }
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; }
static JSBool go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen) { CurlState state; char* referer; JSString* jsbody; JSBool ret = JS_FALSE; jsval tmp; state.cx = cx; state.http = http; state.sendbuf = body; state.sendlen = bodylen; state.sent = 0; state.sent_once = 0; state.recvbuf = NULL; state.recvlen = 0; state.read = 0; if(HTTP_HANDLE == NULL) { HTTP_HANDLE = curl_easy_init(); curl_easy_setopt(HTTP_HANDLE, CURLOPT_READFUNCTION, send_body); curl_easy_setopt(HTTP_HANDLE, CURLOPT_SEEKFUNCTION, (curl_seek_callback) seek_body); curl_easy_setopt(HTTP_HANDLE, CURLOPT_HEADERFUNCTION, recv_header); curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEFUNCTION, recv_body); curl_easy_setopt(HTTP_HANDLE, CURLOPT_NOPROGRESS, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_easy_setopt(HTTP_HANDLE, CURLOPT_ERRORBUFFER, ERRBUF); curl_easy_setopt(HTTP_HANDLE, CURLOPT_COOKIEFILE, ""); curl_easy_setopt(HTTP_HANDLE, CURLOPT_USERAGENT, "CouchHTTP Client - Relax"); } if(!HTTP_HANDLE) { JS_ReportError(cx, "Failed to initialize cURL handle."); goto done; } if(!JS_GetReservedSlot(cx, obj, 0, &tmp)) { JS_ReportError(cx, "Failed to readreserved slot."); goto done; } if(!(referer = enc_string(cx, tmp, NULL))) { JS_ReportError(cx, "Failed to encode referer."); goto done; } curl_easy_setopt(HTTP_HANDLE, CURLOPT_REFERER, referer); free(referer); if(http->method < 0 || http->method > OPTIONS) { JS_ReportError(cx, "INTERNAL: Unknown method."); goto done; } curl_easy_setopt(HTTP_HANDLE, CURLOPT_CUSTOMREQUEST, METHODS[http->method]); curl_easy_setopt(HTTP_HANDLE, CURLOPT_NOBODY, 0); curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_UPLOAD, 0); if(http->method == HEAD) { curl_easy_setopt(HTTP_HANDLE, CURLOPT_NOBODY, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 0); } else if(http->method == POST || http->method == PUT) { curl_easy_setopt(HTTP_HANDLE, CURLOPT_UPLOAD, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 0); } if(body && bodylen) { curl_easy_setopt(HTTP_HANDLE, CURLOPT_INFILESIZE, bodylen); } else { curl_easy_setopt(HTTP_HANDLE, CURLOPT_INFILESIZE, 0); } // curl_easy_setopt(HTTP_HANDLE, CURLOPT_VERBOSE, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_URL, http->url); curl_easy_setopt(HTTP_HANDLE, CURLOPT_HTTPHEADER, http->req_headers); curl_easy_setopt(HTTP_HANDLE, CURLOPT_READDATA, &state); curl_easy_setopt(HTTP_HANDLE, CURLOPT_SEEKDATA, &state); curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEHEADER, &state); curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEDATA, &state); if(curl_easy_perform(HTTP_HANDLE) != 0) { JS_ReportError(cx, "Failed to execute HTTP request: %s", ERRBUF); goto done; } if(!state.resp_headers) { JS_ReportError(cx, "Failed to recieve HTTP headers."); goto done; } tmp = OBJECT_TO_JSVAL(state.resp_headers); if(!JS_DefineProperty( cx, obj, "_headers", tmp, NULL, NULL, JSPROP_READONLY )) { JS_ReportError(cx, "INTERNAL: Failed to set response headers."); goto done; } if(state.recvbuf) { state.recvbuf[state.read] = '\0'; jsbody = dec_string(cx, state.recvbuf, state.read+1); if(!jsbody) { // If we can't decode the body as UTF-8 we forcefully // convert it to a string by just forcing each byte // to a jschar. jsbody = str_from_binary(cx, state.recvbuf, state.read); if(!jsbody) { if(!JS_IsExceptionPending(cx)) { JS_ReportError(cx, "INTERNAL: Failed to decode body."); } goto done; } } tmp = STRING_TO_JSVAL(jsbody); } else { tmp = JS_GetEmptyStringValue(cx); } if(!JS_DefineProperty( cx, obj, "responseText", tmp, NULL, NULL, JSPROP_READONLY )) { JS_ReportError(cx, "INTERNAL: Failed to set responseText."); goto done; } ret = JS_TRUE; done: if(state.recvbuf) JS_free(cx, state.recvbuf); return ret; }
JSBool http_open(JSContext* cx, JSObject* req, jsval mth, jsval url, jsval snc) { HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req); char* method = NULL; int methid; JSBool ret = JS_FALSE; if(!http) { JS_ReportError(cx, "Invalid CouchHTTP instance."); goto done; } if(JSVAL_IS_VOID(mth)) { JS_ReportError(cx, "You must specify a method."); goto done; } method = enc_string(cx, mth, NULL); if(!method) { JS_ReportError(cx, "Failed to encode method."); goto done; } for(methid = 0; METHODS[methid] != NULL; methid++) { if(strcasecmp(METHODS[methid], method) == 0) break; } if(methid > OPTIONS) { JS_ReportError(cx, "Invalid method specified."); goto done; } http->method = methid; if(JSVAL_IS_VOID(url)) { JS_ReportError(cx, "You must specify a URL."); goto done; } if(http->url != NULL) { free(http->url); http->url = NULL; } http->url = enc_string(cx, url, NULL); if(http->url == NULL) { JS_ReportError(cx, "Failed to encode URL."); goto done; } if(JSVAL_IS_BOOLEAN(snc) && JSVAL_TO_BOOLEAN(snc)) { JS_ReportError(cx, "Synchronous flag must be false."); goto done; } if(http->req_headers) { curl_slist_free_all(http->req_headers); http->req_headers = NULL; } // Disable Expect: 100-continue http->req_headers = curl_slist_append(http->req_headers, "Expect:"); ret = JS_TRUE; done: if(method) free(method); return ret; }
static JSBool open(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval) { HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj); char* method = NULL; char* url = NULL; JSBool ret = JS_FALSE; int methid; if(!http) { JS_ReportError(cx, "Invalid CouchHTTP instance."); goto done; } if(argv[0] == JSVAL_VOID) { JS_ReportError(cx, "You must specify a method."); goto done; } method = enc_string(cx, argv[0], NULL); if(!method) { JS_ReportError(cx, "Failed to encode method."); goto done; } for(methid = 0; METHODS[methid] != NULL; methid++) { if(strcasecmp(METHODS[methid], method) == 0) break; } if(methid > COPY) { JS_ReportError(cx, "Invalid method specified."); goto done; } http->method = methid; if(argv[1] == JSVAL_VOID) { JS_ReportError(cx, "You must specify a URL."); goto done; } if(http->url) { free(http->url); http->url = NULL; } http->url = enc_string(cx, argv[1], NULL); if(!http->url) { JS_ReportError(cx, "Failed to encode URL."); goto done; } if(argv[2] != JSVAL_VOID && argv[2] != JSVAL_FALSE) { JS_ReportError(cx, "Synchronous flag must be false if specified."); goto done; } if(http->req_headers) { curl_slist_free_all(http->req_headers); http->req_headers = NULL; } // Disable Expect: 100-continue http->req_headers = curl_slist_append(http->req_headers, "Expect:"); ret = JS_TRUE; done: if(method) free(method); return ret; }
ERL_NIF_TERM encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { Encoder* e; jiffy_st* st = (jiffy_st*) enif_priv_data(env); ERL_NIF_TERM ret = 0; ERL_NIF_TERM stack; ERL_NIF_TERM curr; ERL_NIF_TERM item; const ERL_NIF_TERM* tuple; int arity; ErlNifSInt64 lval; double dval; size_t start; size_t processed; if(argc != 3) { return enif_make_badarg(env); } else if(!enif_get_resource(env, argv[0], st->res_enc, (void**) &e)) { return enif_make_badarg(env); } else if(!enif_is_list(env, argv[1])) { return enif_make_badarg(env); } else if(!enif_is_list(env, argv[2])) { return enif_make_badarg(env); } if(!enc_init(e, env)) { return enif_make_badarg(env); } stack = argv[1]; e->iolist = argv[2]; start = e->iosize + e->i; while(!enif_is_empty_list(env, stack)) { processed = (e->iosize + e->i) - start; if(should_yield(processed, e->bytes_per_iter)) { consume_timeslice(env, processed, e->bytes_per_iter); return enif_make_tuple4( env, st->atom_iter, argv[0], stack, e->iolist ); } 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_obj_error(e, "invalid_object_member", item); goto done; } if(arity != 2) { ret = enc_obj_error(e, "invalid_object_member_arity", item); goto done; } if(!enc_comma(e)) { ret = enc_error(e, "internal_error"); goto done; } if(!enc_string(e, tuple[0])) { ret = enc_obj_error(e, "invalid_object_member_key", tuple[0]); 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(e->use_nil && enif_compare(curr, e->atoms->atom_nil) == 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_obj_error(e, "invalid_string", curr); goto done; } } else if(enif_is_atom(env, curr)) { if(!enc_string(e, curr)) { ret = enc_obj_error(e, "invalid_string", curr); 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)) { ret = enc_obj_error(e, "invalid_ejson", curr); goto done; #if MAP_TYPE_PRESENT } else if(enif_is_map(env, curr)) { if(!enc_map_to_ejson(env, curr, &curr)) { ret = enc_error(e, "internal_error"); goto done; } stack = enif_make_list_cell(env, curr, stack); #endif } else if(enif_is_list(env, curr)) { if(enif_is_empty_list(env, curr)) { if(!enc_start_array(e) || !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; } if(!enif_get_tuple(env, item, &arity, &tuple)) { if(!enc_start_array(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_array, stack); stack = enif_make_list_cell(env, item, stack); } else { if(!enc_start_object(e)) { ret = enc_error(e, "internal_error"); goto done; } if(arity == 0) { if(!enc_end_object(e)) { ret = enc_error(e, "internal_error"); goto done; } continue; } else if(arity != 2) { ret = enc_obj_error(e, "invalid_object_member_arity", item); goto done; } if(!enc_string(e, tuple[0])) { ret = enc_obj_error(e, "invalid_object_member_key", tuple[0]); 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(!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: processed = (e->iosize + e->i) - start; consume_timeslice(env, processed, e->bytes_per_iter); return ret; }