package Tags::Output::Structure;
use base qw(Tags::Output);
use strict;
use warnings;
use Error::Pure qw(err);
our $VERSION = 0.08;
# Flush.
sub flush {
my ($self, $reset_flag) = @_;
my $ouf = $self->{'output_handler'};
# Text output.
my $ret_ar;
if ($ouf) {
foreach my $line_ar (@{$self->{'flush_code'}}) {
my $line = "['";
$line .= join "', '", @{$line_ar};
$line .= "']".$self->{'output_sep'};
no warnings;
print {$ouf} $line
or err 'Cannot write to output handler.';
}
# Structure.
} else {
$ret_ar = $self->{'flush_code'};
}
# Reset.
if ($reset_flag) {
$self->reset;
}
return $ret_ar;
}
# Attributes.
sub _put_attribute {
my ($self, $attr, $value) = @_;
$self->_put_structure('a', $attr, $value);
return;
}
# Begin of tag.
sub _put_begin_of_tag {
my ($self, $tag) = @_;
$self->_put_structure('b', $tag);
unshift @{$self->{'printed_tags'}}, $tag;
return;
}
# CData.
sub _put_cdata {
my ($self, @cdata) = @_;
$self->_put_structure('cd', @cdata);
return;
}
# Comment.
sub _put_comment {
my ($self, @comments) = @_;
$self->_put_structure('c', @comments);
return;
}
# Data.
sub _put_data {
my ($self, @data) = @_;
$self->_put_structure('d', @data);
return;
}
# End of tag.
sub _put_end_of_tag {
my ($self, $tag) = @_;
my $printed = shift @{$self->{'printed_tags'}};
if ($printed ne $tag) {
err "Ending bad tag: '$tag' in block of tag '$printed'.";
}
$self->_put_structure('e', $tag);
return;
}
# Instruction.
sub _put_instruction {
my ($self, $target, $code) = @_;
my @instruction = ('i', $target);
if ($code) {
push @instruction, $code;
}
$self->_put_structure(@instruction);
return;
}
# Raw data.
sub _put_raw {
my ($self, @raw_data) = @_;
$self->_put_structure('r', @raw_data);
return;
}
# Put common structure.
sub _put_structure {
my ($self, @struct) = @_;
push @{$self->{'flush_code'}}, \@struct;
return;
}
1;
__END__
=pod
=encoding utf8
=head1 NAME
Tags::Output::Structure - Structure class for 'Tags' output.
=head1 SYNOPSYS
use Tags::Output::Structure;
my $obj = Tags::Output::Structure->new(%parameters);
$obj->finalize;
my $ret_ar = $obj->flush($reset_flag);
my @tags = $obj->open_tags;
$obj->put(@data);
$obj->reset;
=head1 METHODS
=head2 C<new>
my $obj = Tags::Output::Structure->new(%parameters);
Constructor.
Returns instance of object.
=over 8
=item * C<auto_flush>
Auto flush flag.
Default value is 0.
=item * C<output_callback>
Output callback.
Default value is undef.
=item * C<output_handler>
Set output handler.
Default value is undef.
=item * C<output_sep>
Output separator.
Default value is newline.
=item * C<skip_bad_data>
Skip bad tags.
Default value is 0.
=item * C<strict_instruction>
Strict instruction.
Default value is 1.
=back
=head2 C<finalize>
$obj->finalize;
Finalize Tags output.
Automaticly puts end of all opened tags.
Returns undef.
=head2 C<flush>
my $ret_ar = $obj->flush($reset_flag);
Flush tags in object.
Or returns code.
If enabled $reset_flag, then resets internal variables via reset method.
Returns undef or code.
=head2 C<open_tags>
my @tags = $obj->open_tags;
Get list of opened tags.
Returns array of opened tags.
=head2 C<put>
$obj->put(@data);
Put tags code in tags format.
Returns undef.
=head2 C<reset>
$obj->reset;
Resets internal variables.
Returns undef.
=head1 ERRORS
new():
Auto-flush can't use without output handler.
Output handler is bad file handler.
From Class::Utils::set_params():
Unknown parameter '%s'.
flush():
Cannot write to output handler.
put():
Ending bad tag: '%s' in block of tag '%s'.
=head1 EXAMPLE1
use strict;
use warnings;
use Data::Printer;
use Tags::Output::Structure;
# Object.
my $tags = Tags::Output::Structure->new;
# Put all tag types.
$tags->put(
['b', 'tag'],
['a', 'par', 'val'],
['c', 'data', \'data'],
['e', 'tag'],
['i', 'target', 'data'],
['b', 'tag'],
['d', 'data', 'data'],
['e', 'tag'],
);
# Print out.
my $ret_ar = $tags->flush;
# Dump out.
p $ret_ar;
# Output:
# \ [
# [0] [
# [0] "b",
# [1] "tag"
# ],
# [1] [
# [0] "a",
# [1] "par",
# [2] "val"
# ],
# [2] [
# [0] "c",
# [1] "data",
# [2] \ "data"
# ],
# [3] [
# [0] "e",
# [1] "tag"
# ],
# [4] [
# [0] "i",
# [1] "target",
# [2] "data"
# ],
# [5] [
# [0] "b",
# [1] "tag"
# ],
# [6] [
# [0] "d",
# [1] "data",
# [2] "data"
# ],
# [7] [
# [0] "e",
# [1] "tag"
# ]
# ]
=head1 EXAMPLE2
use strict;
use warnings;
use Tags::Output::Structure;
# Object.
my $tags = Tags::Output::Structure->new(
'output_handler' => \*STDOUT,
);
# Put all tag types.
$tags->put(
['b', 'tag'],
['a', 'par', 'val'],
['c', 'data', \'data'],
['e', 'tag'],
['i', 'target', 'data'],
['b', 'tag'],
['d', 'data', 'data'],
['e', 'tag'],
);
# Print out.
$tags->flush;
# Output:
# ['b', 'tag']
# ['a', 'par', 'val']
# ['c', 'data', 'SCALAR(0x143d9c0)']
# ['e', 'tag']
# ['i', 'target', 'data']
# ['b', 'tag']
# ['d', 'data', 'data']
# ['e', 'tag']
=head1 DEPENDENCIES
L<Error::Pure>,
L<Tags::Output>.
=head1 SEE ALSO
=over
=item L<Tags>
Structure oriented SGML/XML/HTML/etc. elements manipulation.
=item L<Tags::Output>
Base class for Tags::Output::*.
=item L<Task::Tags>
Install the Tags modules.
=back
=head1 REPOSITORY
L<https://github.com/michal-josef-spacek/Tags-Output-Structure>
=head1 AUTHOR
Michal Josef Špaček L<mailto:skim@cpan.org>
L<http://skim.cz>
=head1 LICENSE AND COPYRIGHT
© 2012-2022 Michal Josef Špaček
BSD 2-Clause License
=head1 VERSION
0.08
=cut