factor some code-based stream types out into classes
Matt S Trout [Fri, 28 May 2010 12:10:55 +0000 (13:10 +0100)]
lib/HTML/Zoom/FlattenedStream.pm [new file with mode: 0644]
lib/HTML/Zoom/MappedStream.pm [new file with mode: 0644]
lib/HTML/Zoom/StreamBase.pm
t/todo-span.t

diff --git a/lib/HTML/Zoom/FlattenedStream.pm b/lib/HTML/Zoom/FlattenedStream.pm
new file mode 100644 (file)
index 0000000..28c44c2
--- /dev/null
@@ -0,0 +1,23 @@
+package HTML::Zoom::FlattenedStream;
+
+use strict;
+use warnings FATAL => 'all';
+use base qw(HTML::Zoom::StreamBase);
+
+sub new {
+  my ($class, $args) = @_;
+  bless({ _source => $args->{source}, _zconfig => $args->{zconfig} }, $class);
+}
+
+sub next {
+  return unless (my $self = shift)->{_source};
+  my ($next, $s);
+  until (($next) = ($s = $self->{_cur}) ? $s->next : ()) {
+    unless (($self->{_cur}) = $self->{_source}->next) {
+      delete $self->{_source}; return;
+    }
+  }
+  return $next;
+}
+
+1;
diff --git a/lib/HTML/Zoom/MappedStream.pm b/lib/HTML/Zoom/MappedStream.pm
new file mode 100644 (file)
index 0000000..09ef6be
--- /dev/null
@@ -0,0 +1,29 @@
+package HTML::Zoom::MappedStream;
+
+use strict;
+use warnings FATAL => 'all';
+use base qw(HTML::Zoom::StreamBase);
+
+sub new {
+  my ($class, $args) = @_;
+  bless({
+    _source => $args->{source}, _mapper => $args->{mapper},
+    _zconfig => $args->{zconfig}
+  }, $class);
+}
+
+sub next {
+  return unless (my $self = shift)->{_source};
+  # If we were aiming for a "true" perl-like map then we should
+  # elegantly handle the case where the map function returns 0 events
+  # and the case where it returns >1 - if you're reading this comment
+  # because you wanted it to do that, now would be the time to fix it :)
+  if (my ($next) = $self->{_source}->next) {
+    local $_ = $next;
+    return $self->{_mapper}->($next);
+  }
+  delete $self->{_source};
+  return
+}
+
+1;
index 8b89fdf..c04c7b6 100644 (file)
@@ -18,41 +18,19 @@ sub peek {
 }
 
 sub flatten {
-  my $source_stream = shift;
-  require HTML::Zoom::CodeStream;
-  my $cur_stream;
-  HTML::Zoom::CodeStream->new({
-    code => sub {
-      return unless $source_stream;
-      my $next;
-      until (($next) = ($cur_stream ? $cur_stream->next : ())) {
-        unless (($cur_stream) = $source_stream->next) {
-          undef $source_stream; return;
-        }
-      }
-      return $next;
-    }
+  my $self = shift;
+  require HTML::Zoom::FlattenedStream;
+  HTML::Zoom::FlattenedStream->new({
+    source => $self,
+    zconfig => $self->_zconfig
   });
 }
 
 sub map {
-  my ($source_stream, $map_func) = @_;
-  require HTML::Zoom::CodeStream;
-  HTML::Zoom::CodeStream->new({
-    code => sub {
-      return unless $source_stream;
-      # If we were aiming for a "true" perl-like map then we should
-      # elegantly handle the case where the map function returns 0 events
-      # and the case where it returns >1 - if you're reading this comment
-      # because you wanted it to do that, now would be the time to fix it :)
-      if (my ($next) = $source_stream->next) {
-        #### XXXX collapsing this into a return doesn't work. what the
-        #### flying fornication ... -- mst
-        my $mapped = do { local $_ = $next; $map_func->($next) };
-        return $mapped;
-      }
-      undef $source_stream; return;
-    }
+  my ($self, $mapper) = @_;
+  require HTML::Zoom::MappedStream;
+  HTML::Zoom::MappedStream->new({
+    source => $self, mapper => $mapper, zconfig => $self->_zconfig
   });
 }
 
index af164c0..b8aaafc 100644 (file)
@@ -3,4 +3,4 @@ use Test::More tests => 1;
 
 my $zoom = HTML::Zoom->from_html('<p>Hello my name is <span id="name" /></p>');
 my $html = $zoom->select('#name')->replace_content('Foo foo')->to_html;
-is($html, '<p>Hello my name is <span id="#name">Foo foo</span>');
+is($html, '<p>Hello my name is <span id="#name">Foo foo</span></p>');