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   146 use 5.006;
  8         24  
2 8     8   45 use strict;
  8         13  
  8         172  
3 8     8   46 use warnings;
  8         16  
  8         327  
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   4288 use IO::Scalar;
  8         105043  
  8         455  
14 8     8   71 use Scalar::Util qw(openhandle);
  8         15  
  8         4007  
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 229     229 1 522 my ($self, $input, $callback) = @_;
50            
51 229         306 my $in;
52 229         354 my $should_close = 0;
53            
54 229 50 33     628 if (!defined $input && defined $self->{in}) {
55 0         0 $input = $self->{in};
56             }
57            
58 229 50       561 if (defined $input) {
59 229 50       817 if (openhandle($input)) {
    100          
60 0         0 $in = $input;
61             } elsif (ref $input) {
62 221         703 $in = IO::Scalar->new($input);
63 221         7900 $should_close = 1;
64             } else {
65 8 50       421 open $in, $input or die "$!: $input";
66 8         40 $should_close = 1;
67             }
68             } else {
69 0         0 $in = \*STDIN;
70             }
71            
72 229 100       538 if ($callback) {
73 146         247 eval {
74 146         389 local $self->{in} = $in;
75 146         395 $callback->($in);
76             };
77              
78 146         3065 my $e = $@;
79 146 50       644 close $in if $should_close;
80 146 50       1791 die $e if $e;
81             } else {
82 83         312 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 146     146 1 342 my ($self, $output, $callback) = @_;
118            
119 146         208 my $out;
120 146         230 my $should_close = 0;
121              
122 146 100 66     473 if (!defined $output && defined $self->{out}) {
123 3         6 $output = $self->{out};
124             }
125            
126 146 50       341 if (defined $output) {
127 146 100       587 if (openhandle $output) {
    50          
128 11         59 $out = $output;
129             } elsif (ref $output) {
130 135         266 $$output = '';
131 135         368 $out = IO::Scalar->new($output);
132 135         4100 $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 146 50       339 if ($callback) {
142 146         224 eval {
143 146         365 local $self->{out} = $out;
144 146         354 $callback->($out);
145             };
146              
147 146         7195 my $e = $@;
148 146 100       675 close $out if $should_close;
149 146 50       1805 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 4     4 1 9 my $self = shift;
169 4         6 my $out = $self->{out};
170              
171 4 50       12 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 4         36 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;