Add support for GArrays: add g_type_info_get_array_type() and properly scan GArray...
authorTomeu Vizoso <tomeu@sugarlabs.org>
Fri, 30 Apr 2010 16:15:23 +0000 (18:15 +0200)
committerTomeu Vizoso <tomeu@sugarlabs.org>
Fri, 30 Apr 2010 16:15:23 +0000 (18:15 +0200)
Based on a previous patch by C. Scott Ananian <cscott@litl.com>

https://bugzilla.gnome.org/show_bug.cgi?id=581687

13 files changed:
gir/gimarshallingtests.c
gir/gimarshallingtests.h
girepository/ginfo.c
girepository/girepository.h
girepository/girnode.c
girepository/girnode.h
girepository/girparser.c
girepository/gtypelib.h
giscanner/annotationparser.py
tests/scanner/foo-1.0-expected.gir
tests/scanner/foo-1.0-expected.tgir
tests/scanner/foo.c
tests/scanner/foo.h

index c48a430a78fd75580a492fb9ff1a3f05081a6315..0a8b7946da2a03df3de991142ef708b3b442ef7b 100644 (file)
@@ -1317,6 +1317,269 @@ g_i_marshalling_tests_array_zero_terminated_inout (gchar ***utf8s)
 }
 
 
+/**
+ * g_i_marshalling_tests_garray_int_none_return:
+ * Returns: (element-type gint) (transfer none):
+ */
+GArray *
+g_i_marshalling_tests_garray_int_none_return (void)
+{
+    static GArray *array = NULL;
+    gint i;
+
+    if (array == NULL) {
+        array = g_array_new (TRUE, TRUE, sizeof (gint));
+        for (i = -1; i < 3; i++)
+            g_array_append_val (array, i);
+    }
+
+    return array;
+}
+
+/**
+ * g_i_marshalling_tests_garray_utf8_none_return:
+ * Returns: (element-type utf8) (transfer none):
+ */
+GArray *
+g_i_marshalling_tests_garray_utf8_none_return (void)
+{
+    static GArray *array = NULL;
+    static gchar *values[] = {"0", "1", "2", NULL};
+    gint i;
+
+    if (array == NULL) {
+        array = g_array_new (TRUE, TRUE, sizeof (gint));
+        for (i = 0; values[i]; i++)
+            g_array_append_val (array, values[i]);
+    }
+
+    return array;
+}
+
+/**
+ * g_i_marshalling_tests_garray_utf8_container_return:
+ * Returns: (element-type utf8) (transfer container):
+ */
+GArray *
+g_i_marshalling_tests_garray_utf8_container_return (void)
+{
+    GArray *array = NULL;
+    static gchar *values[] = {"0", "1", "2", NULL};
+    gint i;
+
+    array = g_array_new (TRUE, TRUE, sizeof (gint));
+    for (i = 0; values[i]; i++)
+        g_array_append_val (array, values[i]);
+
+    return array;
+}
+
+/**
+ * g_i_marshalling_tests_garray_utf8_full_return:
+ * Returns: (element-type utf8) (transfer full):
+ */
+GArray *
+g_i_marshalling_tests_garray_utf8_full_return (void)
+{
+    GArray *array = NULL;
+    static gchar *values[] = {"0", "1", "2", NULL};
+    gint i;
+
+    array = g_array_new (TRUE, TRUE, sizeof (gint));
+    for (i = 0; values[i]; i++) {
+        gchar *str = g_strdup (values[i]);
+        g_array_append_val (array, str);
+    }
+
+    return array;
+}
+
+/**
+ * g_i_marshalling_tests_garray_int_none_in:
+ * @array_: (element-type gint) (transfer none):
+ */
+void
+g_i_marshalling_tests_garray_int_none_in (GArray *array_)
+{
+    g_assert (array_->len == 4);
+    g_assert (g_array_index (array_, gint, 0) == -1);
+    g_assert (g_array_index (array_, gint, 1) == 0);
+    g_assert (g_array_index (array_, gint, 2) == 1);
+    g_assert (g_array_index (array_, gint, 3) == 2);
+}
+
+/**
+ * g_i_marshalling_tests_garray_utf8_none_in:
+ * @array_: (element-type utf8) (transfer none):
+ */
+void
+g_i_marshalling_tests_garray_utf8_none_in (GArray *array_)
+{
+    g_assert (array_->len == 3);
+    g_assert (strcmp (g_array_index (array_, gchar*, 0), "0") == 0);
+    g_assert (strcmp (g_array_index (array_, gchar*, 1), "1") == 0);
+    g_assert (strcmp (g_array_index (array_, gchar*, 2), "2") == 0);
+}
+
+/**
+ * g_i_marshalling_tests_garray_utf8_container_in:
+ * @array_: (element-type utf8) (transfer container):
+ */
+void
+g_i_marshalling_tests_garray_utf8_container_in (GArray *array_)
+{
+    g_assert (array_->len == 3);
+    g_assert (strcmp (g_array_index (array_, gchar*, 0), "0") == 0);
+    g_assert (strcmp (g_array_index (array_, gchar*, 1), "1") == 0);
+    g_assert (strcmp (g_array_index (array_, gchar*, 2), "2") == 0);
+    g_array_free (array_, TRUE);
+}
+
+/**
+ * g_i_marshalling_tests_garray_utf8_full_in:
+ * @array_: (element-type utf8) (transfer full):
+ */
+void
+g_i_marshalling_tests_garray_utf8_full_in (GArray *array_)
+{
+    g_assert (array_->len == 3);
+    g_assert (strcmp (g_array_index (array_, gchar*, 0), "0") == 0);
+    g_assert (strcmp (g_array_index (array_, gchar*, 1), "1") == 0);
+    g_assert (strcmp (g_array_index (array_, gchar*, 2), "2") == 0);
+    g_free (g_array_index (array_, gchar*, 0));
+    g_free (g_array_index (array_, gchar*, 1));
+    g_free (g_array_index (array_, gchar*, 2));
+    g_array_free (array_, TRUE);
+}
+
+/**
+ * g_i_marshalling_tests_garray_utf8_none_out:
+ * @array_: (out) (element-type utf8) (transfer none):
+ */
+void
+g_i_marshalling_tests_garray_utf8_none_out (GArray **array_)
+{
+    static GArray *internal = NULL;
+    static gchar *values[] = {"0", "1", "2", NULL};
+    gint i;
+
+    if (internal == NULL) {
+        internal = g_array_new (TRUE, TRUE, sizeof (gint));
+        for (i = 0; values[i]; i++)
+            g_array_append_val (internal, values[i]);
+    }
+
+    *array_ = internal;
+}
+
+/**
+ * g_i_marshalling_tests_garray_utf8_container_out:
+ * @array_: (out) (element-type utf8) (transfer container):
+ */
+void
+g_i_marshalling_tests_garray_utf8_container_out (GArray **array_)
+{
+    static gchar *values[] = {"0", "1", "2", NULL};
+    gint i;
+
+    *array_ = NULL;
+
+    *array_ = g_array_new (TRUE, TRUE, sizeof (gint));
+    for (i = 0; values[i]; i++)
+        g_array_append_val (*array_, values[i]);
+}
+
+/**
+ * g_i_marshalling_tests_garray_utf8_full_out:
+ * @array_: (out) (element-type utf8) (transfer full):
+ */
+void
+g_i_marshalling_tests_garray_utf8_full_out (GArray **array_)
+{
+    static gchar *values[] = {"0", "1", "2", NULL};
+    gint i;
+
+    *array_ = NULL;
+
+    *array_ = g_array_new (TRUE, TRUE, sizeof (gint));
+    for (i = 0; values[i]; i++) {
+        gchar *str = g_strdup (values[i]);
+        g_array_append_val (*array_, str);
+    }
+}
+
+/**
+ * g_i_marshalling_tests_garray_utf8_none_inout:
+ * @array_: (inout) (element-type utf8) (transfer none):
+ */
+void
+g_i_marshalling_tests_garray_utf8_none_inout (GArray **array_)
+{
+    static GArray *internal = NULL;
+    static gchar *values[] = {"-2", "-1", "0", "1", NULL};
+    gint i;
+
+    g_assert ((*array_)->len == 3);
+    g_assert (strcmp (g_array_index (*array_, gchar*, 0), "0") == 0);
+    g_assert (strcmp (g_array_index (*array_, gchar*, 1), "1") == 0);
+    g_assert (strcmp (g_array_index (*array_, gchar*, 2), "2") == 0);
+
+    if (internal == NULL) {
+        internal = g_array_new (TRUE, TRUE, sizeof (gint));
+        for (i = 0; values[i]; i++)
+            g_array_append_val (internal, values[i]);
+    }
+
+    *array_ = internal;
+}
+
+/**
+ * g_i_marshalling_tests_garray_utf8_container_inout:
+ * @array_: (inout) (element-type utf8) (transfer container):
+ */
+void
+g_i_marshalling_tests_garray_utf8_container_inout (GArray **array_)
+{
+    static gchar *val1 = "-1";
+    static gchar *val2 = "-2";
+
+    g_assert ((*array_)->len == 3);
+    g_assert (strcmp (g_array_index (*array_, gchar*, 0), "0") == 0);
+    g_assert (strcmp (g_array_index (*array_, gchar*, 1), "1") == 0);
+    g_assert (strcmp (g_array_index (*array_, gchar*, 2), "2") == 0);
+
+    g_array_remove_index (*array_, (*array_)->len - 1);
+
+    g_array_prepend_val (*array_, val1);
+    g_array_prepend_val (*array_, val2);
+}
+
+/**
+ * g_i_marshalling_tests_garray_utf8_full_inout:
+ * @array_: (inout) (element-type utf8) (transfer full):
+ */
+void
+g_i_marshalling_tests_garray_utf8_full_inout (GArray **array_)
+{
+    static gchar *val1 = "-1";
+    static gchar *val2 = "-2";
+    gchar *val;
+
+    g_assert ((*array_)->len == 3);
+    g_assert (strcmp (g_array_index (*array_, gchar*, 0), "0") == 0);
+    g_assert (strcmp (g_array_index (*array_, gchar*, 1), "1") == 0);
+    g_assert (strcmp (g_array_index (*array_, gchar*, 2), "2") == 0);
+
+    g_free (g_array_index (*array_, gchar*, (*array_)->len - 1));
+    g_array_remove_index (*array_, (*array_)->len - 1);
+
+    val = g_strdup (val1);
+    g_array_prepend_val (*array_, val);
+
+    val = g_strdup (val2);
+    g_array_prepend_val (*array_, val);
+}
+
 /**
  * g_i_marshalling_tests_glist_int_none_return:
  * Returns: (element-type gint) (transfer none):
index 298f54433e7664ad68c87e4841be62d5c3cc62eb..dd41866fcaa577ce963708a4aa7da3044a5a43c8 100644 (file)
@@ -296,6 +296,26 @@ void g_i_marshalling_tests_array_zero_terminated_out (gchar ***utf8s);
 void g_i_marshalling_tests_array_zero_terminated_inout (gchar ***utf8s);
 
 
+/* GArray */
+
+GArray *g_i_marshalling_tests_garray_int_none_return (void);
+GArray *g_i_marshalling_tests_garray_utf8_none_return (void);
+GArray *g_i_marshalling_tests_garray_utf8_container_return (void);
+GArray *g_i_marshalling_tests_garray_utf8_full_return (void);
+
+void g_i_marshalling_tests_garray_int_none_in (GArray *array_);
+void g_i_marshalling_tests_garray_utf8_none_in (GArray *array_);
+void g_i_marshalling_tests_garray_utf8_container_in (GArray *array_);
+void g_i_marshalling_tests_garray_utf8_full_in (GArray *array_);
+
+void g_i_marshalling_tests_garray_utf8_none_out (GArray **array_);
+void g_i_marshalling_tests_garray_utf8_container_out (GArray **array_);
+void g_i_marshalling_tests_garray_utf8_full_out (GArray **array_);
+
+void g_i_marshalling_tests_garray_utf8_none_inout (GArray **array_);
+void g_i_marshalling_tests_garray_utf8_container_inout (GArray **array_);
+void g_i_marshalling_tests_garray_utf8_full_inout (GArray **array_);
+
 /* GList */
 
 GList *g_i_marshalling_tests_glist_int_none_return (void);
index 724109feb5ee22e8bebac1d330468035f6eb8db6..1d56a22a08110ceb5b828f917493946ce6ff24ec 100644 (file)
@@ -1093,6 +1093,23 @@ g_type_info_is_zero_terminated (GITypeInfo *info)
   return FALSE;
 }
 
+GIArrayType
+g_type_info_get_array_type (GITypeInfo *info)
+{
+  GIRealInfo *rinfo = (GIRealInfo *)info;
+  SimpleTypeBlob *type = (SimpleTypeBlob *)&rinfo->typelib->data[rinfo->offset];
+
+  if (!(type->flags.reserved == 0 && type->flags.reserved2 == 0))
+    {
+      ArrayTypeBlob *blob = (ArrayTypeBlob *)&rinfo->typelib->data[rinfo->offset];
+      g_return_val_if_fail (blob->tag == GI_TYPE_TAG_ARRAY, -1);
+
+      return blob->array_type;
+    }
+
+  return -1;
+}
+
 gint
 g_type_info_get_n_error_domains (GITypeInfo *info)
 {
index cfa5b39065c3fa42531f6658f1b980d80a1193a9..9e62ab15335537c0a5dc5ec4d4e3f979473271c5 100644 (file)
@@ -383,6 +383,13 @@ typedef enum {
    * See docs/typelib-format.txt SimpleTypeBlob definition */
 } GITypeTag;
 
+typedef enum {
+  GI_ARRAY_TYPE_C,
+  GI_ARRAY_TYPE_ARRAY,
+  GI_ARRAY_TYPE_PTR_ARRAY,
+  GI_ARRAY_TYPE_BYTE_ARRAY
+} GIArrayType;
+
 #define G_TYPE_TAG_IS_BASIC(tag) (tag < GI_TYPE_TAG_ARRAY)
 
 const gchar*           g_type_tag_to_string            (GITypeTag   type);
@@ -395,6 +402,7 @@ GIBaseInfo *           g_type_info_get_interface       (GITypeInfo *info);
 gint                   g_type_info_get_array_length    (GITypeInfo *info);
 gint                   g_type_info_get_array_fixed_size(GITypeInfo *info);
 gboolean               g_type_info_is_zero_terminated  (GITypeInfo *info);
+GIArrayType            g_type_info_get_array_type      (GITypeInfo *info);
 
 gint                   g_type_info_get_n_error_domains (GITypeInfo *info);
 GIErrorDomainInfo     *g_type_info_get_error_domain    (GITypeInfo *info,
index 1694406da03658b42daa079f5096d019185f9cb8..6f4a44af9d7410d285f41a56ab9c456ae0d34601 100644 (file)
@@ -1497,6 +1497,7 @@ g_ir_node_build_typelib (GIrNode         *node,
                      array->zero_terminated = type->zero_terminated;
                      array->has_length = type->has_length;
                       array->has_size = type->has_size;
+                      array->array_type = type->array_type;
                      array->reserved2 = 0;
                       if (array->has_length)
                         array->dimensions.length = type->length;
index 7fe235b8916c53fc1f1bdf62c09cafa165427162..5e6cba035a7af6f65dfb0f84443f1ef7693feb72 100644 (file)
@@ -138,6 +138,7 @@ struct _GIrNodeType
   gint length;
   gboolean has_size;
   gint size;
+  gint array_type;
 
   GIrNodeType *parameter_type1;
   GIrNodeType *parameter_type2;
index 5b24604af3bb208cfdff87953bddff92829b7941..85f85e219a919cf2a7b45f4ae379399d2522d808 100644 (file)
@@ -1717,22 +1717,40 @@ start_type (GMarkupParseContext *context,
       typenode->is_pointer = TRUE;
       typenode->is_array = TRUE;
 
-      zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
-      len = find_attribute ("length", attribute_names, attribute_values);
-      size = find_attribute ("fixed-size", attribute_names, attribute_values);
-
-      typenode->zero_terminated = !(zero && strcmp (zero, "1") != 0);
-      typenode->has_length = len != NULL;
-      typenode->length = typenode->has_length ? atoi (len) : -1;
-
-      typenode->has_size = size != NULL;
-      typenode->size = typenode->has_size ? atoi (size) : -1;
+      ctype = find_attribute ("c:type", attribute_names, attribute_values);
+      if (g_str_has_prefix (ctype, "GArray")) {
+        typenode->array_type = GI_ARRAY_TYPE_ARRAY;
+      } else if (g_str_has_prefix (ctype, "GByteArray")) {
+        typenode->array_type = GI_ARRAY_TYPE_BYTE_ARRAY;
+      } else if (g_str_has_prefix (ctype, "GPtrArray")) {
+        typenode->array_type = GI_ARRAY_TYPE_PTR_ARRAY;
+      } else {
+        typenode->array_type = GI_ARRAY_TYPE_C;
+      }
 
-      if (zero)
-        typenode->zero_terminated = strcmp(zero, "1") == 0;
-      else
-        /* If neither zero-terminated nor length nor fixed-size is given, assume zero-terminated. */
-        typenode->zero_terminated = !(typenode->has_length || typenode->has_size);
+      if (typenode->array_type == GI_ARRAY_TYPE_C) {
+          zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
+          len = find_attribute ("length", attribute_names, attribute_values);
+          size = find_attribute ("fixed-size", attribute_names, attribute_values);
+
+          typenode->has_length = len != NULL;
+          typenode->length = typenode->has_length ? atoi (len) : -1;
+
+          typenode->has_size = size != NULL;
+          typenode->size = typenode->has_size ? atoi (size) : -1;
+
+          if (zero)
+            typenode->zero_terminated = strcmp(zero, "1") == 0;
+          else
+            /* If neither zero-terminated nor length nor fixed-size is given, assume zero-terminated. */
+            typenode->zero_terminated = !(typenode->has_length || typenode->has_size);
+        } else {
+          typenode->zero_terminated = FALSE;
+          typenode->has_length = FALSE;
+          typenode->length = -1;
+          typenode->has_size = FALSE;
+          typenode->size = -1;
+        }
     }
   else
     {
index 14edc9841aa739875bead21578b7638883fc2589..820801498dfde37d1cda0327b237e8f056135526 100644 (file)
@@ -524,9 +524,14 @@ typedef struct {
  * of the array. If both has_length and zero_terminated are set, the
  * convention is to pass -1 for the length if the array is
  * zero-terminated.
+ * @has_size: Indicates that size is the fixed size of the array.
+ * @array_type: Indicates whether this is a C array, GArray, GPtrArray, or
+ * GByteArray. If something other than a C array, the length and element size
+ * are implicit in the structure.
  * @length: The index of the parameter which is used to pass the length of the
  * array. The parameter must be an integer type and have the same
  * direction as this one.
+ * @size: The fixed size of the array.
  * @type: The type of the array elements.
  *
  * Arrays are passed by reference, thus is_pointer is always 1.
@@ -539,7 +544,8 @@ typedef struct {
   guint16 zero_terminated :1;
   guint16 has_length      :1;
   guint16 has_size        :1;
-  guint16 reserved2       :5;
+  guint16 array_type      :2;
+  guint16 reserved2       :3;
 
   union {
     guint16 length;
index 3480ac787dfec7a0d7645444359a3c61ffafa9fc..f70bfa452e00a4184ff5d3fa6bd0ee007219cd8a 100644 (file)
@@ -605,6 +605,12 @@ class AnnotationApplier(object):
         has_element_type = OPT_ELEMENT_TYPE in options
         has_array = OPT_ARRAY in options
 
+        if not has_array:
+            has_array = \
+                node.type.name in ['GLib.Array', 'GLib.PtrArray',
+                                   'GLib.ByteArray'] or \
+                node.type.ctype in ['GArray*', 'GPtrArray*', 'GByteArray*']
+
         # FIXME: This is a hack :-(
         if (not isinstance(node, Field) and
             (not has_element_type and
index d29a068e45df50acd176aeea4e33950cba6a11fc..3bd2d89eaceb926c7afe6998bb8544a1dd14d3d7 100644 (file)
@@ -789,6 +789,13 @@ uses a C sugar return type.">
         </parameter>
       </parameters>
     </function>
+    <function name="test_array" c:identifier="foo_test_array">
+      <return-value transfer-ownership="container">
+        <array c:type="GArray*">
+          <type name="utf8"/>
+        </array>
+      </return-value>
+    </function>
     <function name="test_const_char_param"
               c:identifier="foo_test_const_char_param">
       <return-value transfer-ownership="none">
index ea7aa70d2e0a8084878fc449697be801994d40ea..29753af1607df77a5ba702eefb1d222d906260ed 100644 (file)
         </parameter>
       </parameters>
     </function>
+    <function name="test_array" c:identifier="foo_test_array">
+      <return-value transfer-ownership="container">
+        <array>
+          <type name="utf8"/>
+        </array>
+      </return-value>
+    </function>
     <function name="test_const_char_param" c:identifier="foo_test_const_char_param">
       <return-value transfer-ownership="none">
         <type name="none"/>
index d2fb23b2fff0fd33a3a2bd7220da89cb8000c0ab..a404aac9e4234dbb24394c666e973447c3236469 100644 (file)
@@ -454,6 +454,16 @@ foo_test_string_array (char **array)
 {
 }
 
+/**
+ * foo_test_array:
+ * Returns: (element-type utf8) (transfer container):
+ */
+GArray *
+foo_test_array (void)
+{
+  return NULL;
+}
+
 /**
  * foo_rectangle_add:
  * @r1: (inout): add to this rect
index 61c2ca45ce757196354ad81e83eeb0be69b84964..0ebcca2a3fc1ed59c9eea215d4f3c09d5ac11eb3 100644 (file)
@@ -334,6 +334,8 @@ void foo_test_string_array (char **array);
 
 void foo_test_string_array_with_g (gchar **array);
 
+GArray *foo_test_array (void);
+
 const char * foo_test_const_char_retval (void);
 const FooStruct * foo_test_const_struct_retval (void);
 void foo_test_const_char_param (const char * param);