> When I wrote Apache::Filter, I decided to implement an honest-to-god 
> full-on emulation of Perl's filehandle reading routines, and in particular
> it should handle $/ properly.  If you want to have a look at that code,
> perhaps a portion of it could be integrated into Apache.pm so it would
> behave correctly.

I looked at Apache.pm and Apache::Filter.pm. There is a significant 
difference: Apache::Filter "reads" from a string, while Apache.pm must
receive it's information from a function akin to sysread().

Alternative 1: Read the whole content into a string and fetch lines from
that string as in Apache::Filter. I think this is a bad idea, since it
might
defy the purpose of only reading a line at a time.

Alternative 2: Something like these (completely untested) modifications
to Apache.pm:

    $Apache::READ_BLOCK_SIZE = 8*1024; # Some random number.

    # Notes:
    # - $r->read() should return undef() (or at least false) on failure.
    # - $r->read() should accept an optional 'offset' arg like
sysread().
    # - Is it appropriate and possible to add fields to $r? Look into
    #   notes() and pnotes() as an alternative to $r->{'content_buf'}
    #   and $r->{'content_remain'} if not.
    # - $/ eq '' not handled by this READLINE().

    sub READLINE {
      my ($r) = @_;
      # $r->{'content_buf'   }  Data fetched from client, but not yet
returned.
      # $r->{'content_remain'}  Number of bytes remaining to be read.

      my $line;       # Line found.
      my @line;       # Lines found.
      my $pos;        # Index of $/ substring inside of buffer.
      my $num_bytes;  # Number of bytes to read.
      my $block;      # Block just read.

      # First pass?
      if (!defined($self->{'content_buf'})) {
        # Init data. This could be done in new().
        $r->{'content_buf'   } = '';
        $r->{'content_remain'} = $r->header_in('Content-length');
      }

      # Exit with error if past end of file.
      if (!$self->{'content_remain'} && !length($self->{'content_buf'}))
{
        return wantarray() ? () : undef();
      }

      # List context?
      if (wantarray()) {
        # Read remainder of of input (with error checking).
        $r->read($block='', $self->{'content_remain'});
        return () unless (defined($block));
        $self->{'content_buf'} .= $block;

        # Divide into lines.
        @line = $self->{'content_buf'} =~ m#(.*?\Q$/\E|.+(?!\Q$/\E))#gs;

        # Return the lines.
        $self->{'content_buf'   } = '';
        $self->{'content_remain'} = 0;
        return @line;
      }

      for (;;) {
        # EOL found?
        if (defined($/) && ($pos = index($self->{'content_buf'}, $/)) >=
0) {
          # Return the line.
          $line                  = substr($self->{'content_buf'}, 0,
$pos);
          $self->{'content_buf'} = substr($self->{'content_buf'}, $pos);
          return $line;
        }

        # EOF reached?
        if (!$self->{'content_remain'}) {
          # Return last chunk.
          $line = $self->{'content_buf'};
          $self->{'content_buf'   } = '';
          $self->{'content_remain'} = 0;
          return $line;
        }

        # Read another block of input (with error checking).
        $num_bytes = ($self->{'content_remain'} <
$Apache::READ_BLOCK_SIZE
          ? $self->{'content_remain'}
          : $Apache::READ_BLOCK_SIZE;
        );      
        $r->read($block='', $num_bytes);
        return undef() unless (defined($block));
        $self->{'content_buf'   } .= $block;
        $self->{'content_remain'} -= $num_bytes;
      }
    }


ELB

--
Eric L. Brine  |  Chicken: The egg's way of making more eggs.
[EMAIL PROTECTED]  |  Do you always hit the nail on the thumb?
ICQ# 4629314   |  An optimist thinks thorn bushes have roses.

Reply via email to