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   232094 use strict;
  10         26  
  10         280  
4 10     10   66 use warnings;
  10         23  
  10         213  
5 10     10   168 use 5.008001;
  10         34  
6 10     10   3522 use Ref::Util qw( is_blessed_ref is_plain_arrayref is_plain_hashref is_ref is_blessed_hashref );
  10         11371  
  10         783  
7 10     10   4497 use Sub::Identify 0.05 ();
  10         10516  
  10         223  
8 10     10   60 use Carp ();
  10         33  
  10         172  
9 10     10   5034 use Class::Inspector;
  10         30601  
  10         344  
10 10     10   67 use base qw( Exporter );
  10         44  
  10         9839  
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.14'; # VERSION
16              
17              
18             sub perl_to_c ($$)
19             {
20 73     73 1 541 my($inst, $values) = @_;
21 73 100 66     466 if(is_blessed_ref $inst && $inst->isa('FFI::C::Array'))
    50          
22             {
23 10 50       34 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         64 &perl_to_c($inst->get($_), $values->[$_]) for 0..$#$values;
26             }
27             elsif(is_blessed_ref $inst)
28             {
29 63 50       163 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         199 foreach my $name (keys %$values)
32             {
33 100         165 my $value = $values->{$name};
34 100         336 $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 356 my $inst = shift;
47 30 50       63 Carp::croak("Not an object") unless is_blessed_ref($inst);
48 30 100       186 if($inst->isa("FFI::C::Array"))
    100          
49             {
50 4         19 return [map { &c_to_perl($_) } @$inst]
  12         40  
51             }
52             elsif($inst->isa("FFI::C::Struct"))
53             {
54 4         10 my $def = $inst->{def};
55              
56 4         5 my %h;
57 4         6 foreach my $key (keys %{ $def->{members} })
  4         18  
58             {
59 12 50       27 next if $key =~ /^:/;
60 12         52 my $value = $inst->$key;
61 12 100       33 $value = &c_to_perl($value) if is_blessed_ref $value;
62 12 100       28 $value = [@$value] if is_plain_arrayref $value;
63 12         28 $h{$key} = $value;
64             }
65              
66 4         25 return \%h;
67             }
68             else
69             {
70 22         32 my %h;
71 22         39 my $df = $INC{'FFI/C/StructDef.pm'};
72 22         27 foreach my $key (@{ Class::Inspector->methods(ref $inst) })
  22         78  
73             {
74 105 100       3473 next if $key =~ /^(new|DESTROY)$/;
75              
76             # we only want to recurse on generated methods.
77 61         212 my ($file) = Sub::Identify::get_code_location( $inst->can($key) );
78 61 100       128 next unless $file eq $df;
79              
80             # get the value;
81 60         130 my $value = $inst->$key;
82 60 100       139 $value = &c_to_perl($value) if is_blessed_hashref $value;
83 60 100       113 $value = [@$value] if is_plain_arrayref $value;
84 60         121 $h{$key} = $value;
85             }
86              
87 22         106 return \%h;
88             }
89             }
90              
91              
92             sub owned ($)
93             {
94 2     2 1 1061 my $inst = shift;
95 2   66     17 !!($inst->{ptr} && !$inst->{owner});
96             }
97              
98              
99             sub take ($)
100             {
101 1     1 1 524 my $inst = shift;
102 1 50       4 Carp::croak("Not an object") unless is_blessed_ref $inst;
103 1 50       4 Carp::croak("Object is owned by someone else") if $inst->{owner};
104 1         2 my $ptr = delete $inst->{ptr};
105 1 50       4 Carp::croak("Object pointer went away") unless $ptr;
106 1         2 $ptr;
107             }
108              
109              
110             sub addressof ($)
111             {
112 1     1 1 408 my $inst = shift;
113 1 50       6 Carp::croak("Not an object") unless is_blessed_ref $inst;
114 1         2 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 538 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       215 if $inst->{count};
127 1         3 $inst->{count} = $count;
128             }
129              
130             1;
131              
132             __END__