* David Robins <[EMAIL PROTECTED]> [2003-12-13 12:08]:
> I'd like to contribute an HTTP::Parser module to CPAN.

I like the idea.

> "parse" which takes some text and either: 
> dies (on error) (I can return a string if people prefer it), or returns:
> 0: want more data but don't know how much
> -1: like 0 but a hint that we want a line
> <n>: want n bytes more
> HTTP::Request object: finished parsing the request.

You're trying to make a single value do duble duty, and that
doesn't work too well. The following code is the best I could
come up with using your interface - note this is after I've
cleaned it up a half dozen times in the course of writing this
reply. The initial version (ie something a novice is likely to
come up with) was far, far messier.

  my ($req, $ret);
  my $data = get_data(-1);

  until(ref($req = $ret = $httpp->parse($data))) {
    if(not $ret) {
      # 0, need more data, no idea how much
      $data = get_data(-1);
    }
    elsif(-1 == $ret) {
      $data = get_data(-1);
      # [ split off one line, feed it in ]
    }
    else {
      # $ret bytes (probably the request body, right?)
      $data = get_data($bytes);
    }
  }

Not something I'm fond of. If you look closely, you'll notice
that the problem is how I've got to make an effort to distinguish
two different cases: did I get an object, or a hint about the
amount of data still needed?  Your semantics completely also
deviate from all of Perl's ideas about truth, so the caller
cannot take any shortcuts in formulating his conditionals.

You should instead separate retrieving the request object into a
different method. Also, 0 should mean "no more input please" (as
you'd expect it). -1 feels more familiar as a way of saying
"I dunno how much". You can just use -2 as a hint to say "but
make it one line please". This makes the value useful as a
boolean, and puts the cases with an indeterminate amount of bytes
on either side of false, making them easier to handle separately.

Code using this interface would read something like this:

  my $data = get_data(-1);

  while(my $bytes = $httpp->parse($data)) {
    $data = $bytes > 0 ? get_data($bytes) : get_data(-1);
    
    if(-2 == $bytes) {
      # [ split off one line, feed it in ]
    }
  } 

  my $req = $httpp->get_request;

Note how this loop handles all the same cases the above convolute
deals with, and differs only in that it's about a hundred times
clearer to read.

-- 
Regards,
Aristotle
 
"If you can't laugh at yourself, you don't take life seriously enough."

Reply via email to