summaryrefslogtreecommitdiff
path: root/lzf_d.c
diff options
context:
space:
mode:
authorroot <root>2010-05-30 05:46:55 +0000
committerroot <root>2010-05-30 05:46:55 +0000
commit93f371a3809b11713e0230705637e7f148904505 (patch)
tree1a75258c5c55abfff7cc9a4d66524faf668b689b /lzf_d.c
parenta7c01fa037a0965364cfd1fe2d19c158aa2bafaf (diff)
*** empty log message ***
Diffstat (limited to 'lzf_d.c')
-rw-r--r--lzf_d.c57
1 files changed, 48 insertions, 9 deletions
diff --git a/lzf_d.c b/lzf_d.c
index 9e2cd82..076d1d9 100644
--- a/lzf_d.c
+++ b/lzf_d.c
@@ -36,6 +36,8 @@
#include "lzfP.h"
+#include <string.h> /* for memcpy/memset */
+
#if AVOID_ERRNO
# define SET_ERRNO(n)
#else
@@ -43,12 +45,14 @@
# define SET_ERRNO(n) errno = (n)
#endif
+#if USE_REP_MOVSB /* small win on amd, big loss on intel */
#if (__i386 || __amd64) && __GNUC__ >= 3
# define lzf_movsb(dst, src, len) \
asm ("rep movsb" \
: "=D" (dst), "=S" (src), "=c" (len) \
: "0" (dst), "1" (src), "2" (len));
#endif
+#endif
unsigned int
lzf_decompress (const void *const in_data, unsigned int in_len,
@@ -84,9 +88,17 @@ lzf_decompress (const void *const in_data, unsigned int in_len,
#ifdef lzf_movsb
lzf_movsb (op, ip, ctrl);
#else
- do
- *op++ = *ip++;
- while (--ctrl);
+ switch (ctrl)
+ {
+ case 32: *op++ = *ip++; case 31: *op++ = *ip++; case 30: *op++ = *ip++; case 29: *op++ = *ip++;
+ case 28: *op++ = *ip++; case 27: *op++ = *ip++; case 26: *op++ = *ip++; case 25: *op++ = *ip++;
+ case 24: *op++ = *ip++; case 23: *op++ = *ip++; case 22: *op++ = *ip++; case 21: *op++ = *ip++;
+ case 20: *op++ = *ip++; case 19: *op++ = *ip++; case 18: *op++ = *ip++; case 17: *op++ = *ip++;
+ case 16: *op++ = *ip++; case 15: *op++ = *ip++; case 14: *op++ = *ip++; case 13: *op++ = *ip++;
+ case 12: *op++ = *ip++; case 11: *op++ = *ip++; case 10: *op++ = *ip++; case 9: *op++ = *ip++;
+ case 8: *op++ = *ip++; case 7: *op++ = *ip++; case 6: *op++ = *ip++; case 5: *op++ = *ip++;
+ case 4: *op++ = *ip++; case 3: *op++ = *ip++; case 2: *op++ = *ip++; case 1: *op++ = *ip++;
+ }
#endif
}
else /* back reference */
@@ -132,12 +144,39 @@ lzf_decompress (const void *const in_data, unsigned int in_len,
len += 2;
lzf_movsb (op, ref, len);
#else
- *op++ = *ref++;
- *op++ = *ref++;
-
- do
- *op++ = *ref++;
- while (--len);
+ switch (len)
+ {
+ default:
+ len += 2;
+
+ if (op >= ref + len)
+ {
+ /* disjunct areas */
+ memcpy (op, ref, len);
+ op += len;
+ }
+ else
+ {
+ /* overlapping, use octte by octte copying */
+ do
+ *op++ = *ref++;
+ while (--len);
+ }
+
+ break;
+
+ case 9: *op++ = *ref++;
+ case 8: *op++ = *ref++;
+ case 7: *op++ = *ref++;
+ case 6: *op++ = *ref++;
+ case 5: *op++ = *ref++;
+ case 4: *op++ = *ref++;
+ case 3: *op++ = *ref++;
+ case 2: *op++ = *ref++;
+ case 1: *op++ = *ref++;
+ case 0: *op++ = *ref++; /* two octets more */
+ *op++ = *ref++;
+ }
#endif
}
}