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   102 use 5.006;
  8         12  
2 8     8   24 use strict;
  8         12  
  8         107  
3 8     8   21 use warnings;
  8         8  
  8         219  
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   3808 use IO::Scalar;
  8         77441  
  8         304  
14 8     8   42 use Scalar::Util qw(openhandle);
  8         8  
  8         2813  
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 249 my ($self, $input, $callback) = @_;
50            
51 229         161 my $in;
52 229         191 my $should_close = 0;
53            
54 229 50 33     466 if (!defined $input && defined $self->{in}) {
55 0         0 $input = $self->{in};
56             }
57            
58 229 50       307 if (defined $input) {
59 229 50       598 if (openhandle($input)) {
    100          
60 0         0 $in = $input;
61             } elsif (ref $input) {
62 221         507 $in = IO::Scalar->new($input);
63 221         4835 $should_close = 1;
64             } else {
65 8 50       416 open $in, $input or die "$!: $input";
66 8         16 $should_close = 1;
67             }
68             } else {
69 0         0 $in = \*STDIN;
70             }
71            
72 229 100       353 if ($callback) {
73 146         152 eval {
74 146         220 local $self->{in} = $in;
75 146         319 $callback->($in);
76             };
77              
78 146         1812 my $e = $@;
79 146 50       489 close $in if $should_close;
80 146 50       1116 die $e if $e;
81             } else {
82 83         214 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 169 my ($self, $output, $callback) = @_;
118            
119 146         114 my $out;
120 146         133 my $should_close = 0;
121              
122 146 100 66     315 if (!defined $output && defined $self->{out}) {
123 3         4 $output = $self->{out};
124             }
125            
126 146 50       196 if (defined $output) {
127 146 100       397 if (openhandle $output) {
    50          
128 11         37 $out = $output;
129             } elsif (ref $output) {
130 135         164 $$output = '';
131 135         284 $out = IO::Scalar->new($output);
132 135         2465 $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       225 if ($callback) {
142 146         139 eval {
143 146         215 local $self->{out} = $out;
144 146         270 $callback->($out);
145             };
146              
147 146         4387 my $e = $@;
148 146 100       506 close $out if $should_close;
149 146 50       1118 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 5     5 1 9 my $self = shift;
169 5         8 my $out = $self->{out};
170              
171 5 50       19 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 5         52 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;