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