File Coverage

blib/lib/EJS/Template/IO.pm
Criterion Covered Total %
statement 54 62 87.1
branch 21 34 61.7
condition 3 6 50.0
subroutine 8 8 100.0
pod 3 3 100.0
total 89 113 78.7


line stmt bran cond sub pod time code
1 8     8   101 use 5.006;
  8         15  
2 8     8   28 use strict;
  8         20  
  8         121  
3 8     8   24 use warnings;
  8         11  
  8         220  
4              
5             =head1 NAME
6              
7             EJS::Template::IO - Mix-in module to normalize input/output parameters for EJS::Template
8              
9             =cut
10              
11             package EJS::Template::IO;
12              
13 8     8   3658 use IO::Scalar;
  8         76146  
  8         638  
14 8     8   38 use Scalar::Util qw(openhandle);
  8         9  
  8         2900  
15              
16             =head1 Methods
17              
18             =head2 input
19              
20             Normalizes input.
21              
22             $self->input('filepath.ejs');
23             $self->input(\$source_text);
24             $self->input($input_handle);
25             $self->input(\*STDIN);
26              
27             It returns a list in the form C<($input, $should_close)>, where C<$input> is
28             the normalized input handle and C<$should_close> indicates the file handle has
29             been opened and your code is responsible for closing it.
30              
31             Alternatively, a callback can be given as the second argument, which will be invoked
32             with its argument set to the normalized C<$input>.
33              
34             $self->input('filepath.ejs', sub {
35             my ($input) = @_;
36             while (<$input>) {
37             ...
38             }
39             });
40              
41             If C<$input> is a file handle that has been opened by this C method, then
42             it will be closed automatically after the callback returns.
43             Even if C is invoked within the callback, the file handle will be closed if
44             necessary, and then this C method will forward C.
45              
46             =cut
47              
48             sub input {
49 226     226 1 232 my ($self, $input, $callback) = @_;
50            
51 226         180 my $in;
52 226         181 my $should_close = 0;
53            
54 226 50 33     507 if (!defined $input && defined $self->{in}) {
55 0         0 $input = $self->{in};
56             }
57            
58 226 50       307 if (defined $input) {
59 226 50       613 if (openhandle($input)) {
    100          
60 0         0 $in = $input;
61             } elsif (ref $input) {
62 218         508 $in = IO::Scalar->new($input);
63 218         4908 $should_close = 1;
64             } else {
65 8 50       308 open $in, $input or die "$!: $input";
66 8         16 $should_close = 1;
67             }
68             } else {
69 0         0 $in = \*STDIN;
70             }
71            
72 226 100       353 if ($callback) {
73 144         156 eval {
74 144         237 local $self->{in} = $in;
75 144         283 $callback->($in);
76             };
77              
78 144         1832 my $e = $@;
79 144 50       470 close $in if $should_close;
80 144 50       1140 die $e if $e;
81             } else {
82 82         212 return ($in, $should_close);
83             }
84             }
85              
86             =head2 output
87              
88             Normalizes output.
89              
90             $self->output('filepath.out');
91             $self->output(\$result_text);
92             $self->output($output_handle);
93             $self->output(\*STDOUT);
94              
95             It returns a list in the form C<($output, $should_close)>, where C<$output> is
96             the normalized output handle and C<$should_close> indicates the file handle has
97             been opened and your code is responsible for closing it.
98              
99             Alternatively, a callback can be given as the second argument, which will be invoked
100             with its argument set to the normalized C<$output>.
101              
102             $self->output('filepath.out', sub {
103             my ($output) = @_;
104             while (<$output>) {
105             ...
106             }
107             });
108              
109             If C<$output> is a file handle that has been opened by this C method, then
110             it will be closed automatically after the callback returns.
111             Even if C is invoked within the callback, the file handle will be closed if
112             necessary, and then this C method will forward C.
113              
114             =cut
115              
116             sub output {
117 144     144 1 167 my ($self, $output, $callback) = @_;
118            
119 144         114 my $out;
120 144         128 my $should_close = 0;
121              
122 144 100 66     352 if (!defined $output && defined $self->{out}) {
123 3         4 $output = $self->{out};
124             }
125            
126 144 50       209 if (defined $output) {
127 144 100       392 if (openhandle $output) {
    50          
128 11         35 $out = $output;
129             } elsif (ref $output) {
130 133         146 $$output = '';
131 133         288 $out = IO::Scalar->new($output);
132 133         2377 $should_close = 1;
133             } else {
134 0 0       0 open($out, '>', $output) or die "$!: $output";
135 0         0 $should_close = 1;
136             }
137             } else {
138 0         0 $out = \*STDOUT;
139             }
140            
141 144 50       221 if ($callback) {
142 144         133 eval {
143 144         211 local $self->{out} = $out;
144 144         247 $callback->($out);
145             };
146              
147 144         4214 my $e = $@;
148 144 100       483 close $out if $should_close;
149 144 50       1258 die $e if $e;
150             } else {
151 0         0 return ($out, $should_close);
152             }
153             }
154              
155             =head2 print
156              
157             Prints text to the current output target.
158              
159             It can be invoked only within an execution context where the output file handle is open.
160              
161             $self->output('filepath.out', sub {
162             $self->print(...);
163             });
164              
165             =cut
166              
167             sub print {
168 164     164 1 199 my $self = shift;
169 164         203 my $out = $self->{out};
170              
171 164 50       467 unless ($out) {
172 0         0 die "print() can be invoked only within an execution context where the output file handle is open";
173             }
174              
175 164         1115 print $out $_ for @_;
176             }
177              
178             =head1 SEE ALSO
179              
180             =over 4
181              
182             =item * L
183              
184             =back
185              
186             =cut
187              
188             1;