first cut at repeater
[catagits/HTML-Zoom.git] / lib / HTML / Zoom / StreamBase.pm
1 package HTML::Zoom::StreamBase;
2
3 use strict;
4 use warnings FATAL => 'all';
5
6 sub peek {
7   my ($self) = @_;
8   if (exists $self->{_peeked}) {
9     return ($self->{_peeked});
10   }
11   if (my ($peeked) = $self->next) {
12     return ($self->{_peeked} = $peeked);
13   }
14   return;
15 }
16
17 sub flatten {
18   my $source_stream = shift;
19   require HTML::Zoom::CodeStream;
20   my $cur_stream;
21   HTML::Zoom::CodeStream->new({
22     code => sub {
23       return unless $source_stream;
24       my $next;
25       until (($next) = ($cur_stream ? $cur_stream->next : ())) {
26 #::Dwarn $source_stream;
27         unless (($cur_stream) = $source_stream->next) {
28           undef $source_stream; return;
29         }
30       }
31 #::Dwarn $next;
32       return $next;
33     }
34   });
35 }
36
37 sub map {
38   my ($source_stream, $map_func) = @_;
39   require HTML::Zoom::CodeStream;
40   HTML::Zoom::CodeStream->new({
41     code => sub {
42       return unless $source_stream;
43       # If we were aiming for a "true" perl-like map then we should
44       # elegantly handle the case where the map function returns 0 events
45       # and the case where it returns >1 - if you're reading this comment
46       # because you wanted it to do that, now would be the time to fix it :)
47       if (my ($next) = $source_stream->next) {
48         #### XXXX collapsing this into a return doesn't work. what the
49         #### flying fornication ... -- mst
50         my $mapped = do { local $_ = $next; $map_func->($next) };
51         return $mapped;
52       }
53       undef $source_stream; return;
54     }
55   });
56 }
57
58 1;