File Coverage

blib/lib/FFI/Platypus/Type/StringArray.pm
Criterion Covered Total %
statement 66 66 100.0
branch 15 16 93.7
condition 1 3 33.3
subroutine 12 12 100.0
pod 0 4 0.0
total 94 101 93.0


line stmt bran cond sub pod time code
1             package FFI::Platypus::Type::StringArray;
2              
3 1     1   7423 use strict;
  1         2  
  1         22  
4 1     1   4 use warnings;
  1         2  
  1         20  
5 1     1   4 use FFI::Platypus;
  1         1  
  1         58  
6              
7             # ABSTRACT: Platypus custom type for arrays of strings
8             our $VERSION = '0.02'; # VERSION
9              
10              
11             use constant _incantation =>
12 1 50 33     82 $^O eq 'MSWin32' && $Config::Config{archname} =~ /MSWin32-x64/
13             ? 'Q'
14 1     1   6 : 'L!';
  1         2  
15 1     1   5 use constant _size_of_pointer => FFI::Platypus->new->sizeof('opaque');
  1         2  
  1         3  
16 1     1   40539 use constant _pointer_buffer => "P" . _size_of_pointer;
  1         2  
  1         441  
17              
18             my @stack;
19              
20             sub perl_to_native
21             {
22             # this is the variable length version
23             # and is actually simpler than the
24             # fixed length version
25 4     4 0 1616 my $count = scalar @{ $_[0] };
  4         6  
26 4         12 my $pointers = pack(('P' x $count)._incantation, @{ $_[0] }, 0);
  4         14  
27 4         11 my $array_pointer = unpack _incantation, pack 'P', $pointers;
28 4         8 push @stack, [ \$_[0], \$pointers ];
29 4         15 $array_pointer;
30             }
31              
32             sub perl_to_native_post
33             {
34 16     16 0 21 pop @stack;
35 16         75 ();
36             }
37              
38             sub native_to_perl
39             {
40 4 100   4 0 2844 return unless defined $_[0];
41 3         5 my @list;
42 3         4 my $i=0;
43 3         4 while(1)
44             {
45 7         21 my $pointer_pointer = unpack(
46             _incantation,
47             unpack(
48             _pointer_buffer,
49             pack(
50             _incantation, $_[0]+_size_of_pointer*$i
51             )
52             )
53             );
54 7 100       14 last unless $pointer_pointer;
55 4         10 push @list, unpack('p', pack(_incantation, $pointer_pointer));
56 4         6 $i++;
57             }
58 3         14 \@list;
59             }
60              
61             sub ffi_custom_type_api_1
62             {
63             # arg0 = class
64             # arg1 = FFI::Platypus instance
65             # arg2 = array size
66             # arg3 = default value
67 5     5 0 26931 my(undef, undef, $count, $default) = @_;
68              
69 5         27 my $config = {
70             native_type => 'opaque',
71             perl_to_native => \&perl_to_native,
72             perl_to_native_post => \&perl_to_native_post,
73             native_to_perl => \&native_to_perl,
74             };
75              
76 5 100       15 if(defined $count)
77             {
78 4         10 my $end = $count-1;
79              
80             $config->{perl_to_native} = sub {
81 12     12   4686 my $incantation = '';
82              
83             my @list = ((map {
84             defined $_
85 48         53 ? do { $incantation .= 'P'; $_ }
  48         70  
86             : defined $default
87 6         24 ? do { $incantation .= 'P'; $default }
  6         7  
88 60 100       81 : do { $incantation .= _incantation; 0 };
  6 100       9  
  6         9  
89 12         24 } @{ $_[0] }[0..$end]), 0);
  12         24  
90              
91 12         19 $incantation .= _incantation;
92              
93 12         41 my $pointers = pack $incantation, @list;
94 12         28 my $array_pointer = unpack _incantation, pack 'P', $pointers;
95 12         26 push @stack, [ \@list, $pointers ];
96 12         46 $array_pointer;
97 4         58 };
98              
99 4         12 my $pointer_buffer = "P@{[ FFI::Platypus->new->sizeof('opaque') * $count ]}";
  4         20  
100 4         81544 my $incantation_count = _incantation.$count;
101              
102             $config->{native_to_perl} = sub {
103 4 100   4   239 return unless defined $_[0];
104 3         26 my @pointer_pointer = unpack($incantation_count, unpack($pointer_buffer, pack(_incantation, $_[0])));
105 6 100       7 [map { defined $_ ? $_ : $default } map { unpack('p', pack(_incantation, $_)) } @pointer_pointer];
  9         33  
  9         20  
106 4         110 };
107              
108             }
109              
110 5         15 $config;
111             }
112              
113             1;
114              
115             __END__