static JSBool from_gbytes_func(JSContext *context, unsigned argc, jsval *vp) { JS::CallArgs argv = JS::CallArgsFromVp (argc, vp); JSObject *bytes_obj; GBytes *gbytes; ByteArrayInstance *priv; JSObject *obj; JSBool ret = JS_FALSE; if (!gjs_parse_call_args(context, "overrides_gbytes_to_array", "o", argv, "bytes", &bytes_obj)) return JS_FALSE; if (!gjs_typecheck_boxed(context, bytes_obj, NULL, G_TYPE_BYTES, TRUE)) return JS_FALSE; gbytes = (GBytes*) gjs_c_struct_from_boxed(context, bytes_obj); obj = byte_array_new(context); if (obj == NULL) return JS_FALSE; priv = priv_from_js(context, obj); g_assert (priv != NULL); priv->bytes = g_bytes_ref(gbytes); ret = JS_TRUE; argv.rval().set(OBJECT_TO_JSVAL(obj)); return ret; }
struct byte_array *byte_array_new_data(uint32_t size, uint8_t *data) { struct byte_array *ba = byte_array_new(); ba->size = ba->length = size; ba->data = ba->current = data; return ba; }
struct variable *sys_save(struct context *context) { struct variable *args = (struct variable*)stack_pop(context->operand_stack); struct variable *v = param_var(args, 1); struct variable *path = param_var(args, 2); struct byte_array *bytes = byte_array_new(); variable_serialize(context, bytes, v); int w = write_file(path->str, bytes, 0, -1); byte_array_del(bytes); return variable_new_int(context, w); }
struct byte_array* serial_encode_string(struct byte_array* buf, const struct byte_array* bytes) { if (!bytes) return buf; if (!buf) buf = byte_array_new(); encode_int(buf, bytes->length); byte_array_resize(buf, buf->length + bytes->length); memcpy(buf->current, bytes->data, bytes->length); buf->current = buf->data + buf->length; return buf; }
struct byte_array *encode_int(struct byte_array *buf, int32_t value) { if (!buf) buf = byte_array_new(); uint8_t growth = encode_int_size(value); byte_array_resize(buf, buf->length + growth); bool neg = value < 0; value = abs(value); uint8_t byte = (value & 0x3F) | ((value >= 0x40) ? 0x80 : 0) | (neg ? 0x40 : 0); *buf->current++ = byte; value >>= 6; while (value) { byte = (value & 0x7F) | ((value >= 0x80) ? 0x80 : 0); *buf->current++ = byte; value >>= 7; } return buf; }
struct byte_array* serial_encode_int(struct byte_array* buf, int32_t value) { if (!buf) buf = byte_array_new(); encode_int(buf, value); return buf; }
struct byte_array* serial_encode_float(struct byte_array* buf, float value) { if (!buf) buf = byte_array_new(); encode_float(buf, value); return buf; }
/* fromArray() function implementation */ static JSBool from_array_func(JSContext *context, unsigned argc, jsval *vp) { JS::CallArgs argv = JS::CallArgsFromVp (argc, vp); ByteArrayInstance *priv; guint32 len; guint32 i; JSObject *obj; JSBool ret = JS_FALSE; obj = byte_array_new(context); if (obj == NULL) return JS_FALSE; JS_AddObjectRoot(context, &obj); priv = priv_from_js(context, obj); g_assert (priv != NULL); g_assert(argc > 0); /* because we specified min args 1 */ priv->array = gjs_g_byte_array_new(0); if (!JS_IsArrayObject(context, JSVAL_TO_OBJECT(argv[0]))) { gjs_throw(context, "byteArray.fromArray() called with non-array as first arg"); goto out; } if (!JS_GetArrayLength(context, JSVAL_TO_OBJECT(argv[0]), &len)) { gjs_throw(context, "byteArray.fromArray() can't get length of first array arg"); goto out; } g_byte_array_set_size(priv->array, len); for (i = 0; i < len; ++i) { jsval elem; guint8 b; elem = JSVAL_VOID; if (!JS_GetElement(context, JSVAL_TO_OBJECT(argv[0]), i, &elem)) { /* this means there was an exception, while elem == JSVAL_VOID * means no element found */ goto out; } if (JSVAL_IS_VOID(elem)) continue; if (!gjs_value_to_byte(context, elem, &b)) goto out; g_array_index(priv->array, guint8, i) = b; } ret = JS_TRUE; argv.rval().set(OBJECT_TO_JSVAL(obj)); out: JS_RemoveObjectRoot(context, &obj); return ret; }
/* fromString() function implementation */ static JSBool from_string_func(JSContext *context, unsigned argc, jsval *vp) { JS::CallArgs argv = JS::CallArgsFromVp (argc, vp); ByteArrayInstance *priv; char *encoding; gboolean encoding_is_utf8; JSObject *obj; JSBool retval = JS_FALSE; obj = byte_array_new(context); if (obj == NULL) return JS_FALSE; JS_AddObjectRoot(context, &obj); priv = priv_from_js(context, obj); g_assert (priv != NULL); g_assert(argc > 0); /* because we specified min args 1 */ priv->array = gjs_g_byte_array_new(0); if (!JSVAL_IS_STRING(argv[0])) { gjs_throw(context, "byteArray.fromString() called with non-string as first arg"); goto out; } if (argc > 1 && JSVAL_IS_STRING(argv[1])) { if (!gjs_string_to_utf8(context, argv[1], &encoding)) goto out; /* maybe we should be smarter about utf8 synonyms here. * doesn't matter much though. encoding_is_utf8 is * just an optimization anyway. */ if (strcmp(encoding, "UTF-8") == 0) { encoding_is_utf8 = TRUE; g_free(encoding); encoding = NULL; } else { encoding_is_utf8 = FALSE; } } else { encoding_is_utf8 = TRUE; } if (encoding_is_utf8) { /* optimization? avoids iconv overhead and runs * libmozjs hardwired utf16-to-utf8. */ char *utf8 = NULL; if (!gjs_string_to_utf8(context, argv[0], &utf8)) goto out; g_byte_array_set_size(priv->array, 0); g_byte_array_append(priv->array, (guint8*) utf8, strlen(utf8)); g_free(utf8); } else { char *encoded; gsize bytes_written; GError *error; const jschar *u16_chars; gsize u16_len; u16_chars = JS_GetStringCharsAndLength(context, JSVAL_TO_STRING(argv[0]), &u16_len); if (u16_chars == NULL) goto out; error = NULL; encoded = g_convert((char*) u16_chars, u16_len * 2, encoding, /* to_encoding */ "UTF-16", /* from_encoding */ NULL, /* bytes read */ &bytes_written, &error); g_free(encoding); if (encoded == NULL) { /* frees the GError */ gjs_throw_g_error(context, error); goto out; } g_byte_array_set_size(priv->array, 0); g_byte_array_append(priv->array, (guint8*) encoded, bytes_written); g_free(encoded); } argv.rval().set(OBJECT_TO_JSVAL(obj)); retval = JS_TRUE; out: JS_RemoveObjectRoot(context, &obj); return retval; }