File Coverage

blib/lib/Tags/Output.pm
Criterion Covered Total %
statement 149 155 96.1
branch 39 44 88.6
condition 9 12 75.0
subroutine 27 27 100.0
pod 7 7 100.0
total 231 245 94.2


line stmt bran cond sub pod time code
1             package Tags::Output;
2              
3 27     27   184777 use strict;
  27         49  
  27         1052  
4 27     27   136 use warnings;
  27         71  
  27         1590  
5              
6 27     27   13903 use Class::Utils qw(set_params);
  27         320109  
  27         716  
7 27     27   17475 use Encode;
  27         538198  
  27         3354  
8 27     27   248 use Error::Pure qw(err);
  27         61  
  27         9418  
9              
10             our $VERSION = 0.16;
11              
12             # Constructor.
13             sub new {
14 60     60 1 7278476 my ($class, @params) = @_;
15              
16             # Create object.
17 60         179 my $self = bless {}, $class;
18              
19             # Get default parameters.
20 60         330 $self->_default_parameters;
21              
22             # Process params.
23 60         298 set_params($self, @params);
24              
25             # Check parameters to right values.
26 56         982 $self->_check_params;
27              
28             # Initialization.
29 53         216 $self->reset;
30              
31             # Object.
32 53         566 return $self;
33             }
34              
35             # Finalize Tags output.
36             sub finalize {
37 2     2 1 6 my $self = shift;
38              
39 2         2 while (@{$self->{'printed_tags'}}) {
  5         8  
40 3         12 $self->put(['e', $self->{'printed_tags'}->[0]]);
41             }
42              
43 2         2 return;
44             }
45              
46             # Flush tags in object.
47             sub flush {
48 75     75 1 576 my ($self, $reset_flag) = @_;
49              
50 75         143 my $ouf = $self->{'output_handler'};
51 75         115 my $ret;
52 75 100       202 if (ref $self->{'flush_code'} eq 'ARRAY') {
53 4         8 $ret = join $self->{'output_sep'}, @{$self->{'flush_code'}};
  4         19  
54             } else {
55 71         155 $ret = $self->{'flush_code'};
56             }
57              
58             # Output callback.
59 75         263 $self->_process_callback(\$ret, 'output_callback');
60              
61 75 100       174 if ($ouf) {
62 27     27   222 no warnings;
  27         54  
  27         42060  
63 13 50       18 print {$ouf} $ret or err 'Cannot write to output handler.';
  13         53  
64 13         298 undef $ret;
65             }
66              
67             # Reset.
68 75 50       198 if ($reset_flag) {
69 0         0 $self->reset;
70             }
71              
72             # Return string.
73 75         201 return $ret;
74             }
75              
76             # Return array of opened elements.
77             sub open_elements {
78 8     8 1 23 my $self = shift;
79              
80 8         9 return @{$self->{'printed_tags'}};
  8         39  
81             }
82              
83             # Deprecated.
84             sub open_tags {
85 4     4 1 387 my $self = shift;
86              
87 4         67 warn "Method open_tags() is deprecated";
88              
89 4         290 return $self->open_elements;
90             }
91              
92             # Put tags code.
93             sub put {
94 89     89 1 5417 my ($self, @data) = @_;
95              
96             # For every data.
97 89         233 foreach my $tags_structure_ar (@data) {
98              
99             # Bad data.
100 280 100       757 if (ref $tags_structure_ar ne 'ARRAY') {
101 1         3 err 'Bad data.';
102             }
103              
104             # Input 'Tags' item callback.
105 279 100       651 if (defined $self->{'input_tags_item_callback'}) {
106 8         19 $self->{'input_tags_item_callback'}->($tags_structure_ar)
107             }
108              
109             # Split to type and main tags structure.
110 279         500 my ($type, @tags_struct) = @{$tags_structure_ar};
  279         685  
111              
112             # Attributes.
113 279 100       1214 if ($type eq 'a') {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
114 31         91 $self->_check_arguments(\@tags_struct, 1, 2);
115 31         113 $self->_put_attribute(@tags_struct);
116              
117             # Begin of tag.
118             } elsif ($type eq 'b') {
119 89         486 $self->_check_arguments(\@tags_struct, 1, 1);
120 89         303 $self->_put_begin_of_tag(@tags_struct);
121              
122             # CData.
123             } elsif ($type eq 'cd') {
124 6         33 $self->_put_cdata(@tags_struct);
125              
126             # Comment.
127             } elsif ($type eq 'c') {
128 11         23 $self->_put_comment(@tags_struct);
129              
130             # Data.
131             } elsif ($type eq 'd') {
132 39         125 $self->_put_data(@tags_struct);
133              
134             # End of tag.
135             } elsif ($type eq 'e') {
136 83         254 $self->_check_arguments(\@tags_struct, 1, 1);
137 83         233 $self->_put_end_of_tag(@tags_struct);
138              
139             # Instruction.
140             } elsif ($type eq 'i') {
141 5 50       10 if ($self->{'strict_instruction'}) {
142 5         14 $self->_check_arguments(\@tags_struct, 1, 2);
143             }
144 5         16 $self->_put_instruction(@tags_struct);
145              
146             # Raw data.
147             } elsif ($type eq 'r') {
148 13         28 $self->_put_raw(@tags_struct);
149              
150             # Other.
151             } else {
152 2 100       8 if (! $self->{'skip_bad_tags'}) {
153 1         4 err 'Bad type of data.';
154             }
155             }
156             }
157              
158             # Auto-flush.
159 83 100       251 if ($self->{'auto_flush'}) {
160 12         51 $self->flush;
161 12         31 $self->_reset_flush;
162             }
163              
164 83         232 return;
165             }
166              
167             # Reset.
168             sub reset {
169 5     5 1 8 my $self = shift;
170              
171             # Flush code.
172 5         59 $self->_reset_flush;
173              
174             # Printed tags.
175 5         10 $self->{'printed_tags'} = [];
176              
177 5         8 return;
178             }
179              
180             # Check arguments.
181             sub _check_arguments {
182 208     208   471 my ($self, $tags_struct_ar, $min_arg_num, $max_arg_num) = @_;
183              
184 208         284 my $arg_num = scalar @{$tags_struct_ar};
  208         327  
185 208 50 33     858 if ($arg_num < $min_arg_num || $arg_num > $max_arg_num) {
186             err 'Bad number of arguments.',
187 0         0 '\'Tags\' structure', join ', ', @{$tags_struct_ar};
  0         0  
188             }
189              
190 208         349 return;
191             }
192              
193             # Check parameters to rigth values.
194             sub _check_params {
195 56     56   94 my $self = shift;
196              
197             # Check to output handler.
198 56 100 100     236 if (defined $self->{'output_handler'}
199             && ref $self->{'output_handler'} ne 'GLOB') {
200              
201 1         6 err 'Output handler is bad file handler.';
202             }
203              
204             # Check auto-flush only with output handler.
205 55 100 100     207 if ($self->{'auto_flush'} && ! defined $self->{'output_handler'}) {
206 1         3 err 'Auto-flush can\'t use without output handler.';
207             }
208              
209 54         98 return;
210             }
211              
212             # Default parameters.
213             sub _default_parameters {
214 60     60   103 my $self = shift;
215              
216             # Auto-flush.
217 60         231 $self->{'auto_flush'} = 0;
218              
219             # Input 'Tags' item callback.
220 60         157 $self->{'input_tags_item_callback'} = undef;
221              
222             # Output callback.
223             $self->{'output_callback'} = sub {
224 75     75   166 my ($data_sr, $self) = @_;
225              
226 75 50       209 if (defined $self->{'output_encoding'}) {
227 0         0 ${$data_sr} = Encode::encode(
228             $self->{'output_encoding'},
229 0         0 ${$data_sr},
  0         0  
230             );
231             }
232              
233 75         118 return;
234 60         357 };
235              
236             # Output encoding.
237 60         201 $self->{'output_encoding'} = undef;
238              
239             # Set output handler.
240 60         125 $self->{'output_handler'} = undef;
241              
242             # Output separator.
243 60         172 $self->{'output_sep'} = "\n";
244              
245             # Skip bad tags.
246 60         155 $self->{'skip_bad_tags'} = 0;
247              
248             # Strict instruction.
249 60         120 $self->{'strict_instruction'} = 1;
250              
251 60         129 return;
252             }
253              
254             # Process dala callback.
255             sub _process_callback {
256 151     151   340 my ($self, $data_r, $callback_type) = @_;
257              
258             # Process data callback.
259 151 100 66     682 if (defined $self->{$callback_type}
260             && ref $self->{$callback_type} eq 'CODE') {
261              
262 139         394 $self->{$callback_type}->($data_r, $self);
263             }
264              
265 151         324 return;
266             }
267              
268             # Attributes.
269             sub _put_attribute {
270 2     2   6 my ($self, $attr, $value) = @_;
271              
272 2         3 push @{$self->{'flush_code'}}, 'Attribute';
  2         5  
273              
274 2         7 return;
275             }
276              
277             # Begin of tag.
278             sub _put_begin_of_tag {
279 5     5   9 my ($self, $tag) = @_;
280              
281 5         6 push @{$self->{'flush_code'}}, 'Begin of tag';
  5         10  
282              
283 5         20 unshift @{$self->{'printed_tags'}}, $tag;
  5         11  
284              
285 5         11 return;
286             }
287              
288             # CData.
289             sub _put_cdata {
290 2     2   6 my ($self, @cdata) = @_;
291              
292 2         3 push @{$self->{'flush_code'}}, 'CData';
  2         5  
293              
294 2         5 return;
295             }
296              
297             # Comment.
298             sub _put_comment {
299 2     2   6 my ($self, @comments) = @_;
300              
301 2         3 push @{$self->{'flush_code'}}, 'Comment';
  2         5  
302              
303 2         6 return;
304             }
305              
306             # Data.
307             sub _put_data {
308 4     4   17 my ($self, @data) = @_;
309              
310 4         8 push @{$self->{'flush_code'}}, 'Data';
  4         8  
311              
312 4         8 return;
313             }
314              
315             # End of tag.
316             sub _put_end_of_tag {
317 5     5   8 my ($self, $tag) = @_;
318              
319 5         8 push @{$self->{'flush_code'}}, 'End of tag';
  5         8  
320              
321 5         7 shift @{$self->{'printed_tags'}};
  5         8  
322              
323 5         16 return;
324             }
325              
326             # Instruction.
327             sub _put_instruction {
328 2     2   6 my ($self, $target, $code) = @_;
329              
330 2         3 push @{$self->{'flush_code'}}, 'Instruction';
  2         6  
331              
332 2         5 return;
333             }
334              
335             # Raw data.
336             sub _put_raw {
337 2     2   15 my ($self, @raw_data) = @_;
338              
339 2         3 push @{$self->{'flush_code'}}, 'Raw data';
  2         5  
340              
341 2         6 return;
342             }
343              
344             # Reset flush code.
345             sub _reset_flush {
346 5     5   15 my $self = shift;
347              
348 5         19 $self->{'flush_code'} = [];
349              
350 5         8 return;
351             }
352              
353             1;
354              
355             __END__