introduce ZConfig system, first cut at HTML::Zoom itself
[catagits/HTML-Zoom.git] / lib / HTML / Zoom / StreamBase.pm
1 package HTML::Zoom::StreamBase;
2
3 use strict;
4 use warnings FATAL => 'all';
5 use HTML::Zoom::MatchWithoutFilter;
6
7 sub _zconfig { shift->{_zconfig} }
8
9 sub peek {
10   my ($self) = @_;
11   if (exists $self->{_peeked}) {
12     return ($self->{_peeked});
13   }
14   if (my ($peeked) = $self->next) {
15     return ($self->{_peeked} = $peeked);
16   }
17   return;
18 }
19
20 sub flatten {
21   my $source_stream = shift;
22   require HTML::Zoom::CodeStream;
23   my $cur_stream;
24   HTML::Zoom::CodeStream->new({
25     code => sub {
26       return unless $source_stream;
27       my $next;
28       until (($next) = ($cur_stream ? $cur_stream->next : ())) {
29         unless (($cur_stream) = $source_stream->next) {
30           undef $source_stream; return;
31         }
32       }
33       return $next;
34     }
35   });
36 }
37
38 sub map {
39   my ($source_stream, $map_func) = @_;
40   require HTML::Zoom::CodeStream;
41   HTML::Zoom::CodeStream->new({
42     code => sub {
43       return unless $source_stream;
44       # If we were aiming for a "true" perl-like map then we should
45       # elegantly handle the case where the map function returns 0 events
46       # and the case where it returns >1 - if you're reading this comment
47       # because you wanted it to do that, now would be the time to fix it :)
48       if (my ($next) = $source_stream->next) {
49         #### XXXX collapsing this into a return doesn't work. what the
50         #### flying fornication ... -- mst
51         my $mapped = do { local $_ = $next; $map_func->($next) };
52         return $mapped;
53       }
54       undef $source_stream; return;
55     }
56   });
57 }
58
59 sub with_filter {
60   my ($self, $selector, $filter) = @_;
61   my $match = $self->_parse_selector($selector);
62   $self->_zconfig->stream_utils->wrap_with_filter($self, $match, $filter);
63 }
64
65 sub select {
66   my ($self, $selector) = @_;
67   my $match = $self->_parse_selector($selector);
68   return HTML::Zoom::MatchWithoutFilter->construct(
69     $self, $match, $self->_zconfig->filter_builder,
70   );
71 }
72
73 sub _parse_selector {
74   my ($self, $selector) = @_;
75   return $selector if ref($selector); # already a match sub
76   $self->_zconfig->selector_parser->parse_selector($selector);
77 }
78
79 1;