void* to_erl(JSContext* cx, jsval val, int* length) { emonk_buf_t buf; char* ret; buf.size = 1024; buf.used = 1; // VERSION_MAGIC buf.buf = (unsigned char*) driver_alloc(buf.size * sizeof(char)); if(buf.buf == NULL) return NULL; buf.buf[0] = VERSION_MAGIC; if(!to_erl_intern(&buf, cx, val)) { driver_free(buf.buf); return NULL; } ret = driver_realloc(buf.buf, buf.used); if(ret == NULL) { if(buf.buf != NULL) driver_free(buf.buf); return NULL; } *length = buf.used; return ret; }
int to_erl_object(emonk_buf_t* buf, JSContext* cx, JSObject* obj) { JSObject* iter; JSString* key; jsid idp; jsval val; jschar* keyname; size_t keylen; int count = 0; int lengthpos; REQUEST(7); BUFPTR[0] = SMALL_TUPLE; BUFPTR[1] = (char) 1; BUFPTR[2] = LIST; // Remember the byte offset where length goes so we can write it // after enumerating the properties. lengthpos = buf->used + 3; buf->used += 7; iter = JS_NewPropertyIterator(cx, obj); if(iter == NULL) return ERROR; while(JS_NextProperty(cx, iter, &idp)) { // Done iterating, write length and bail. if(idp == JSVAL_VOID) { count = htonl(count); memcpy(buf->buf+lengthpos, &count, 4); REQUEST(1); BUFPTR[0] = NIL; buf->used += 1; return OK; } REQUEST(2); BUFPTR[0] = SMALL_TUPLE; BUFPTR[1] = 2; buf->used += 2; if(!JS_IdToValue(cx, idp, &val)) return ERROR; if(!to_erl_string(buf, cx, val)) return ERROR; key = JS_ValueToString(cx, val); keyname = JS_GetStringChars(key); keylen = JS_GetStringLength(key); if(!JS_GetUCProperty(cx, obj, keyname, keylen, &val)) return ERROR; if(!to_erl_intern(buf, cx, val)) return ERROR; count += 1; } return ERROR; }
int to_erl_array(emonk_buf_t* buf, JSContext* cx, JSObject* obj) { unsigned int length, nlen; jsval v; int i; if(!JS_GetArrayLength(cx, obj, &length)) return ERROR; REQUEST(5); BUFPTR[0] = LIST; nlen = htonl(length); memcpy(BUFPTR+1, &nlen, 4); buf->used += 5; for(i = 0; i < length; i++) { if(!JS_GetElement(cx, obj, i, &v)) return ERROR; if(!to_erl_intern(buf, cx, v)) return ERROR; } REQUEST(1); BUFPTR[0] = NIL; buf->used += 1; return OK; }
int to_erl_array(ErlNifEnv* env, JSContext* cx, JSObject* obj, ERL_NIF_TERM* term) { ERL_NIF_TERM* array = NULL; int ret = ERROR; unsigned int length; jsval v; int i; if(!JS_GetArrayLength(cx, obj, &length)) return ERROR; array = (ERL_NIF_TERM*) enif_alloc(length * sizeof(ERL_NIF_TERM)); if(array == NULL) goto done; for(i = 0; i < length; i++) { if(!JS_GetElement(cx, obj, i, &v)) goto done; if(!to_erl_intern(env, cx, v, array+i)) goto done; } *term = enif_make_list_from_array(env, array, length); ret = OK; done: if(array != NULL) enif_free(array); return ret; }
int to_erl_object(ErlNifEnv* env, JSContext* cx, JSObject* obj, ERL_NIF_TERM* term) { ERL_NIF_TERM* array = NULL; ERL_NIF_TERM list; ERL_NIF_TERM keyterm; ERL_NIF_TERM valterm; JSObject* iter; jsid idp; jsval val; int length; int index; int ret = ERROR; iter = JS_NewPropertyIterator(cx, obj); if(iter == NULL) goto done; length = 0; while(JS_NextProperty(cx, iter, &idp)) { if(idp == JSID_VOID) break; length += 1; } array = enif_alloc(length * sizeof(ERL_NIF_TERM)); if(array == NULL) goto done; iter = JS_NewPropertyIterator(cx, obj); if(iter == NULL) goto done; index = 0; while(JS_NextProperty(cx, iter, &idp)) { if(idp == JSID_VOID) { list = enif_make_list_from_array(env, array, length); *term = enif_make_tuple1(env, list); ret = OK; goto done; } if(!JS_IdToValue(cx, idp, &val)) goto done; if(!to_erl_string(env, cx, val, &keyterm)) goto done; if(!JS_GetPropertyById(cx, obj, idp, &val)) goto done; if(!to_erl_intern(env, cx, val, &valterm)) goto done; array[index] = enif_make_tuple2(env, keyterm, valterm); index += 1; } done: if(array != NULL) enif_free(array); return ret; }
ERL_NIF_TERM to_erl(ErlNifEnv* env, JSContext* cx, jsval val) { ERL_NIF_TERM ret = util_mk_atom(env, "undefined"); if(!to_erl_intern(env, cx, val, &ret)) { return util_mk_atom(env, "undefined"); } return ret; }
int to_erl_from_handler(emonk_buf_t* buf, JSContext* cx, JSObject* obj) { JSObject* func; jsval tojson; jsval rval; if(!JS_GetProperty(cx, obj, "toJSON", &tojson)) { return ERROR; } if(!JSVAL_IS_OBJECT(tojson)) return IGNORE; func = JSVAL_TO_OBJECT(tojson); if(func == NULL) return ERROR; if(!JS_ObjectIsFunction(cx, func)) return IGNORE; if(!JS_CallFunctionValue(cx, obj, tojson, 0, NULL, &rval)) { return ERROR; } return to_erl_intern(buf, cx, rval); }
int to_erl_convert(ErlNifEnv* env, JSContext* cx, JSObject* obj, ERL_NIF_TERM* term) { JSObject* func; jsval tojson; jsval rval; if(!JS_GetProperty(cx, obj, "toJSON", &tojson)) { return ERROR; } if(!JSVAL_IS_OBJECT(tojson)) return ERROR; func = JSVAL_TO_OBJECT(tojson); if(func == NULL) return ERROR; if(!JS_ObjectIsFunction(cx, func)) return ERROR; if(!JS_CallFunctionValue(cx, obj, tojson, 0, NULL, &rval)) { return ERROR; } return to_erl_intern(env, cx, rval, term); }