diff options
Diffstat (limited to 'libseed/seed-types.c')
-rw-r--r-- | libseed/seed-types.c | 144 |
1 files changed, 141 insertions, 3 deletions
diff --git a/libseed/seed-types.c b/libseed/seed-types.c index 51208e0..722f265 100644 --- a/libseed/seed-types.c +++ b/libseed/seed-types.c @@ -312,6 +312,92 @@ seed_gi_make_jsarray(JSContextRef ctx, return ret; } +JSValueRef +seed_array_from_zero_terminated_c_array(JSContextRef ctx, + gpointer pointer, + GITypeInfo* param_info, + JSValueRef* exception) +{ + JSObjectRef ret; + GITypeTag element_type; + GArgument arg; + guint i; + + element_type = g_type_info_get_tag(param_info); + + // Special case handling array(guint8), which happens to be a string + // in most cases + if (element_type == GI_TYPE_TAG_UINT8) { + // TODO: this is pretty simple and probably incomplete. + // GJS makes possible the return of an array, supporting + // all types. We're only supporting strings ATM. + ret = seed_value_from_string(ctx, pointer, exception); + return ret; + } + + ret = JSObjectMakeArray(ctx, NULL, NULL, NULL); + +#define ITERATE(type) \ + do { \ + g##type* array = (g##type*) pointer; \ + for (i = 0; array[i]; i++) { \ + arg.v_##type = array[i]; \ + JSValueRef val \ + = seed_value_from_gi_argument(ctx, &arg, param_info, exception); \ + seed_object_set_property_at_index(ctx, ret, i, val, exception); \ + } \ + } while (0); + + switch (element_type) { + /* We handle GI_TYPE_TAG_UINT8 above. */ + case GI_TYPE_TAG_INT8: + ITERATE(int8); + break; + case GI_TYPE_TAG_UINT16: + ITERATE(uint16); + break; + case GI_TYPE_TAG_INT16: + ITERATE(int16); + break; + case GI_TYPE_TAG_UINT32: + ITERATE(uint32); + break; + case GI_TYPE_TAG_INT32: + ITERATE(int32); + break; + case GI_TYPE_TAG_UINT64: + ITERATE(uint64); + break; + case GI_TYPE_TAG_INT64: + ITERATE(int64); + break; + case GI_TYPE_TAG_FLOAT: + ITERATE(float); + break; + case GI_TYPE_TAG_DOUBLE: + ITERATE(double); + break; + case GI_TYPE_TAG_GTYPE: + case GI_TYPE_TAG_UTF8: + case GI_TYPE_TAG_FILENAME: + case GI_TYPE_TAG_ARRAY: + case GI_TYPE_TAG_INTERFACE: + case GI_TYPE_TAG_GLIST: + case GI_TYPE_TAG_GSLIST: + case GI_TYPE_TAG_GHASH: + case GI_TYPE_TAG_ERROR: + ITERATE(pointer); + break; + default: + seed_make_exception(ctx, exception, "Argumenterror", + "Unknown element-type %d", element_type); + } + +#undef ITERATE + + return ret; +} + static gboolean seed_gi_make_array_from_string(JSContextRef ctx, JSStringRef js_string, @@ -331,18 +417,29 @@ seed_gi_make_array_from_string(JSContextRef ctx, guint real_size = JSStringGetUTF8CString(js_string, buffer, length); switch (element_type) { + case GI_TYPE_TAG_INT8: case GI_TYPE_TAG_UINT8: { *array_p = buffer; + + // So, GJS doesn't computer the \0 at the end of line. + // it does make sense, as converting a string to an array + // we don't want the EOS. However, I couldn't find a way to do it + // with + // JSC, so I'm basically reducing one byte. + if (out_array_length) + *out_array_length = real_size - 1; break; } + case GI_TYPE_TAG_INT16: + case GI_TYPE_TAG_UINT16: + // TODO: implement utf16 support default: { seed_make_exception(ctx, exception, "ArgumentError", - "Unhandled array element type"); + "Cannot convert string to array of '%s'", + g_type_tag_to_string(element_type)); return FALSE; } } - if (out_array_length) - *out_array_length = real_size; return TRUE; } @@ -994,6 +1091,21 @@ seed_value_from_gi_argument_full(JSContextRef ctx, g_base_info_unref((GIBaseInfo*) array_type_info); return ret_ptr_array; + } else if (array_type == GI_ARRAY_TYPE_C) { + + if (g_type_info_is_zero_terminated(type_info)) { + GITypeInfo* param_info; + param_info = g_type_info_get_param_type(type_info, 0); + g_assert(param_info != NULL); + + ret = seed_array_from_zero_terminated_c_array( + ctx, arg->v_pointer, param_info, exception); + + g_base_info_unref((GIBaseInfo*) param_info); + g_base_info_unref((GIBaseInfo*) array_type_info); + + return ret; + } } // technically gir has arrays of bytes, eg. @@ -1063,6 +1175,32 @@ seed_value_from_gi_argument_full(JSContextRef ctx, g_base_info_unref(interface); return seed_value_from_long(ctx, arg->v_long, exception); } else if (interface_type == GI_INFO_TYPE_STRUCT) { + + // Trying to find out if this struct can be converted into + // GValue + // If it can be converted, just send the converted value back to + // JS context instead + // of the GValue itself. + GType gtype = g_registered_type_info_get_g_type( + (GIRegisteredTypeInfo*) interface); + if (G_TYPE_IS_INSTANTIATABLE(gtype) + || G_TYPE_IS_INTERFACE(gtype)) + gtype = G_TYPE_FROM_INSTANCE(arg->v_pointer); + + SEED_NOTE(INVOCATION, "gtype of INTERFACE is %s", + g_type_name(gtype)); + if (g_type_is_a(gtype, G_TYPE_VALUE)) { + JSValueRef ret; + // We're using seed_value_from_gvalue_for_signal with NULL + // signal handler + // the current code will only handle basic types. + if ((ret = seed_value_from_gvalue_for_signal( + ctx, arg->v_pointer, exception, NULL, 0))) { + g_base_info_unref(interface); + return ret; + } + } + JSValueRef strukt; strukt = seed_make_struct(ctx, arg->v_pointer, interface); |