File Coverage

blib/lib/IO/TieCombine.pm
Criterion Covered Total %
statement 55 66 83.3
branch 5 8 62.5
condition n/a
subroutine 17 20 85.0
pod 7 7 100.0
total 84 101 83.1


line stmt bran cond sub pod time code
1 1     1   563 use strict;
  1         2  
  1         22  
2 1     1   4 use warnings;
  1         2  
  1         39  
3             package IO::TieCombine;
4             # ABSTRACT: produce tied (and other) separate but combined variables
5             $IO::TieCombine::VERSION = '1.005';
6 1     1   4 use Carp ();
  1         2  
  1         21  
7 1     1   479 use IO::TieCombine::Handle;
  1         2  
  1         24  
8 1     1   472 use IO::TieCombine::Scalar;
  1         2  
  1         23  
9 1     1   725 use Symbol ();
  1         874  
  1         652  
10              
11             #pod =head1 SYNOPSIS
12             #pod
13             #pod First, we set up a bunch of access points:
14             #pod
15             #pod my $hub = IO::TieCombine->new;
16             #pod
17             #pod my $str_ref = $hub->scalar_ref('x');
18             #pod my $fh = $hub->fh('x');
19             #pod my $callback = $hub->callback('x');
20             #pod
21             #pod tie my $scalar, $hub, 'x';
22             #pod tie local *STDOUT, $hub, 'x';
23             #pod
24             #pod tie local *STDERR, $hub, 'err';
25             #pod
26             #pod Then we write to things:
27             #pod
28             #pod $$str_ref .= 'And ';
29             #pod print $fh "now ";
30             #pod $callback->('for ');
31             #pod $scalar .= 'something ';
32             #pod print "completely ";
33             #pod warn "different.\n";
34             #pod
35             #pod And then:
36             #pod
37             #pod $hub->combined_contents; # And now for something completely different.
38             #pod $hub->slot_contents('x'); # And now for something completely
39             #pod $hub->slot_contents('err'); # different.
40             #pod
41             #pod B Because of a serious problem with Perl 5.10.0, output sent to a
42             #pod tied filehandle using C B. 5.10.1 or
43             #pod later is needed. Since 5.10.0 is broken in so many other ways, you should
44             #pod really upgrade anyway.
45             #pod
46             #pod B Because of a different problem with Perls 5.10.1 - 5.16.3, if you
47             #pod send output to a tied filehandle using C, and C<$\> is undefined (which is
48             #pod the default), B<< C<$\> will not be restored to C after the C >>!
49             #pod This means that once you've used C to print to I tied filehandle, you
50             #pod have corrupted the global state of your program. Either start your program by
51             #pod setting C<$\> to an empty string, which should be safe, or upgrade to 5.18.0.
52             #pod
53             #pod =cut
54              
55             #pod =method new
56             #pod
57             #pod The constructor takes no arguments.
58             #pod
59             #pod =cut
60              
61             sub new {
62 1     1 1 14 my ($class) = @_;
63              
64 1         6 my $self = {
65             combined => \(my $str = ''),
66             slots => { },
67             };
68              
69 1         5 bless $self => $class;
70             }
71              
72             #pod =method combined_contents
73             #pod
74             #pod This method returns the contents of all collected data.
75             #pod
76             #pod =cut
77              
78             sub combined_contents {
79 1     1 1 3 my ($self) = @_;
80 1         2 return ${ $self->{combined} };
  1         5  
81             }
82              
83             #pod =method slot_contents
84             #pod
85             #pod my $str = $hub->slot_contents( $slot_name );
86             #pod
87             #pod This method returns the contents of all collected data for the named slot.
88             #pod
89             #pod =cut
90              
91             sub slot_contents {
92 4     4 1 14 my ($self, $name) = @_;
93 4 50       12 Carp::confess("no name provided for slot_contents") unless defined $name;
94              
95             Carp::confess("no such output slot exists")
96 4 50       13 unless exists $self->{slots}{$name};
97              
98 4         4 return ${ $self->{slots}{$name} };
  4         19  
99             }
100              
101             sub _slot_ref {
102 6     6   9 my ($self, $name) = @_;
103 6 50       15 Carp::confess("no slot name provided") unless defined $name;
104              
105 6 100       23 $self->{slots}{$name} = \(my $str = '') unless $self->{slots}{$name};
106 6         29 return $self->{slots}{$name};
107             }
108              
109             sub _tie_args {
110 5     5   8 my ($self, $name) = @_;
111             return {
112             slot_name => $name,
113             combined_ref => $self->{combined},
114 5         17 output_ref => $self->_slot_ref($name),
115             };
116             }
117              
118             #pod =method clear_slot
119             #pod
120             #pod $hub->clear_slot( $slot_name );
121             #pod
122             #pod This sets the slot back to an empty string.
123             #pod
124             #pod =cut
125              
126             sub clear_slot {
127 1     1 1 777 my ($self, $slot_name) = @_;
128 1         2 ${ $self->_slot_ref($slot_name) } = '';
  1         3  
129 1         14 return;
130             }
131              
132             #pod =method fh
133             #pod
134             #pod my $fh = $hub->fh( $slot_name );
135             #pod
136             #pod This method returns a reference to a tied filehandle. When printed to, output
137             #pod is collected in the named slot.
138             #pod
139             #pod =cut
140              
141             sub fh {
142 2     2 1 11 my ($self, $name) = @_;
143              
144 2         8 my $sym = Symbol::gensym;
145 2         28 my ($class, @rest) = $self->_tie_fh_args($name);
146 2         17 tie *$sym, $class, @rest;
147 2         7 return $sym;
148             }
149              
150             sub TIEHANDLE {
151 0     0   0 my ($self, @args) = @_;
152 0         0 my ($class, @rest) = $self->_tie_fh_args(@args);
153              
154 0         0 return $class->TIEHANDLE(@rest);
155             }
156              
157             sub _tie_fh_args {
158 2     2   4 my ($self, $name) = @_;
159 2         6 return ('IO::TieCombine::Handle', $self->_tie_args($name));
160             }
161              
162             #pod =method scalar_ref
163             #pod
164             #pod my $str_ref = $hub->scalar_ref( $slot_name );
165             #pod
166             #pod This method returns a reference to scalar. When appended to, the new content
167             #pod is collected in the named slot. Attempting to alter the string other than by
168             #pod adding new content to its end will result in an exception.
169             #pod
170             #pod =cut
171              
172             sub scalar_ref {
173 2     2 1 10 my ($self, $name) = @_;
174 2         8 my ($class, @rest) = $self->_tie_scalar_args($name);
175 2         15 tie my($tie), $class, @rest;
176 2         8 return \$tie;
177             }
178              
179             sub TIESCALAR {
180 1     1   7 my ($self, @args) = @_;
181 1         3 my ($class, @rest) = $self->_tie_scalar_args(@args);
182              
183 1         7 return $class->TIESCALAR(@rest);
184             }
185              
186             sub _tie_scalar_args {
187 3     3   4 my ($self, $name) = @_;
188 3         9 return ('IO::TieCombine::Scalar', $self->_tie_args($name));
189             }
190              
191             #pod =method callback
192             #pod
193             #pod my $code = $hub->callback( $slot_name );
194             #pod
195             #pod =cut
196              
197             sub callback {
198 0     0 1   my ($self, $name) = @_;
199 0           my $slot = $self->_slot_ref($name);
200             return sub {
201 0     0     my ($value) = @_;
202              
203 0           ${ $slot } .= $value;
  0            
204 0           ${ $self->{combined} } .= $value;
  0            
205             }
206 0           }
207              
208             1;
209              
210             __END__