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   237587 use strict;
  10         23  
  10         285  
4 10     10   47 use warnings;
  10         20  
  10         216  
5 10     10   153 use 5.008001;
  10         36  
6 10     10   3311 use Ref::Util qw( is_blessed_ref is_plain_arrayref is_plain_hashref is_ref is_blessed_hashref );
  10         11174  
  10         845  
7 10     10   4366 use Sub::Identify 0.05 ();
  10         10326  
  10         272  
8 10     10   76 use Carp ();
  10         74  
  10         175  
9 10     10   4926 use Class::Inspector;
  10         30327  
  10         343  
10 10     10   67 use base qw( Exporter );
  10         18  
  10         10310  
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.15'; # VERSION
16              
17              
18             sub perl_to_c ($$)
19             {
20 73     73 1 160 my($inst, $values) = @_;
21 73 100 66     499 if(is_blessed_ref $inst && $inst->isa('FFI::C::Array'))
    50          
22             {
23 10 50       31 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         83 &perl_to_c($inst->get($_), $values->[$_]) for 0..$#$values;
26             }
27             elsif(is_blessed_ref $inst)
28             {
29 63 50       137 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         195 foreach my $name (keys %$values)
32             {
33 100         158 my $value = $values->{$name};
34 100         340 $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 283 my $inst = shift;
47 30 50       59 Carp::croak("Not an object") unless is_blessed_ref($inst);
48 30 100       147 if($inst->isa("FFI::C::Array"))
    100          
49             {
50 4         14 return [map { &c_to_perl($_) } @$inst]
  12         40  
51             }
52             elsif($inst->isa("FFI::C::Struct"))
53             {
54 4         9 my $def = $inst->{def};
55              
56 4         10 my %h;
57 4         6 foreach my $key (keys %{ $def->{members} })
  4         15  
58             {
59 12 50       26 next if $key =~ /^:/;
60 12         51 my $value = $inst->$key;
61 12 100       33 $value = &c_to_perl($value) if is_blessed_ref $value;
62 12 100       26 $value = [@$value] if is_plain_arrayref $value;
63 12         28 $h{$key} = $value;
64             }
65              
66 4         19 return \%h;
67             }
68             else
69             {
70 22         32 my %h;
71 22         41 my $df = $INC{'FFI/C/StructDef.pm'};
72 22         27 foreach my $key (@{ Class::Inspector->methods(ref $inst) })
  22         71  
73             {
74 105 100       3327 next if $key =~ /^(new|DESTROY)$/;
75              
76             # we only want to recurse on generated methods.
77 61         208 my ($file) = Sub::Identify::get_code_location( $inst->can($key) );
78 61 100       137 next unless $file eq $df;
79              
80             # get the value;
81 60         132 my $value = $inst->$key;
82 60 100       132 $value = &c_to_perl($value) if is_blessed_hashref $value;
83 60 100       127 $value = [@$value] if is_plain_arrayref $value;
84 60         116 $h{$key} = $value;
85             }
86              
87 22         94 return \%h;
88             }
89             }
90              
91              
92             sub owned ($)
93             {
94 2     2 1 1218 my $inst = shift;
95 2   66     20 !!($inst->{ptr} && !$inst->{owner});
96             }
97              
98              
99             sub take ($)
100             {
101 1     1 1 506 my $inst = shift;
102 1 50       7 Carp::croak("Not an object") unless is_blessed_ref $inst;
103 1 50       5 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         4 $ptr;
107             }
108              
109              
110             sub addressof ($)
111             {
112 1     1 1 444 my $inst = shift;
113 1 50       5 Carp::croak("Not an object") unless is_blessed_ref $inst;
114 1         3 my $ptr = $inst->{ptr};
115 1 50       3 Carp::croak("Object pointer went away") unless $ptr;
116 1         3 $ptr;
117             }
118              
119              
120             sub set_array_count ($$)
121             {
122 2     2 1 549 my($inst, $count) = @_;
123 2 50 33     15 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       196 if $inst->{count};
127 1         4 $inst->{count} = $count;
128             }
129              
130             1;
131              
132             __END__