first try at a read method for filehandles
John Napiorkowski [Fri, 25 Mar 2011 20:48:55 +0000 (16:48 -0400)]
lib/HTML/Zoom/ReadFH.pm
t/to_fh.t [new file with mode: 0644]

index b877c53..2307b04 100644 (file)
@@ -29,6 +29,110 @@ sub getline {
   return $html
 }
 
+sub getlines {
+  my $self = shift;
+  die "Needs to be array context"
+    unless wantarray;
+  my @lines;
+  while (my $chunk = $self->getline) {
+    push @lines, $chunk;
+  }
+  return @lines;
+}
+
+## See: http://perldoc.perl.org/functions/read.html for read spec
+
+sub read {
+  my ($self, $buff, $len, $off) = @_;
+  $off = defined $off ? $off : 0;
+  $self->{_pos} = defined $self->{_pos} ? $self->{_pos} + $off : $off;
+  my $html = $self->{_html} ||= join '', $self->getlines;
+  return if $self->{_pos} > length $html;
+  $_[1] = substr $html, $self->{_pos}, $len;
+  unless(my $overflow = $len - length($buff)) {
+    $_[1] .= "\0" x $overflow;
+  }
+  $self->{_pos} += $len;
+}
+
 sub close { "The door shuts behind you with a ominous boom" }
 
 1;
+
+=head1 NAME
+
+HTML::Zoom::ReadFH - IO::FileHandler like methods on Zoom
+
+=head1 SYNOPSIS
+
+    my $zoom = HTML::Zoom->from_file($html_template);
+
+    #... zoom select modifications
+    
+    my $fh = $zoom->to_fh;
+
+=head1 DESCRIPTION
+
+If you have a L<HTML::Zoom> object and need to render it as something very much
+like a FileHandle, this is the way to do it.  Currently the code is written in
+a minimal manner.  There's just enough support to enable this for L<Plack> and
+L<Catalyst>.
+
+=head1 METHODS
+
+This class supports the following methods.
+
+=head2 getline
+
+    my $fh = $zoom->to_fh;
+    my $line = $fh->getline;
+
+An L<IO::Handle> like C<getline> method.
+
+=head2 getlines
+
+    my $fh = $zoom->to_fh;
+    my @lines = $fh->getlines;
+
+An L<IO::Handle> like C<getlines> method.
+
+=head2 read
+
+    my $fh = $zoom->to_fh;
+    my $buff;
+    $zoom->read($buff, $length, $offset);
+
+An L<IO::Handle> like C<read> method.
+
+=head2 close
+
+Currently is a NOP
+
+=head1 NOTES
+
+    jnap: so to make the "to_fh" work for catalyst looks like I need to add a read
+      method (like "$io->read ( BUF, LEN, [OFFSET] )") to HTML::Zoom::ReadFH
+    jnap: any thoughts or objections?
+    mst: jnap: fine by me
+    mst: it's only as minimal as it is because I implemented enough to make the
+      Plack handler I was using happy and moved on
+    jnap: cool, thanks, figured so
+    mst: please also add a comment in ReadFH to that effect
+    mst: so the next person to find they need something can turn straight up with a patch
+
+Please remember that a patch acceptable to mst would include a test case.
+
+=head1 ALSO SEE
+
+L<HTML::Zoom>
+
+=head1 AUTHORS
+
+See L<HTML::Zoom> for authors.
+
+=head1 LICENSE
+
+See L<HTML::Zoom> for the license.
+
+=cut
+
diff --git a/t/to_fh.t b/t/to_fh.t
new file mode 100644 (file)
index 0000000..5c25295
--- /dev/null
+++ b/t/to_fh.t
@@ -0,0 +1,73 @@
+use strict;
+use warnings FATAL => 'all';
+
+use HTML::Zoom;
+use Test::More tests => 12;
+
+ok my $zoom = HTML::Zoom->from_html(<<HTML);
+<html>
+  <head>
+    <title>Hi!</title>
+  </head>
+  <body id="content-area">
+    <h1>Test</h1>
+    <div>
+      <p class="first-para">Some stuff</p>
+      <p class="boday-para">More stuff</p>
+    </div>
+    <p id="footer">Copryright 2222</p>
+  </body>
+</html>
+HTML
+
+ok my $fh = $zoom->to_fh,
+  'got filehandle';
+
+ok my $html = $zoom->to_html,
+  'got html';
+
+ok my $lines = join('', $zoom->to_fh->getlines),
+  'got joined lines';
+
+is $html, $lines,
+  'straight html is same as lines';
+
+{
+  $fh->read(my $buff, 2);
+
+  ok $buff,
+    'got a populated buffer';
+
+  is $buff, '<h',
+    'got expected info in buffer';
+}
+
+{
+  $fh->read(my $buff, 4);
+
+  ok $buff,
+    'got a populated buffer';
+
+  is $buff, 'tml>',
+    'got expected info in buffer';
+}
+
+{
+  $fh->read(my $buff, 4, 14);
+
+  ok $buff,
+    'got a populated buffer';
+
+  is $buff, '<tit',
+    'got expected info in buffer';
+}
+
+{
+  my @lines;
+  while($fh->read(my $buff, 15)) {
+    push @lines, $buff;
+  }
+
+  is $#lines, 15,
+    'correct number of lines';
+}