package HTML::Zoom::StreamBase;
-use strict;
-use warnings FATAL => 'all';
+use strictures 1;
+use HTML::Zoom::TransformBuilder;
+
+sub _zconfig { shift->{_zconfig} }
sub peek {
my ($self) = @_;
if (exists $self->{_peeked}) {
return ($self->{_peeked});
}
- if (my ($peeked) = $self->next) {
+ if (my ($peeked) = $self->_next(1)) {
return ($self->{_peeked} = $peeked);
}
return;
}
-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;
+sub next {
+ my ($self) = @_;
+
+ # peeked entry so return that
+
+ if (exists $self->{_peeked}) {
+ if (my $peeked_from = delete $self->{_peeked_from}) {
+ $peeked_from->next;
}
+ return (delete $self->{_peeked});
+ }
+
+ $self->_next;
+}
+
+
+sub flatten {
+ 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
+ });
+}
+
+sub with_filter {
+ my ($self, $selector, $filter) = @_;
+ my $match = $self->_parse_selector($selector);
+ $self->_zconfig->stream_utils->wrap_with_filter($self, $match, $filter);
+}
+
+sub with_transform {
+ my ($self, $transform) = @_;
+ $transform->apply_to_stream($self);
+}
+
+sub select {
+ my ($self, $selector) = @_;
+ return HTML::Zoom::TransformBuilder->new({
+ zconfig => $self->_zconfig,
+ selector => $selector,
+ filters => [],
+ proto => $self,
});
}
+sub then {
+ my ($self) = @_;
+ # see notes in HTML/Zoom.pm for why this needs to be fixed
+ $self->select($self->transform->selector);
+}
+
+sub apply {
+ my ($self, $code) = @_;
+ local $_ = $self;
+ $self->$code;
+}
+
+sub apply_if {
+ my ($self, $predicate, $code) = @_;
+ if($predicate) {
+ local $_ = $self;
+ $self->$code;
+ }
+ else {
+ $self;
+ }
+}
+
+sub to_html {
+ my ($self) = @_;
+ $self->_zconfig->producer->html_from_stream($self);
+}
+
+sub AUTOLOAD {
+ my ($self, $selector, @args) = @_;
+ my $sel = $self->select($selector);
+ my $meth = our $AUTOLOAD;
+ $meth =~ s/.*:://;
+ if (ref($selector) eq 'HASH') {
+ my $ret = $self;
+ $ret = $ret->_do($_, $meth, @{$selector->{$_}}) for keys %$selector;
+ $ret;
+ } else {
+ $self->_do($selector, $meth, @args);
+ }
+}
+
+sub _do {
+ my ($self, $selector, $meth, @args) = @_;
+ return $self->select($selector)->$meth(@args);
+}
+
+sub DESTROY {}
+
1;