| 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 | 
| 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 | 
| 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; |