ff42fa66fe33d5f8380671e13a83750e9e6c9e1d
[catagits/HTML-Zoom.git] / lib / HTML / Zoom / StreamUtils.pm
1 package HTML::Zoom::StreamUtils;
2
3 use strictures 1;
4 use base qw(HTML::Zoom::SubObject);
5
6 use Scalar::Util ();
7
8 use HTML::Zoom::CodeStream;
9 use HTML::Zoom::FilterStream;
10 use HTML::Zoom::ArrayStream;
11
12 sub stream_from_code {
13   my ($self, $code) = @_;
14   HTML::Zoom::CodeStream->new({
15     code => $code,
16     zconfig => $self->_zconfig,
17   })
18 }
19
20 sub stream_from_array {
21   my $self = shift;
22   my @array = @_;
23   HTML::Zoom::ArrayStream->new({
24     array => \@array,
25     zconfig => $self->_zconfig,
26   })
27 }
28
29 sub stream_concat {
30   shift->stream_from_array(@_)->flatten;
31 }
32
33 sub stream_from_proto {
34   my ($self, $proto) = @_;
35   my $ref = ref $proto;
36   if (not $ref) {
37     return $self->stream_from_array({
38       type => 'TEXT',
39       raw => $self->_zconfig->parser->html_escape($proto)
40     });
41   } elsif ($ref eq 'ARRAY') {
42     return $self->stream_from_array(@$proto);
43   } elsif ($ref eq 'CODE') {
44     return $proto->();
45   } elsif ($ref eq 'SCALAR') {
46     return $self->_zconfig->parser->html_to_stream($$proto);
47   } elsif (Scalar::Util::blessed($proto) && $proto->can('to_stream')) {
48     my $stream = $proto->to_stream;
49     return $self->stream_from_code(sub { $stream->next });
50   }
51   die "Don't know how to turn $proto (ref $ref) into a stream";
52 }
53
54 sub wrap_with_filter {
55   my ($self, $stream, $match, $filter) = @_;
56   HTML::Zoom::FilterStream->new({
57     stream => $stream,
58     match => $match,
59     filter => $filter,
60     zconfig => $self->_zconfig,
61   })
62 }
63
64 sub stream_to_array {
65   my $stream = $_[1];
66   my @array;
67   while (my ($evt) = $stream->next) { push @array, $evt }
68   return @array;
69 }
70
71 sub flatten_stream_of_streams {
72   my ($self, $source_stream) = @_;
73   my $cur_stream;
74   HTML::Zoom::CodeStream->new({
75     code => sub {
76       return unless $source_stream;
77       my $next;
78       until (($next) = ($cur_stream ? $cur_stream->next : ())) {
79         unless (($cur_stream) = $source_stream->next) {
80           undef $source_stream; return;
81         }
82       }
83       return $next;
84     }
85   });
86 }
87
88 1;