File Coverage

blib/lib/Tie/Handle/Filter.pm
Criterion Covered Total %
statement 47 48 97.9
branch 11 18 61.1
condition 4 9 44.4
subroutine 19 19 100.0
pod n/a
total 81 94 86.1


line stmt bran cond sub pod time code
1             package Tie::Handle::Filter;
2              
3             # ABSTRACT: [DEPRECATED] filters filehandle output through a coderef
4              
5             #pod =head1 SYNOPSIS
6             #pod
7             #pod use Tie::Handle::Filter;
8             #pod
9             #pod # prefix output to STDERR with standard Greenwich time
10             #pod BEGIN {
11             #pod tie *STDERR, 'Tie::Handle::Filter', *STDERR,
12             #pod sub { scalar(gmtime) . ': ', @_ };
13             #pod }
14             #pod
15             #pod =head1 DESCRIPTION
16             #pod
17             #pod B This module distribution is deprecated in favor
18             #pod of L, which is more robust while
19             #pod being functionally identical, or
20             #pod L, which uses a different
21             #pod mechanism that may offer better performance.
22             #pod
23             #pod This is a small module for changing output when it is sent to a given
24             #pod file handle. By default it passes everything unchanged, but when
25             #pod provided a code reference, that reference is passed the string being
26             #pod sent to the tied file handle and may return a transformed result.
27             #pod
28             #pod =cut
29              
30 5     5   42690 use 5.008;
  5         14  
31 5     5   19 use strict;
  5         7  
  5         82  
32 5     5   19 use warnings;
  5         5  
  5         128  
33 5     5   15 use base 'Tie::Handle';
  5         5  
  5         2485  
34 5     5   7596 use Carp;
  5         5  
  5         229  
35 5     5   2354 use English '-no_match_vars';
  5         13188  
  5         24  
36 5     5   3429 use FileHandle::Fmode ':all';
  5         4871  
  5         2725  
37             our $VERSION = '0.011';
38              
39             #pod =head1 DIAGNOSTICS
40             #pod
41             #pod Wherever possible this module attempts to emulate the built-in functions
42             #pod it ties, so it will return values as expected from whatever function is
43             #pod called. Certain operations may also L|Carp> (throw a fatal
44             #pod exception) if they fail, such as aliasing the file handle during a
45             #pod L|perlfunc/tie> or attempting to perform an
46             #pod L on a tied file handle.
47             #pod
48             #pod =cut
49              
50             sub TIEHANDLE {
51 22     22   22338 my ( $class, $handle_glob, $writer_ref ) = @_;
52              
53             ## no critic (InputOutput::RequireBriefOpen)
54 22 50       120 open my $fh, _get_filehandle_open_mode($handle_glob) . q(&=), $handle_glob
55             or croak $OS_ERROR;
56              
57             return bless {
58             filehandle => $fh,
59             writer => (
60             ( defined $writer_ref and 'CODE' eq ref $writer_ref )
61             ? $writer_ref
62 2     2   16 : sub { return @_ }
63 22 100 66     741 ),
64             }, $class;
65             }
66              
67             sub _get_filehandle_open_mode {
68 22     22   40 my $fh = shift;
69 22         46 for ($fh) {
70 22 50 33     69 return '>>' if is_WO($_) and is_A($_);
71 22 50       354 return '>' if is_WO($_);
72 22 50       232 return '<' if is_RO($_);
73 22 50 33     272 return '+>>' if is_RW($_) and is_A($_);
74 22 50       527 return '+<' if is_RW($_);
75             }
76 0         0 return '+>';
77             }
78              
79             ## no critic (Subroutines::RequireArgUnpacking)
80             ## no critic (Subroutines::RequireFinalReturn)
81              
82             #pod =method PRINT
83             #pod
84             #pod All arguments to L|perlfunc/print> and L|perlfunc/say>
85             #pod directed at the tied file handle are passed to the user-defined
86             #pod function, and the result is then passed to L|perlfunc/print>.
87             #pod
88             #pod =cut
89              
90             sub PRINT {
91 9     9   1240 my $self = shift;
92             ## no critic (InputOutput::RequireCheckedSyscalls)
93 9         12 print { $self->{filehandle} } $self->{writer}->(@_);
  9         50  
94             }
95              
96             #pod =method PRINTF
97             #pod
98             #pod The second and subsequent arguments to L|perlfunc/printf>
99             #pod (i.e., everything but the format string) directed at the tied file
100             #pod handle are passed to the user-defined function, and the result is then
101             #pod passed preceded by the format string to L|perlfunc/printf>.
102             #pod
103             #pod Please note that this does not include calls to
104             #pod L|perlfunc/sprintf>.
105             #pod
106             #pod =cut
107              
108             sub PRINTF {
109 2     2   588 my ( $self, $format ) = splice @_, 0, 2;
110 2         3 printf { $self->{filehandle} } $format, $self->{writer}->(@_);
  2         11  
111             }
112              
113             #pod =method WRITE
114             #pod
115             #pod The first argument to L|perlfunc/syswrite> (i.e., the buffer
116             #pod scalar variable) directed at the tied file handle is passed to the
117             #pod user-defined function, and the result is then passed along with the
118             #pod optional second and third arguments (i.e., length of data in bytes and
119             #pod offset within the string) to L|perlfunc/syswrite>.
120             #pod
121             #pod Note that if you do not provide a length argument to
122             #pod L|perlfunc/syswrite>, it will be computed from the result of
123             #pod the user-defined function. However, if you do provide a length (and
124             #pod possibly offset), they will be relative to the results of the
125             #pod user-defined function, not the input.
126             #pod
127             #pod =cut
128              
129             sub WRITE {
130 3     3   549 my ( $self, $original ) = splice @_, 0, 2;
131 3         11 my $buffer = ( $self->{writer}->($original) )[0];
132 3 50       95 syswrite $self->{filehandle}, $buffer,
    100          
133             ( defined $_[0] ? $_[0] : length $buffer ),
134             ( defined $_[1] ? $_[1] : 0 );
135             }
136              
137             sub CLOSE {
138 10     10   8643 my $self = shift;
139             ## no critic (InputOutput::RequireCheckedSyscalls)
140             ## no critic (InputOutput::RequireCheckedClose)
141 10         321 close $self->{filehandle};
142             }
143              
144             #pod =head1 BUGS AND LIMITATIONS
145             #pod
146             #pod If your function needs to know what operation was used to call it,
147             #pod consider using C<(caller 1)[3]> to determine the method used to call
148             #pod it, which will return C,
149             #pod C, or C per
150             #pod L.
151             #pod
152             #pod Currently this module is biased towards write-only file handles, such as
153             #pod C, C, or ones used for logging. It does not (yet) define
154             #pod the following methods and their associated functions, so don't do them
155             #pod with file handles tied to this class.
156             #pod
157             #pod =head2 READ
158             #pod
159             #pod =over
160             #pod
161             #pod =item L|perlfunc/read>
162             #pod
163             #pod =item L|perlfunc/sysread>
164             #pod
165             #pod =back
166             #pod
167             #pod =head2 READLINE
168             #pod
169             #pod =over
170             #pod
171             #pod =item LHANDLEE>|perlop/"I/O Operators">
172             #pod
173             #pod =item L|perlfunc/readline>
174             #pod
175             #pod =back
176             #pod
177             #pod =head2 GETC
178             #pod
179             #pod =over
180             #pod
181             #pod =item L|perlfunc/getc>
182             #pod
183             #pod =back
184             #pod
185             #pod =head2 OPEN
186             #pod
187             #pod =over
188             #pod
189             #pod =item L|perlfunc/open> (e.g., re-opening the file handle)
190             #pod
191             #pod =back
192             #pod
193             #pod =head2 BINMODE
194             #pod
195             #pod =over
196             #pod
197             #pod =item L|perlfunc/binmode>
198             #pod
199             #pod =back
200             #pod
201             #pod =head2 EOF
202             #pod
203             #pod =over
204             #pod
205             #pod =item L|perlfunc/eof>
206             #pod
207             #pod =back
208             #pod
209             #pod =head2 TELL
210             #pod
211             #pod =over
212             #pod
213             #pod =item L|perlfunc/tell>
214             #pod
215             #pod =back
216             #pod
217             #pod =head2 SEEK
218             #pod
219             #pod =over
220             #pod
221             #pod =item L|perlfunc/seek>
222             #pod
223             #pod =back
224             #pod
225             #pod =cut
226              
227             my $unimplemented_ref = sub {
228             ## no critic (ValuesAndExpressions::ProhibitMagicNumbers)
229             my $package = ( caller 0 )[0];
230             my $method = ( caller 1 )[3];
231             $method =~ s/\A ${package} :: //xms;
232             croak "$package doesn't define a $method method";
233             };
234              
235 1     1   59 sub OPEN { $unimplemented_ref->() }
236 1     1   57 sub BINMODE { $unimplemented_ref->() }
237 1     1   57 sub EOF { $unimplemented_ref->() }
238 1     1   58 sub TELL { $unimplemented_ref->() }
239 1     1   57 sub SEEK { $unimplemented_ref->() }
240              
241             #pod =head1 SEE ALSO
242             #pod
243             #pod =over
244             #pod
245             #pod =item L
246             #pod
247             #pod Prepends filehandle output with a timestamp, optionally formatted via
248             #pod L|POSIX/strftime>.
249             #pod
250             #pod =item L
251             #pod
252             #pod Prepends every line of filehandle output with a timestamp, optionally
253             #pod formatted via L|POSIX/strftime>.
254             #pod
255             #pod =back
256             #pod
257             #pod =cut
258              
259             1;
260              
261             __END__