David Nicol wrote:
> On 8/21/06, Fred Moyer <[EMAIL PROTECTED]> wrote:
>> Greetings,
>>
>> I've hacked a method I needed into Qpsmtpd::Transaction called
>> body_front_write(), which writes to the front of the message body.  I
>> drew heavily from body_write(), but couldn't find a way to avoid
>> making a copy of the body in order to write to the front of it.  I was
>> wondering if anyone knew of a cleaner way to do this,
> 
> An alternate way to write at the beginning of something, which is
> certainly more complex
> and probably not worth the effort, is to store the thing as a list of
> things and join them
> when you are done with them.  To do it that way would require
> refactoring all body code
> to use an array rather than a scalar, but you could then unshift the
> new piece on the front
> instead of copying the body buffer.

This is how body_write() works if ! $self->{_body_file} except it pushes
instead of unshifts; I adapted that part to body_front_write().  I
refactored it a bit more also to avoid the copy and instead match
body_write() in doing the concatenation in the
$self->{_body_file}->print call.  I also removed a redundant
body_resetpos() call, this runs ok for me in production.

What's the best way to deploy something like this that isn't in the
core?  A module that adds this method to the Symbol table namespace for
Qpsmtpd::Transaction?  An application patch during build?  I want to add
it to my application but I'd rather keep a clean copy of the qpsmtpd
source to make upgrading easy.

Here's the revised version, a bit shorter:

sub body_front_write {
  my $self = shift;
  my $data = shift;
  if ($self->{_body_file}) {
    #warn("body_write to file\n");

    # go to the beginning of the file
    $self->body_resetpos
      unless $self->{body_file_writing};
    $self->{_body_file_writing} = 1;

    # write the data and recalculate length
    $self->{_body_file}->print(ref $data eq "SCALAR" ?
        $$data  . $self->body_as_string :
        $data   . $self->body_as_string )

      and $self->{_body_size} = length (ref $data eq "SCALAR" ?
        $$data  . $self->body_as_string :
        $data   . $self->body_as_string );

    # mark finished
    $self->{_body_file_writing} = 0;
  }
  else {
    #warn("body_write to array\n");
    $self->{_body_array} ||= [];

    my $ref = ref($data) eq "SCALAR" ? $data : \$data;
    unshift @{ $self->{_body_array} }, split('', $$ref);

    $self->{_body_size} += scalar(@{ $self->{_body_array} });
    $self->{_body_current_pos} = ( scalar(@{ $self->{_body_array} }) - 1 );
    $self->body_spool if ( $self->{_body_size} >= $self->size_threshold() );
  }
}



Reply via email to