File Coverage

blib/lib/Tie/Coupler.pm
Criterion Covered Total %
statement 15 121 12.4
branch 0 32 0.0
condition 0 15 0.0
subroutine 5 18 27.7
pod 4 4 100.0
total 24 190 12.6


line stmt bran cond sub pod time code
1             # ----------------------------------------------------------------------------#
2             # Tie::Coupler #
3             # #
4             # Copyright (c) 2001-02 Arun Kumar U . #
5             # All rights reserved. #
6             # #
7             # This program is free software; you can redistribute it and/or #
8             # modify it under the same terms as Perl itself. #
9             # ----------------------------------------------------------------------------#
10              
11             package Tie::Coupler;
12              
13 1     1   557 use strict;
  1         1  
  1         35  
14 1     1   3 use vars qw($VERSION);
  1         1  
  1         47  
15              
16 1     1   4 use Carp;
  1         9  
  1         394  
17              
18             $VERSION = '0.01';
19              
20             sub new
21             {
22 0     0 1   my ($class) = shift;
23 0           my ($args) = $_[2];
24 0           my (%sargs, %cargs);
25            
26 0 0 0       if (defined($args) && ref($args) ne 'HASH') {
27 0           warn("Invalid options: Should be a hash reference\n");
28 0           croak('Usage: ' . __PACKAGE__ . '->new($scalar1, $scalar2, $opthash)');
29             }
30            
31 0 0         $args = {} if (!defined($args));
32 0           %sargs = %cargs = %{$args};
  0            
33 0           $sargs{'convert'} = $sargs{'fconvert'};
34 0           $sargs{'this'} = \$_[0]; $sargs{'couple'} = \$_[1];
  0            
35              
36 0           $cargs{'convert'} = $cargs{'rconvert'};
37 0           $cargs{'this'} = \$_[1]; $cargs{'couple'} = \$_[0];
  0            
38              
39 0           my $simpl = tie($_[0], 'Tie::Coupling', \%sargs);
40 0           my $cimpl = tie($_[1], 'Tie::Coupling', \%cargs);
41            
42 0           my $self = {};
43 0           $self->{'_simpl'} = $simpl;
44 0           $self->{'_cimpl'} = $cimpl;
45 0           $self->{'_source'} = \$_[0];
46 0           $self->{'_couple'} = \$_[1];
47              
48 0           bless $self, $class;
49 0           return $self;
50             }
51              
52             sub decouple
53             {
54 0     0 1   my $var = $_[0]->{'_source'};
55 0           my $couple = $_[0]->{'_couple'};
56              
57             ## Ugly hack to prevent -w from spitting the warning message
58             ## "untie attempted while 1 inner references still exist"
59              
60 0           undef($_[0]);
61              
62 0           untie(${$var});
  0            
63 0           untie(${$couple});
  0            
64             }
65              
66             sub fconvert
67             {
68 0     0 1   my ($self) = shift;
69 0           $self->{'_simpl'}->convert(@_);
70             }
71              
72             sub rconvert
73             {
74 0     0 1   my ($self) = shift;
75 0           $self->{'_cimpl'}->convert(@_);
76             }
77              
78             1;
79              
80             package Tie::Coupling;
81              
82 1     1   5 use strict;
  1         1  
  1         20  
83 1     1   4 use Carp;
  1         1  
  1         738  
84              
85             my @options = qw(this couple convert init);
86             my @attribs = qw(couple value this init);
87              
88             sub TIESCALAR
89             {
90 0     0     my ($proto, $args) = @_;
91 0           my ($self, $class);
92              
93 0           $self = {};
94 0   0       $class = ref($proto) || $proto;
95 0           bless $self, $class;
96            
97 0           map { $self->{"_" . $_} = $args->{$_}; } @options;
  0            
98 0           $self->_checkOptions();
99 0           $self->_value($self->_this());
100              
101 0 0         if ($self->{'_init'}) { $self->STORE($self->_value()); }
  0            
102              
103 0           return $self;
104             }
105              
106             sub FETCH
107             {
108 0     0     my ($self) = @_;
109 0           return $self->_value();
110             }
111              
112             sub STORE
113             {
114 0     0     my ($self, $value) = @_;
115            
116 0           my $convert = $self->convert();
117 0           my $pattern = qr{(?i)retain};
118              
119 0 0         if (!defined($convert)) {
    0          
    0          
120 0           $self->_value($value);
121 0           $self->_couple($value);
122             }
123 0           elsif ($convert =~ $pattern) { $self->_value($value); }
124             elsif (defined($convert)) {
125 0           my $nvalue = $self->_transform($value);
126 0           $self->_value($value);
127 0           $self->_couple($nvalue);
128             }
129 0           else { confess("Should have never got this far !!"); }
130 0           return $self->_value();
131             }
132              
133             sub convert
134             {
135 0     0     my ($self) = shift;
136            
137 0 0         $self->{'_convert'} = $_[0] if (@_);
138 0           return $self->{'_convert'};
139             }
140              
141             sub _checkOptions
142             {
143 0     0     my ($self) = @_;
144            
145 0           my $convert = $self->convert();
146 0           my $ref = ref($convert);
147 0           my $pattern = qr{(?i)retain};
148              
149 0 0 0       if (defined($convert) && $convert !~ $pattern) {
150 0 0 0       if (!($ref eq 'CODE' || $ref eq 'ARRAY')) {
151 0           carp("Conversion callback should be either a code reference or an array reference\n");
152 0           croak("Usage: tie \$s, \'" . __PACKAGE__ .
153             "\', { couple => \\\$var, convert => \\&coderef }");
154             }
155             }
156             }
157              
158             sub _value
159             {
160 0     0     my ($self) = shift;
161            
162 0 0         $self->{'_value'} = $_[0] if (@_);
163 0           return $self->{'_value'};
164             }
165              
166             sub _couple
167             {
168 0     0     my ($self) = shift;
169            
170 0 0         ${$self->{'_couple'}} = $_[0] if (@_);
  0            
171 0           return ${$self->{'_couple'}};
  0            
172             }
173              
174             sub _this
175             {
176 0     0     my ($self) = shift;
177            
178 0 0         ${$self->{'_this'}} = $_[0] if (@_);
  0            
179 0           return ${$self->{'_this'}};
  0            
180             }
181              
182             sub _transform
183             {
184 0     0     my ($self, $value) = @_;
185 0           my ($convert, $ref);
186              
187 0           $convert = $self->convert();
188 0           $ref = ref($convert);
189            
190 0 0         return $value if (!defined($convert));
191              
192 0 0 0       if (!($ref eq 'CODE' || $ref eq 'ARRAY')) {
193 0           croak("Conversion callback should be either a CODE reference or an ARRAY reference\n");
194             }
195              
196 0 0         if ($ref eq 'CODE') { return $convert->($value); }
  0            
197             else {
198 0 0         if (ref($convert->[0]) eq 'CODE') {
199 0           my $function = $convert->[0];
200 0           my @params = (@{$convert})[1 .. $#{$convert}];
  0            
  0            
201            
202 0           return $function->($value, @params);
203             }
204             else {
205 0           my $pack = $convert->[0];
206 0           my $method = $convert->[1];
207 0           my @params = (@{$convert})[2 .. $#{$convert}];
  0            
  0            
208            
209 0           return $pack->$method($value, @params);
210             }
211             }
212             }
213              
214             1;
215              
216             __END__;