File Coverage

blib/lib/FFI/C/Util.pm
Criterion Covered Total %
statement 75 78 96.1
branch 31 42 73.8
condition 5 9 55.5
subroutine 14 14 100.0
pod 6 6 100.0
total 131 149 87.9


line stmt bran cond sub pod time code
1             package FFI::C::Util;
2              
3 10     10   183594 use strict;
  10         21  
  10         231  
4 10     10   73 use warnings;
  10         16  
  10         184  
5 10     10   126 use 5.008001;
  10         34  
6 10     10   2721 use Ref::Util qw( is_blessed_ref is_plain_arrayref is_plain_hashref is_ref is_blessed_hashref );
  10         9206  
  10         660  
7 10     10   3479 use Sub::Identify 0.05 ();
  10         8473  
  10         228  
8 10     10   57 use Carp ();
  10         18  
  10         140  
9 10     10   3916 use Class::Inspector;
  10         26045  
  10         280  
10 10     10   58 use base qw( Exporter );
  10         20  
  10         8130  
11              
12             our @EXPORT_OK = qw( perl_to_c c_to_perl take owned set_array_count addressof );
13              
14             # ABSTRACT: Utility functions for dealing with structured C data
15             our $VERSION = '0.12'; # VERSION
16              
17              
18             sub perl_to_c ($$)
19             {
20 73     73 1 133 my($inst, $values) = @_;
21 73 100 66     368 if(is_blessed_ref $inst && $inst->isa('FFI::C::Array'))
    50          
22             {
23 10 50       24 Carp::croak("Tried to initalize a @{[ ref $inst ]} with something other than an array reference")
  0         0  
24             unless is_plain_arrayref $values;
25 10         52 &perl_to_c($inst->get($_), $values->[$_]) for 0..$#$values;
26             }
27             elsif(is_blessed_ref $inst)
28             {
29 63 50       109 Carp::croak("Tried to initalize a @{[ ref $inst ]} with something other than an hash reference")
  0         0  
30             unless is_plain_hashref $values;
31 63         156 foreach my $name (keys %$values)
32             {
33 100         134 my $value = $values->{$name};
34 100         258 $inst->$name($value);
35             }
36             }
37             else
38             {
39 0         0 Carp::croak("Not an object");
40             }
41             }
42              
43              
44             sub c_to_perl ($)
45             {
46 30     30 1 226 my $inst = shift;
47 30 50       56 Carp::croak("Not an object") unless is_blessed_ref($inst);
48 30 100       118 if($inst->isa("FFI::C::Array"))
    100          
49             {
50 4         21 return [map { &c_to_perl($_) } @$inst]
  12         25  
51             }
52             elsif($inst->isa("FFI::C::Struct"))
53             {
54 4         7 my $def = $inst->{def};
55              
56 4         5 my %h;
57 4         4 foreach my $key (keys %{ $def->{members} })
  4         12  
58             {
59 12 50       23 next if $key =~ /^:/;
60 12         42 my $value = $inst->$key;
61 12 100       23 $value = &c_to_perl($value) if is_blessed_ref $value;
62 12 100       23 $value = [@$value] if is_plain_arrayref $value;
63 12         23 $h{$key} = $value;
64             }
65              
66 4         17 return \%h;
67             }
68             else
69             {
70 22         23 my %h;
71 22         36 my $df = $INC{'FFI/C/StructDef.pm'};
72 22         21 foreach my $key (@{ Class::Inspector->methods(ref $inst) })
  22         63  
73             {
74 105 100       2813 next if $key =~ /^(new|DESTROY)$/;
75              
76             # we only want to recurse on generated methods.
77 61         176 my ($file) = Sub::Identify::get_code_location( $inst->can($key) );
78 61 100       111 next unless $file eq $df;
79              
80             # get the value;
81 60         115 my $value = $inst->$key;
82 60 100       111 $value = &c_to_perl($value) if is_blessed_hashref $value;
83 60 100       92 $value = [@$value] if is_plain_arrayref $value;
84 60         102 $h{$key} = $value;
85             }
86              
87 22         75 return \%h;
88             }
89             }
90              
91              
92             sub owned ($)
93             {
94 2     2 1 941 my $inst = shift;
95 2   66     15 !!($inst->{ptr} && !$inst->{owner});
96             }
97              
98              
99             sub take ($)
100             {
101 1     1 1 392 my $inst = shift;
102 1 50       4 Carp::croak("Not an object") unless is_blessed_ref $inst;
103 1 50       3 Carp::croak("Object is owned by someone else") if $inst->{owner};
104 1         3 my $ptr = delete $inst->{ptr};
105 1 50       3 Carp::croak("Object pointer went away") unless $ptr;
106 1         3 $ptr;
107             }
108              
109              
110             sub addressof ($)
111             {
112 1     1 1 364 my $inst = shift;
113 1 50       4 Carp::croak("Not an object") unless is_blessed_ref $inst;
114 1         2 my $ptr = $inst->{ptr};
115 1 50       4 Carp::croak("Object pointer went away") unless $ptr;
116 1         2 $ptr;
117             }
118              
119              
120             sub set_array_count ($$)
121             {
122 2     2 1 442 my($inst, $count) = @_;
123 2 50 33     14 Carp::croak("Not a FFI::C::Array")
124             unless is_blessed_ref $inst && $inst->isa('FFI::C::Array');
125             Carp::croak("This array already has a size")
126 2 100       178 if $inst->{count};
127 1         3 $inst->{count} = $count;
128             }
129              
130             1;
131              
132             __END__