summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--giscanner/transformer.py27
-rw-r--r--tests/offsets/gitestoffsets.c11
-rw-r--r--tests/offsets/offsets.h15
-rw-r--r--tests/scanner/test_transformer.py42
4 files changed, 85 insertions, 10 deletions
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index e2294a63..9911de70 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -551,25 +551,32 @@ raise ValueError."""
# Special handling for fields; we don't have annotations on them
# to apply later, yet.
if source_type.type == CTYPE_ARRAY:
+ # Determine flattened array size and its element type.
+ flattened_size = 1
+ while source_type.type == CTYPE_ARRAY:
+ for child in source_type.child_list:
+ if flattened_size is not None:
+ flattened_size *= child.const_int
+ break
+ else:
+ flattened_size = None
+ source_type = source_type.base_type
+
# If the array contains anonymous unions, like in the GValue
# struct, we need to handle this specially. This is necessary
# to be able to properly calculate the size of the compound
# type (e.g. GValue) that contains this array, see
# <https://bugzilla.gnome.org/show_bug.cgi?id=657040>.
- if (source_type.base_type.type == CTYPE_UNION
- and source_type.base_type.name is None):
- synthesized_type = self._synthesize_union_type(symbol, parent_symbol)
- ftype = ast.Array(None, synthesized_type)
+ if source_type.type == CTYPE_UNION and source_type.name is None:
+ element_type = self._synthesize_union_type(symbol, parent_symbol)
else:
ctype = self._create_source_type(source_type)
complete_ctype = self._create_complete_source_type(source_type)
- from_ctype = self.create_type_from_ctype_string(ctype,
- complete_ctype=complete_ctype)
- ftype = ast.Array(None, from_ctype)
- child_list = list(symbol.base_type.child_list)
+ element_type = self.create_type_from_ctype_string(ctype,
+ complete_ctype=complete_ctype)
+ ftype = ast.Array(None, element_type)
ftype.zeroterminated = False
- if child_list:
- ftype.size = child_list[0].const_int
+ ftype.size = flattened_size
else:
ftype = self._create_type_from_base(symbol.base_type)
# ast.Fields are assumed to be read-write
diff --git a/tests/offsets/gitestoffsets.c b/tests/offsets/gitestoffsets.c
index 9ce673e9..a84e8e8a 100644
--- a/tests/offsets/gitestoffsets.c
+++ b/tests/offsets/gitestoffsets.c
@@ -92,6 +92,16 @@ compiled (FILE *outfile)
PRINT_MEMBER (OffsetsArray, some_ptrs);
g_fprintf (outfile, "\n");
+ PRINT_TYPE (OffsetsMultiDimArray);
+ PRINT_MEMBER (OffsetsMultiDimArray, ints);
+ PRINT_MEMBER (OffsetsMultiDimArray, chars);
+ PRINT_MEMBER (OffsetsMultiDimArray, floats);
+ PRINT_MEMBER (OffsetsMultiDimArray, pointers1);
+ PRINT_MEMBER (OffsetsMultiDimArray, pointers2);
+ PRINT_MEMBER (OffsetsMultiDimArray, pointers3);
+ PRINT_MEMBER (OffsetsMultiDimArray, dummy);
+ fprintf (outfile, "\n");
+
PRINT_TYPE (OffsetsBasic);
PRINT_MEMBER (OffsetsBasic, dummy1);
PRINT_MEMBER (OffsetsBasic, field_int8);
@@ -183,6 +193,7 @@ int main(int argc, char **argv)
g_error ("Cannot open '%s': %s'", argv[1], g_strerror(errno));
introspected_struct (outfile, "Array");
+ introspected_struct (outfile, "MultiDimArray");
introspected_struct (outfile, "Basic");
introspected_struct (outfile, "Enum");
introspected_struct (outfile, "Nested");
diff --git a/tests/offsets/offsets.h b/tests/offsets/offsets.h
index 658601f5..7d89fe8d 100644
--- a/tests/offsets/offsets.h
+++ b/tests/offsets/offsets.h
@@ -124,6 +124,21 @@ struct _OffsetsArray
gpointer some_ptrs[5];
};
+/* Test multi-dimensional arrays */
+
+typedef struct _OffsetsMultiDimArray OffsetsMultiDimArray;
+
+struct _OffsetsMultiDimArray
+{
+ gint ints[10][2];
+ gchar chars[255][10];
+ float floats[11][13][17];
+ gchar* pointers1[3][5];
+ gpointer pointers2[7][9];
+ double** pointers3[2][3][4];
+ gchar dummy;
+};
+
/* Test object offsets */
typedef struct _OffsetsObj OffsetsObj;
diff --git a/tests/scanner/test_transformer.py b/tests/scanner/test_transformer.py
index 4731b5ce..92f21c67 100644
--- a/tests/scanner/test_transformer.py
+++ b/tests/scanner/test_transformer.py
@@ -483,5 +483,47 @@ class TestCallbacks(unittest.TestCase):
self.assertTrue(isinstance(node, ast.Callback))
+class TestArrays(unittest.TestCase):
+ def setUp(self):
+ # Hack to set logging singleton
+ self.namespace = ast.Namespace('Test', '1.0')
+ logger = MessageLogger.get(namespace=self.namespace)
+ logger.enable_warnings((WARNING, ERROR, FATAL))
+
+ def test_multidimensional_arrays(self):
+ """Multidimensional arrays are flattend into a single dimension."""
+
+ load_namespace_from_source_string(self.namespace, """
+ typedef struct {
+ int data[2][3][5][7][11];
+ } TestMultiDimArray;
+ """)
+
+ node = self.namespace.get('MultiDimArray')
+ self.assertIsNotNone(node)
+
+ field = node.fields[0]
+ self.assertIsInstance(field, ast.Field)
+ self.assertIsInstance(field.type, ast.Array)
+ self.assertEqual(field.type.element_type, ast.TYPE_INT)
+ self.assertEqual(field.type.size, 2 * 3 * 5 * 7 * 11)
+
+ def test_flexible_array_member(self):
+ """Flexible array members don't break transformer.
+
+ They are generally unsupported, so nothing else is validated.
+ """
+
+ load_namespace_from_source_string(self.namespace, """
+ typedef struct {
+ int length;
+ unsigned char data[];
+ } TestFlexibleArray;
+ """)
+
+ node = self.namespace.get('FlexibleArray')
+ self.assertIsNotNone(node)
+
+
if __name__ == '__main__':
unittest.main()