[seed] Adding support for array lengh prediction.



commit 2cf5841a6eba1c8d7240a9482ed6944105d75e60
Author: Danilo Cesar Lemes de Paula <danilo cesar collabora co uk>
Date:   Wed Feb 3 16:31:29 2016 -0200

    Adding support for array lengh prediction.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=761517
    
    When user sends a string to a GI method that expects a regular gchar
    array, usually it requires the user to also send the length of that
    array.
    
    That shouldn't be necessary as the engine can guess that size.
    
    This is the behaviour this patch is implementing.

 libseed/seed-closure.c |    1 +
 libseed/seed-engine.c  |   43 +++++++++++++++++++++++++++++++------------
 libseed/seed-structs.c |    2 ++
 libseed/seed-types.c   |   41 ++++++++++++++++++++++++++++++++---------
 libseed/seed-types.h   |    8 ++++++++
 5 files changed, 74 insertions(+), 21 deletions(-)
---
diff --git a/libseed/seed-closure.c b/libseed/seed-closure.c
index 953c720..dc88258 100644
--- a/libseed/seed-closure.c
+++ b/libseed/seed-closure.c
@@ -185,6 +185,7 @@ seed_handle_closure(ffi_cif* cif, void* result, void** args, gpointer userdata)
 
     seed_value_to_gi_argument(ctx, (JSValueRef) return_value, return_type,
                               GI_TRANSFER_NOTHING, &return_arg, 0);
+
     switch (return_tag) {
 #if GOBJECT_INTROSPECTION_VERSION < 0x000900
         case GI_TYPE_TAG_LONG:
diff --git a/libseed/seed-engine.c b/libseed/seed-engine.c
index c024308..e442d85 100644
--- a/libseed/seed-engine.c
+++ b/libseed/seed-engine.c
@@ -466,6 +466,7 @@ seed_gobject_method_invoked(JSContextRef ctx,
     GIBaseInfo* iface_info = NULL;
     GArgument retval;
     GArgument* in_args;
+    gint* skipped_args;
     GArgument* out_args;
     GArgument* out_values;
     gint* out_pos;
@@ -496,13 +497,15 @@ seed_gobject_method_invoked(JSContextRef ctx,
 
     out_pos = g_new0(gint, n_args + 1);
     in_args = g_new0(GArgument, n_args + 1);
+    skipped_args = g_new0(gint, n_args + 1);
     out_args = g_new0(GArgument, n_args + 1);
     out_values = g_new0(GArgument, n_args + 1);
     n_in_args = n_out_args = 0;
     caller_allocated = g_new0(gboolean, n_args + 1);
 
-    // start buy pushing the object onto the call stack.
+    memset(skipped_args, 0, n_args);
 
+    // start buy pushing the object onto the call stack.
     if (instance_method)
         in_args[n_in_args++].v_pointer = object;
 
@@ -564,7 +567,7 @@ seed_gobject_method_invoked(JSContextRef ctx,
                     caller_allocated[i] = TRUE;
                 }
                 n_out_args++;
-            } else
+            } else if (!skipped_args[i])
                 in_args[n_in_args++].v_pointer = 0;
 
         } else if (dir == GI_DIRECTION_IN || dir == GI_DIRECTION_INOUT) {
@@ -631,18 +634,34 @@ seed_gobject_method_invoked(JSContextRef ctx,
                 }
             }
 
-            if (!seed_value_to_gi_argument(ctx, arguments[i], type_info,
-                                           transfer, &in_args[n_in_args++],
-                                           exception)) {
-                seed_make_exception(ctx, exception, "ArgumentError",
-                                    "Unable to make argument %d for"
-                                    " function: %s. \n",
-                                    i + 1,
-                                    g_base_info_get_name((GIBaseInfo*) info));
+            guint out_length = 0;
+            if (!skipped_args[i])
+                if (!seed_value_to_gi_argument_with_out_length(
+                      ctx, arguments[i], type_info, transfer,
+                      &in_args[n_in_args++], &out_length, exception)) {
+                    seed_make_exception(ctx, exception, "ArgumentError",
+                                        "Unable to make argument %d for"
+                                        " function: %s. \n",
+                                        i + 1, g_base_info_get_name(
+                                                 (GIBaseInfo*) info));
+
+                    retval_ref = JSValueMakeNull(ctx);
+                    goto invoke_return;
+                }
 
-                retval_ref = JSValueMakeNull(ctx);
-                goto invoke_return;
+            // check if what we did we did on an array,
+            // if yes, fill the g_type_info_get_array_length() position with the
+            // size of the array and mark it as already skipped.
+            GITypeTag type_tag = g_type_info_get_tag(type_info);
+            gint array_len_pos = g_type_info_get_array_length(type_info);
+            if (type_tag == GI_TYPE_TAG_ARRAY
+                && g_type_info_get_array_type(type_info) == GI_ARRAY_TYPE_C
+                && array_len_pos >= 0) {
+                n_in_args++;
+                skipped_args[array_len_pos] = 1;
+                in_args[array_len_pos + 1].v_uint64 = out_length;
             }
+
             if (dir == GI_DIRECTION_INOUT) {
                 GArgument* out_value = &out_values[n_out_args];
                 out_args[n_out_args++].v_pointer = out_value;
diff --git a/libseed/seed-structs.c b/libseed/seed-structs.c
index 7d70d68..0982e36 100644
--- a/libseed/seed-structs.c
+++ b/libseed/seed-structs.c
@@ -236,6 +236,7 @@ seed_union_set_property(JSContextRef context,
 
     seed_value_to_gi_argument(context, value, field_type, GI_TRANSFER_NOTHING,
                               &field_value, exception);
+
     ret = g_field_info_set_field(field, priv->pointer, &field_value);
     if (!ret)
         g_warning("Setting property failed on union of type: %s  "
@@ -755,6 +756,7 @@ seed_construct_struct_type_with_parameters(JSContextRef ctx,
 
         seed_value_to_gi_argument(ctx, jsprop_value, field_type,
                                   GI_TRANSFER_NOTHING, &field_value, exception);
+
         set_ret = g_field_info_set_field(field, object, &field_value);
 
         if (!set_ret)
diff --git a/libseed/seed-types.c b/libseed/seed-types.c
index ac9e38b..3330419 100644
--- a/libseed/seed-types.c
+++ b/libseed/seed-types.c
@@ -315,7 +315,9 @@ static gboolean
 seed_gi_make_array_from_string(JSContextRef ctx,
                                JSStringRef js_string,
                                GITypeInfo* param_type,
+                               guint length,
                                void** array_p,
+                               guint* out_array_length,
                                JSValueRef* exception)
 {
     GITypeTag element_type;
@@ -324,9 +326,8 @@ seed_gi_make_array_from_string(JSContextRef ctx,
     // This could be handled by the case where the value is an object,
     // however, getting length from a string crashs inside JSC. So,
     // we're now proper handling strings here
-    size_t length = JSStringGetMaximumUTF8CStringSize(js_string);
     gchar* buffer = g_malloc(length * sizeof(gchar));
-    JSStringGetUTF8CString(js_string, buffer, length);
+    guint real_size = JSStringGetUTF8CString(js_string, buffer, length);
 
     switch (element_type) {
         case GI_TYPE_TAG_UINT8: {
@@ -339,6 +340,9 @@ seed_gi_make_array_from_string(JSContextRef ctx,
             return FALSE;
         }
     }
+    if (out_array_length)
+        *out_array_length = real_size;
+
     return TRUE;
 }
 
@@ -490,12 +494,13 @@ seed_gi_make_array(JSContextRef ctx,
 }
 
 gboolean
-seed_value_to_gi_argument(JSContextRef ctx,
-                          JSValueRef value,
-                          GITypeInfo* type_info,
-                          GITransfer transfer,
-                          GArgument* arg,
-                          JSValueRef* exception)
+seed_value_to_gi_argument_with_out_length(JSContextRef ctx,
+                                          JSValueRef value,
+                                          GITypeInfo* type_info,
+                                          GITransfer transfer,
+                                          GArgument* arg,
+                                          guint* out_array_length,
+                                          JSValueRef* exception)
 {
     GITypeTag gi_tag = g_type_info_get_tag(type_info);
 
@@ -750,8 +755,10 @@ seed_value_to_gi_argument(JSContextRef ctx,
 
                 JSStringRef js_string
                   = JSValueToStringCopy(ctx, value, exception);
+                size_t length = JSStringGetMaximumUTF8CStringSize(js_string);
                 if (!seed_gi_make_array_from_string(ctx, js_string, param_type,
-                                                    &arg->v_pointer,
+                                                    length, &arg->v_pointer,
+                                                    out_array_length,
                                                     exception)) {
                     g_base_info_unref((GIBaseInfo*) param_type);
                     JSStringRelease(js_string);
@@ -781,6 +788,9 @@ seed_value_to_gi_argument(JSContextRef ctx,
                     g_base_info_unref((GIBaseInfo*) param_type);
                     return FALSE;
                 }
+                if (out_array_length != NULL)
+                    *out_array_length = length;
+
                 g_base_info_unref((GIBaseInfo*) param_type);
                 break;
             }
@@ -859,6 +869,19 @@ seed_value_to_gi_argument(JSContextRef ctx,
     return TRUE;
 }
 
+gboolean
+seed_value_to_gi_argument(JSContextRef ctx,
+                          JSValueRef value,
+                          GITypeInfo* type_info,
+                          GITransfer transfer,
+                          GArgument* arg,
+                          JSValueRef* exception)
+{
+    return seed_value_to_gi_argument_with_out_length(ctx, value, type_info,
+                                                     transfer, arg, NULL,
+                                                     exception);
+}
+
 JSValueRef
 seed_value_from_gi_argument(JSContextRef ctx,
                             GArgument* arg,
diff --git a/libseed/seed-types.h b/libseed/seed-types.h
index 29be0cf..fe90ae0 100644
--- a/libseed/seed-types.h
+++ b/libseed/seed-types.h
@@ -56,6 +56,14 @@ gboolean seed_value_to_gi_argument(JSContextRef ctx,
                                    GArgument* arg,
                                    JSValueRef* exception);
 
+gboolean seed_value_to_gi_argument_with_out_length(JSContextRef ctx,
+                                                   JSValueRef value,
+                                                   GITypeInfo* type_info,
+                                                   GITransfer transfer,
+                                                   GArgument* arg,
+                                                   guint* out_array_length,
+                                                   JSValueRef* exception);
+
 JSValueRef seed_value_from_gi_argument(JSContextRef ctx,
                                        GArgument* arg,
                                        GITypeInfo* type_info,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]