[perl-Glib-Object-Introspection/more-arrays: 2/2] WIP: array → SV: support GArray, GPtrArray and GByteArra y



commit 7556f1603db41166d768c0ff3e201cfc245aed20
Author: Torsten Schönfeld <kaffeetisch gmx de>
Date:   Tue Feb 17 22:08:27 2015 +0100

    WIP: array → SV: support GArray, GPtrArray and GByteArray

 gperl-i11n-marshal-array.c |   67 +++++++++++++++++++++++++++++--------------
 t/arrays.t                 |    8 +++++
 2 files changed, 53 insertions(+), 22 deletions(-)
---
diff --git a/gperl-i11n-marshal-array.c b/gperl-i11n-marshal-array.c
index 705a8b0..e557f55 100644
--- a/gperl-i11n-marshal-array.c
+++ b/gperl-i11n-marshal-array.c
@@ -15,20 +15,62 @@ array_to_sv (GITypeInfo *info,
              GITransfer transfer,
              GPerlI11nInvocationInfo *iinfo)
 {
+       GIArrayType array_type;
        GITypeInfo *param_info;
-       gboolean is_zero_terminated;
        GITypeTag param_tag;
        gsize item_size;
        GITransfer item_transfer;
-       gssize length, i;
        gboolean need_struct_value_semantics;
+       gssize length = -1, i;
        AV *av;
 
        if (pointer == NULL) {
                return &PL_sv_undef;
        }
 
-       is_zero_terminated = g_type_info_is_zero_terminated (info);
+       array_type = g_type_info_get_array_type (info);
+
+#define GET_LENGTH_AND_POINTER(type, len_field, data_field) { \
+               type *array = pointer; \
+               length = array->len_field; \
+               pointer = array->data_field; }
+
+       switch (array_type) {
+       case GI_ARRAY_TYPE_ARRAY:
+               GET_LENGTH_AND_POINTER (GArray, len, data);
+               break;
+       case GI_ARRAY_TYPE_PTR_ARRAY:
+               GET_LENGTH_AND_POINTER (GPtrArray, len, pdata);
+               break;
+       case GI_ARRAY_TYPE_BYTE_ARRAY:
+               GET_LENGTH_AND_POINTER (GByteArray, len, data);
+               break;
+       case GI_ARRAY_TYPE_C:
+               if (g_type_info_is_zero_terminated (info)) {
+                       length = g_strv_length (pointer);
+               } else {
+                       length = g_type_info_get_array_fixed_size (info);
+                       if (length < 0) {
+                               SV *conversion_sv;
+                               gint length_pos = g_type_info_get_array_length (info);
+                               g_assert (iinfo && iinfo->aux_args);
+                               conversion_sv = arg_to_sv (&(iinfo->aux_args[length_pos]),
+                                                          iinfo->arg_types[length_pos],
+                                                          GI_TRANSFER_NOTHING, NULL);
+                               length = SvIV (conversion_sv);
+                               SvREFCNT_dec (conversion_sv);
+                       }
+               }
+               break;
+       default:
+               ccroak ("Unhandled array type %d", array_type);
+       }
+
+#undef GET_LENGTH_AND_POINTER
+
+       if (length < 0) {
+               ccroak ("Could not determine the length of the array");
+       }
 
        /* FIXME: What about an array containing arrays of strings, where the
         * outer array is GI_TRANSFER_EVERYTHING but the inner arrays are
@@ -37,25 +79,6 @@ array_to_sv (GITypeInfo *info,
                ? GI_TRANSFER_EVERYTHING
                : GI_TRANSFER_NOTHING;
 
-       if (is_zero_terminated) {
-               length = g_strv_length (pointer);
-       } else {
-               length = g_type_info_get_array_fixed_size (info);
-               if (length < 0) {
-                       SV *conversion_sv;
-                       gint length_pos = g_type_info_get_array_length (info);
-                       g_assert (iinfo && iinfo->aux_args);
-                       conversion_sv = arg_to_sv (&(iinfo->aux_args[length_pos]),
-                                                  iinfo->arg_types[length_pos],
-                                                  GI_TRANSFER_NOTHING, NULL);
-                       length = SvIV (conversion_sv);
-                       SvREFCNT_dec (conversion_sv);
-               }
-       }
-
-       if (length < 0) {
-               ccroak ("Could not determine the length of the array");
-       }
        param_info = g_type_info_get_param_type (info, 0);
        param_tag = g_type_info_get_tag (param_info);
        item_size = size_of_type_info (param_info);
diff --git a/t/arrays.t b/t/arrays.t
index 5fc309d..c7d99c9 100644
--- a/t/arrays.t
+++ b/t/arrays.t
@@ -53,4 +53,12 @@ is (Regress::test_gslist_null_out (), undef);
 
 # -----------------------------------------------------------------------------
 
+is_deeply ([GI::init_function ([qw/a b c/])], [Glib::TRUE, [qw/a b/]]);
+
+my $test_array_ref = [-1, 0, 1, 2];
+is_deeply (GI::array_fixed_int_return (), $test_array_ref);
+is_deeply (GI::array_fixed_short_return (), $test_array_ref);
+GI::array_fixed_int_in ($test_array_ref);
+GI::array_fixed_short_in ($test_array_ref);
+is_deeply (GI::array_fixed_out (), $test_array_ref);
 is_deeply (GI::array_fixed_out_struct (), [{long_ => 7, int8 => 6}, {long_ => 6, int8 => 7}]);


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