From: Michihiro NAKAJIMA Date: Tue, 9 Aug 2011 08:06:39 +0000 (-0400) Subject: Improve lzss_emit_match() to be faster than previous version. X-Git-Tag: v3.0.0a~160 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cc4135f3ebff0142fcfb178c52052c12a992c7c3;p=thirdparty%2Flibarchive.git Improve lzss_emit_match() to be faster than previous version. This cahnge makes user CPU time less about 40% when extracting test_read_format_rar_ppmd_lzss_conversion.rar.uu. This idea from our lha reader. SVN-Revision: 3576 --- diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c index 39bca01f1..8f17d78b1 100644 --- a/libarchive/archive_read_support_format_rar.c +++ b/libarchive/archive_read_support_format_rar.c @@ -521,11 +521,33 @@ lzss_emit_literal(struct rar *rar, uint8_t literal) static inline void lzss_emit_match(struct rar *rar, int offset, int length) { - int i, windowoffs = lzss_current_offset(&rar->lzss); - for(i = 0; i < length; i++) - { - rar->lzss.window[(windowoffs + i) & lzss_mask(&rar->lzss)] = - rar->lzss.window[(windowoffs + i - offset) & lzss_mask(&rar->lzss)]; + int dstoffs = lzss_current_offset(&rar->lzss); + int srcoffs = (dstoffs - offset) & lzss_mask(&rar->lzss); + int l, li, remaining; + unsigned char *d, *s; + + remaining = length; + while (remaining > 0) { + l = remaining; + if (dstoffs > srcoffs) { + if (l > lzss_size(&rar->lzss) - dstoffs) + l = lzss_size(&rar->lzss) - dstoffs; + } else { + if (l > lzss_size(&rar->lzss) - srcoffs) + l = lzss_size(&rar->lzss) - srcoffs; + } + d = &(rar->lzss.window[dstoffs]); + s = &(rar->lzss.window[srcoffs]); + if (l >= 8 && ((dstoffs + l < srcoffs) || (srcoffs + l < dstoffs))) + memcpy(d, s, l); + else { + li = l; + while (li-- > 0) + *d++ = *s++; + } + remaining -= l; + dstoffs = (dstoffs + l) & lzss_mask(&(rar->lzss)); + srcoffs = (srcoffs + l) & lzss_mask(&(rar->lzss)); } rar->lzss.position += length; }