diff options
-rw-r--r-- | giscanner/transformer.py | 27 | ||||
-rw-r--r-- | tests/offsets/gitestoffsets.c | 11 | ||||
-rw-r--r-- | tests/offsets/offsets.h | 15 | ||||
-rw-r--r-- | tests/scanner/test_transformer.py | 42 |
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() |