]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Improve lzss_emit_match() to be faster than previous version.
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Tue, 9 Aug 2011 08:06:39 +0000 (04:06 -0400)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Tue, 9 Aug 2011 08:06:39 +0000 (04:06 -0400)
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

libarchive/archive_read_support_format_rar.c

index 39bca01f15026f35fab6e0ea90e7dcdcc70b7645..8f17d78b1ba19687ad7b9c9515d85732628f650f 100644 (file)
@@ -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;
 }