X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FEml.pm;h=f022516c12cd091cd2ee6bc77212208f399b7522;hb=e07a58aa1a1118b2aeb75e674c3542ae5d93b2c9;hp=1adaff04f7be871d1ab9343c4bb737436b603d09;hpb=d35a49e114579a4df7bcb23d013ef0101cbb3ec2;p=public-inbox.git diff --git a/lib/PublicInbox/Eml.pm b/lib/PublicInbox/Eml.pm index 1adaff04..f022516c 100644 --- a/lib/PublicInbox/Eml.pm +++ b/lib/PublicInbox/Eml.pm @@ -71,11 +71,19 @@ sub re_memo ($) { # compatible with our uses of Email::MIME sub new { my $ref = ref($_[1]) ? $_[1] : \(my $cpy = $_[1]); - if ($$ref =~ /(?:\r?\n(\r?\n))/gs) { # likely - # This can modify $$ref in-place and to avoid memcpy/memmove - # on a potentially large $$ref. It does need to make a - # copy for $hdr, though. Idea stolen from Email::Simple - my $hdr = substr($$ref, 0, pos($$ref), ''); # sv_chop on $$ref + # substr() can modify the first arg in-place and to avoid + # memcpy/memmove on a potentially large scalar. It does need + # to make a copy for $hdr, though. Idea stolen from Email::Simple. + + # We also prefer index() on common LFLF emails since it's faster + # and re scan can bump RSS by length($$ref) on big strings + if (index($$ref, "\r\n") < 0 && (my $pos = index($$ref, "\n\n")) >= 0) { + # likely on *nix + my $hdr = substr($$ref, 0, $pos + 2, ''); # sv_chop on $$ref + chop($hdr); # lower SvCUR + bless { hdr => \$hdr, crlf => "\n", bdy => $ref }, __PACKAGE__; + } elsif ($$ref =~ /\r?\n(\r?\n)/s) { + my $hdr = substr($$ref, 0, $+[0], ''); # sv_chop on $$ref substr($hdr, -(length($1))) = ''; # lower SvCUR bless { hdr => \$hdr, crlf => $1, bdy => $ref }, __PACKAGE__; } elsif ($$ref =~ /^[a-z0-9-]+[ \t]*:/ims && $$ref =~ /(\r?\n)\z/s) { @@ -90,8 +98,8 @@ sub new { sub new_sub { my (undef, $ref) = @_; # special case for messages like <85k5su9k59.fsf_-_@lola.goethe.zz> - $$ref =~ /\A(?:(\r?\n))/gs or goto &new; - my $hdr = substr($$ref, 0, pos($$ref), ''); # sv_chop on $$ref + $$ref =~ /\A(\r?\n)/s or goto &new; + my $hdr = substr($$ref, 0, $+[0], ''); # sv_chop on $$ref bless { hdr => \$hdr, crlf => $1, bdy => $ref }, __PACKAGE__; } @@ -131,8 +139,12 @@ sub mp_descend ($$) { # Cut at the the first epilogue, not subsequent ones. # *sigh* just the regexp match alone seems to bump RSS by # length($$bdy) on a ~30M string: - $$bdy =~ /((?:\r?\n)?^--$bnd--[ \t]*\r?$)/gsm and - substr($$bdy, pos($$bdy) - length($1)) = ''; + my $epilogue_missing; + if ($$bdy =~ /(?:\r?\n)?^--$bnd--[ \t]*\r?$/sm) { + substr($$bdy, $-[0]) = ''; + } else { + $epilogue_missing = 1; + } # *Sigh* split() doesn't work in-place and return CoW strings # because Perl wants to "\0"-terminate strings. So split() @@ -150,6 +162,10 @@ sub mp_descend ($$) { if (@parts) { # the usual path if we got this far: undef $bdy; # release memory ASAP if $nr > 0 + + # compatibility with Email::MIME + $parts[-1] =~ s/\n\r?\n\z/\n/s if $epilogue_missing; + @parts = grep /[^ \t\r\n]/s, @parts; # ignore empty parts # Keep "From: someone..." from preamble in old,