[perl-glib-object-introspection] SV → Array: Also accept strings when a guchar* pointer is expected



commit 03977ba9ea6837a6c14d8426fb2217bbcc06ef84
Author: Torsten Schönfeld <kaffeetisch gmx de>
Date:   Mon Oct 19 21:53:35 2020 +0200

    SV → Array: Also accept strings when a guchar* pointer is expected

 gperl-i11n-marshal-array.c | 21 ++++++++++++++++-----
 t/arrays.t                 | 29 ++++++++++++++++++++++++++++-
 2 files changed, 44 insertions(+), 6 deletions(-)
---
diff --git a/gperl-i11n-marshal-array.c b/gperl-i11n-marshal-array.c
index 12914d8..6b24bff 100644
--- a/gperl-i11n-marshal-array.c
+++ b/gperl-i11n-marshal-array.c
@@ -263,13 +263,8 @@ sv_to_array (GITransfer transfer,
        if (!gperl_sv_is_defined (sv))
                return NULL;
 
-       if (!gperl_sv_is_array_ref (sv))
-               ccroak ("need an array ref to convert to GArray");
-
        array_type = g_type_info_get_array_type (type_info);
 
-       av = (AV *) SvRV (sv);
-
        item_transfer = transfer == GI_TRANSFER_CONTAINER
                      ? GI_TRANSFER_NOTHING
                      : transfer;
@@ -287,6 +282,22 @@ sv_to_array (GITransfer transfer,
                _need_struct_value_semantics (array_type, param_info, param_tag);
        is_zero_terminated = g_type_info_is_zero_terminated (type_info);
        item_size = size_of_type_info (param_info);
+
+       if (!gperl_sv_is_array_ref (sv)) {
+               // special-case const guchar* with transfer=none
+               if (SvPOK (sv) && param_tag == GI_TYPE_TAG_UINT8 && transfer == GI_TRANSFER_NOTHING) {
+                       STRLEN string_length = 0;
+                       char* string = SvPV (sv, string_length);
+                       if (length_pos >= 0) {
+                               array_info->length = is_zero_terminated ? string_length : string_length - 1;
+                       }
+                       return string;
+               } else {
+                       ccroak ("need an array ref to convert to GArray");
+               }
+       }
+
+       av = (AV *) SvRV (sv);
        length = (gsize) (av_len (av) + 1); /* av_len always returns at least -1 */
 
        switch (array_type) {
diff --git a/t/arrays.t b/t/arrays.t
index 999c29e..a434762 100644
--- a/t/arrays.t
+++ b/t/arrays.t
@@ -6,7 +6,7 @@ use strict;
 use warnings;
 use utf8;
 
-plan tests => 88;
+plan tests => 92;
 
 ok (Regress::test_strv_in ([ '1', '2', '3' ]));
 
@@ -227,3 +227,30 @@ __PDF__
     }
   }
 }
+
+# -----------------------------------------------------------------------------
+
+SKIP: {
+  my $have_gio = eval {
+    Glib::Object::Introspection->setup (
+      basename    => 'Gio',
+      version     => '2.0',
+      package     => 'Glib::IO');
+    1;
+  };
+  skip 'string special case using Gio', 4
+    unless $have_gio;
+
+  my $msg1 = Glib::IO::DBusMessage->new_signal ('/asdf/ghjk', 'de.asdf', 'ghjk');
+  my $caps = [];
+  my $blob1 = $msg1->to_blob ($caps);
+
+  my $msg2 = Glib::IO::DBusMessage->new_from_blob ($blob1, $caps);
+  is ($msg2->get_interface (), $msg1->get_interface ());
+  is_deeply ($msg2->to_blob ($caps), $blob1);
+
+  my $blob1_as_string = pack "C*", @$blob1;
+  my $msg3 = Glib::IO::DBusMessage->new_from_blob ($blob1_as_string, $caps);
+  is ($msg3->get_interface (), $msg1->get_interface ());
+  is_deeply ($msg3->to_blob ($caps), $blob1);
+}


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