summaryrefslogtreecommitdiff
path: root/libseed/seed-types.c
diff options
context:
space:
mode:
Diffstat (limited to 'libseed/seed-types.c')
-rw-r--r--libseed/seed-types.c144
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);