File Coverage

blib/lib/ExtUtils/XSpp/Node/Member.pm
Criterion Covered Total %
statement 78 82 95.1
branch 23 26 88.4
condition 6 10 60.0
subroutine 21 24 87.5
pod 11 14 78.5
total 139 156 89.1


line stmt bran cond sub pod time code
1             package ExtUtils::XSpp::Node::Member;
2 21     21   109 use strict;
  21         38  
  21         974  
3 21     21   233 use warnings;
  21         43  
  21         614  
4 21     21   125 use Carp ();
  21         44  
  21         507  
5 21     21   103 use base 'ExtUtils::XSpp::Node';
  21         43  
  21         2750  
6              
7             =head1 NAME
8              
9             ExtUtils::XSpp::Node::Member - Node representing a class member variable
10              
11             =head1 DESCRIPTION
12              
13             An L sub-class representing a single member
14             variable in a class such as
15              
16             class FooBar {
17             int foo; // <-- this one
18             }
19              
20             Member declarations do not produce any XS code unless they are
21             decorated by either C<%get> or C<%set>.
22              
23             =head1 METHODS
24              
25             =head2 new
26              
27             Creates a new C.
28              
29             Named parameters: C indicating the C++ name of the member,
30             C indicating the Perl name of the member (defaults to the
31             same as C), C indicates the (C++) type of the member
32             and finally C, which is an L.
33              
34             =cut
35              
36             sub init {
37 12     12 1 22 my $this = shift;
38 12         92 my %args = @_;
39              
40 12         53 $this->{CPP_NAME} = $args{cpp_name};
41 12   33     69 $this->{PERL_NAME} = $args{perl_name} || $args{cpp_name};
42 12         29 $this->{TYPE} = $args{type};
43 12         31 $this->{CLASS} = $args{class};
44 12         27 $this->{CONDITION} = $args{condition};
45 12         23 $this->{TAGS} = $args{tags};
46 12         54 $this->{EMIT_CONDITION} = $args{emit_condition};
47             }
48              
49             sub print {
50 12     12 1 22 my( $this, $state ) = @_;
51 12         16 my $str = '';
52              
53 12 100       40 $str .= $this->_getter->print( $state ) if $this->_getter;
54 12 100       39 $str .= $this->_setter->print( $state ) if $this->_setter;
55              
56 12         59 return $str;
57             }
58              
59             sub _getter {
60 21     21   38 my( $this ) = @_;
61              
62 21 50       49 die 'Tried to create getter before adding member to a class'
63             unless $this->class;
64 21 100       89 return $this->{_getter} if $this->{_getter};
65              
66             # TODO use plugin infrastructure
67 12         20 my $getter;
68 12         26 for my $tag ( @{$this->tags} ) {
  12         29  
69 10 100       45 if( $tag->{any} eq 'get' ) {
70 9   100     43 $getter = $tag->{positional}[0] || '';
71 9         20 last;
72             }
73             }
74 12 100       34 return unless defined $getter;
75              
76 9         21 my $f = $this->{_getter} =
77             ExtUtils::XSpp::Node::Method->new
78             ( class => $this->class,
79             cpp_name => $this->_getter_name( $getter ),
80             ret_type => $this->type,
81             call_code => $this->_getter_code,
82             condition => $this->condition,
83             emit_condition => $this->emit_condition,
84             const => 1,
85             );
86 9         37 $f->set_ret_typemap( $this->typemap );
87 9         31 $f->resolve_typemaps;
88 9         32 $f->disable_exceptions;
89              
90 9         41 return $this->{_getter};
91             }
92              
93             sub _setter {
94 21     21   33 my( $this ) = @_;
95              
96 21 50       45 die 'Tried to create getter before adding member to a class'
97             unless $this->class;
98 21 100       77 return $this->{_setter} if $this->{_setter};
99              
100             # TODO use plugin infrastructure
101 12         15 my $setter;
102 12         18 for my $tag ( @{$this->tags} ) {
  12         23  
103 18 100       53 if( $tag->{any} eq 'set' ) {
104 9   100     45 $setter = $tag->{positional}[0] || '';
105 9         15 last;
106             }
107             }
108 12 100       46 return unless defined $setter;
109              
110 9         23 my $f = $this->{_setter} =
111             ExtUtils::XSpp::Node::Method->new
112             ( class => $this->class,
113             cpp_name => $this->_setter_name( $setter ),
114             arguments => [ ExtUtils::XSpp::Node::Argument->new
115             ( type => $this->type,
116             name => 'value'
117             )
118             ],
119             ret_type => ExtUtils::XSpp::Node::Type->new( base => 'void' ),
120             call_code => $this->_setter_code,
121             condition => $this->condition,
122             emit_condition => $this->emit_condition,
123             );
124 9         37 $f->set_arg_typemap( 0, $this->typemap );
125 9         26 $f->resolve_typemaps;
126 9         30 $f->disable_exceptions;
127              
128 9         46 return $this->{_setter};
129             }
130              
131             sub _getter_code {
132 9     9   15 my( $this ) = @_;
133              
134 9         24 return [ sprintf 'RETVAL = THIS->%s', $this->cpp_name ];
135             }
136              
137             sub _getter_name {
138 9     9   18 my( $this, $name ) = @_;
139              
140 9 100       25 return $name if $name;
141 8         39 return $this->class->_getter_name( $this->perl_name );
142             }
143              
144             sub _setter_code {
145 9     9   17 my( $this ) = @_;
146              
147 9         21 return [ sprintf 'THIS->%s = value', $this->cpp_name ];
148             }
149              
150             sub _setter_name {
151 9     9   21 my( $this, $name ) = @_;
152              
153 9 100       23 return $name if $name;
154 8         15 return $this->class->_setter_name( $this->perl_name );
155             }
156              
157             =head2 resolve_typemaps
158              
159             Fetches the L object for the type
160             from the typemap registry and stores a reference to the object.
161              
162             =cut
163              
164             sub resolve_typemaps {
165 12     12 1 17 my $this = shift;
166              
167 12   33     97 $this->{TYPEMAPS}{TYPE} ||=
168             ExtUtils::XSpp::Typemap::get_typemap_for_type( $this->type );
169             }
170              
171             =head1 ACCESSORS
172              
173             =head2 cpp_name
174              
175             Returns the C++ name of the member.
176              
177             =head2 perl_name
178              
179             Returns the Perl name of the member (defaults to same as C++).
180              
181             =head2 set_perl_name
182              
183             Sets the Perl name of the member.
184              
185             =head2 type
186              
187             Returns the C++ type for the member.
188              
189             =head2 class
190              
191             Returns the class (L) that the
192             member belongs to.
193              
194             =head2 access
195              
196             Returns C<'public'>, C<'protected'> or C<'private'> depending on
197             member access declaration.
198              
199             =cut
200              
201 18     18 1 137 sub cpp_name { $_[0]->{CPP_NAME} }
202 0     0 0 0 sub set_cpp_name { $_[0]->{CPP_NAME} = $_[1] }
203 16     16 1 71 sub perl_name { $_[0]->{PERL_NAME} }
204 7     7 1 23 sub set_perl_name { $_[0]->{PERL_NAME} = $_[1] }
205 30     30 1 160 sub type { $_[0]->{TYPE} }
206 24     24 0 67 sub tags { $_[0]->{TAGS} }
207 76     76 1 273 sub class { $_[0]->{CLASS} }
208 12     12 1 69 sub access { $_[0]->{ACCESS} }
209 0     0 0 0 sub set_access { $_[0]->{ACCESS} = $_[1] }
210              
211             =head2 typemap
212              
213             Returns the typemap for member type.
214              
215             =head2 set_typemap( typemap )
216              
217             Sets the typemap for member type.
218              
219             =cut
220              
221             sub typemap {
222 18     18 1 31 my ($this) = @_;
223              
224 18 50       71 die "Typemap not available yet" unless $this->{TYPEMAPS}{TYPE};
225 18         91 return $this->{TYPEMAPS}{TYPE};
226             }
227              
228             sub set_typemap {
229 0     0 1   my ($this, $typemap) = @_;
230              
231 0           $this->{TYPEMAPS}{TYPE} = $typemap;
232             }
233              
234             1;