From 43aa2bbc2378127a55e45bc3a4fb5d411c58925b Mon Sep 17 00:00:00 2001 From: qbix79 Date: Sun, 25 May 2008 08:23:53 +0000 Subject: [PATCH] Update lzf to 3.2 fixes texturecache on 64 bit. git-svn-id: https://svn.eduke32.com/eduke32@742 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/build/include/lzf.h | 24 ++- polymer/build/src/lzfP.h | 68 +++---- polymer/build/src/lzf_c.c | 355 ++++++++++++++++++++---------------- polymer/build/src/lzf_d.c | 148 +++++++++------ 4 files changed, 337 insertions(+), 258 deletions(-) diff --git a/polymer/build/include/lzf.h b/polymer/build/include/lzf.h index 8538609ab..1b6da2108 100644 --- a/polymer/build/include/lzf.h +++ b/polymer/build/include/lzf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 Marc Alexander Lehmann + * Copyright (c) 2000-2007 Marc Alexander Lehmann * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: @@ -11,9 +11,6 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO @@ -26,14 +23,15 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License version 2 (the "GPL"), in which case the - * provisions of the GPL are applicable instead of the above. If you wish to - * allow the use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the - * BSD license, indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by the GPL. If - * you do not delete the provisions above, a recipient may use your version - * of this file under either the BSD or the GPL. + * the GNU General Public License ("GPL") version 2 or any later version, + * in which case the provisions of the GPL are applicable instead of + * the above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use your + * version of this file under the BSD license, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete the + * provisions above, a recipient may use your version of this file under + * either the BSD or the GPL. */ #ifndef LZF_H @@ -62,7 +60,7 @@ * the data uncompressed otherwise. * * lzf_compress might use different algorithms on different systems and - * even diferent runs, thus might result in different compressed strings + * even different runs, thus might result in different compressed strings * depending on the phase of the moon or similar factors. However, all * these strings are architecture-independent and will result in the * original data when decompressed using lzf_decompress. diff --git a/polymer/build/src/lzfP.h b/polymer/build/src/lzfP.h index 48963b2bc..d533f1829 100644 --- a/polymer/build/src/lzfP.h +++ b/polymer/build/src/lzfP.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 Marc Alexander Lehmann + * Copyright (c) 2000-2007 Marc Alexander Lehmann * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: @@ -11,9 +11,6 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO @@ -26,14 +23,15 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License version 2 (the "GPL"), in which case the - * provisions of the GPL are applicable instead of the above. If you wish to - * allow the use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the - * BSD license, indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by the GPL. If - * you do not delete the provisions above, a recipient may use your version - * of this file under either the BSD or the GPL. + * the GNU General Public License ("GPL") version 2 or any later version, + * in which case the provisions of the GPL are applicable instead of + * the above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use your + * version of this file under the BSD license, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete the + * provisions above, a recipient may use your version of this file under + * either the BSD or the GPL. */ #ifndef LZFP_h @@ -46,29 +44,28 @@ #endif /* - * size of hashtable is (1 << HLOG) * sizeof (char *) + * Size of hashtable is (1 << HLOG) * sizeof (char *) * decompression is independent of the hash table size * the difference between 15 and 14 is very small - * for small blocks (and 14 is usually a but faster). + * for small blocks (and 14 is usually a bit faster). * For a low-memory/faster configuration, use HLOG == 13; - * For best compression, use 15 or 16 (or more). + * For best compression, use 15 or 16 (or more, up to 23). */ #ifndef HLOG -# define HLOG 14 +# define HLOG 16 #endif /* - * sacrifice very little compression quality in favour of compression speed. + * Sacrifice very little compression quality in favour of compression speed. * This gives almost the same compression as the default code, and is - * (very roughly) 15% faster. This is the preferable mode of operation. + * (very roughly) 15% faster. This is the preferred mode of operation. */ - #ifndef VERY_FAST # define VERY_FAST 1 #endif /* - * sacrifice some more compression quality in favour of compression speed. + * Sacrifice some more compression quality in favour of compression speed. * (roughly 1-2% worse compression for large blocks and * 9-10% for small, redundant, blocks and >>20% better speed in both cases) * In short: when in need for speed, enable this for binary data, @@ -79,30 +76,23 @@ #endif /* - * unconditionally aligning does not cost very much, so do it if unsure + * Unconditionally aligning does not cost very much, so do it if unsure */ #ifndef STRICT_ALIGN # define STRICT_ALIGN !(defined(__i386) || defined (__amd64)) #endif /* - * use string functions to copy memory. - * this is usually a loss, even with glibc's optimized memcpy - */ -#ifndef USE_MEMCPY -# define USE_MEMCPY 0 -#endif - -/* - * you may choose to pre-set the hash table (might be faster on some - * modern cpus and large (>>64k) blocks) + * You may choose to pre-set the hash table (might be faster on some + * modern cpus and large (>>64k) blocks, and also makes compression + * deterministic/repeatable when the configuration otherwise is the same). */ #ifndef INIT_HTAB # define INIT_HTAB 0 #endif /* - * avoid assigning values to errno variable? for some embedding purposes + * Avoid assigning values to errno variable? for some embedding purposes * (linux kernel for example), this is neccessary. NOTE: this breaks * the documentation in lzf.h. */ @@ -119,6 +109,18 @@ # define LZF_STATE_ARG 0 #endif +/* + * Wether to add extra checks for input validity in lzf_decompress + * and return EINVAL if the input stream has been corrupted. This + * only shields against overflowing the input buffer and will not + * detect most corrupted streams. + * This check is not normally noticable on modern hardware + * (<1% slowdown), but might slow down older cpus considerably. + */ +#ifndef CHECK_INPUT +# define CHECK_INPUT 1 +#endif + /*****************************************************************************/ /* nothing should be changed below */ @@ -145,7 +147,7 @@ typedef const u8 *LZF_STATE[1 << (HLOG)]; # endif #endif -#if USE_MEMCPY || INIT_HTAB +#if INIT_HTAB # ifdef __cplusplus # include # else diff --git a/polymer/build/src/lzf_c.c b/polymer/build/src/lzf_c.c index 3dcda790c..c1847f3a7 100644 --- a/polymer/build/src/lzf_c.c +++ b/polymer/build/src/lzf_c.c @@ -1,19 +1,16 @@ /* - * Copyright (c) 2000-2005 Marc Alexander Lehmann - * + * Copyright (c) 2000-2007 Marc Alexander Lehmann + * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO @@ -26,14 +23,15 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License version 2 (the "GPL"), in which case the - * provisions of the GPL are applicable instead of the above. If you wish to - * allow the use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the - * BSD license, indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by the GPL. If - * you do not delete the provisions above, a recipient may use your version - * of this file under either the BSD or the GPL. + * the GNU General Public License ("GPL") version 2 or any later version, + * in which case the provisions of the GPL are applicable instead of + * the above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use your + * version of this file under the BSD license, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete the + * provisions above, a recipient may use your version of this file under + * either the BSD or the GPL. */ #include "lzfP.h" @@ -49,12 +47,18 @@ #ifndef FRST # define FRST(p) (((p[0]) << 8) | p[1]) # define NEXT(v,p) (((v) << 8) | p[2]) -# define IDX(h) ((((h ^ (h << 5)) >> (3*8 - HLOG)) - h*5) & (HSIZE - 1)) +# if ULTRA_FAST +# define IDX(h) ((( h >> (3*8 - HLOG)) - h ) & (HSIZE - 1)) +# elif VERY_FAST +# define IDX(h) ((( h >> (3*8 - HLOG)) - h*5) & (HSIZE - 1)) +# else +# define IDX(h) ((((h ^ (h << 5)) >> (3*8 - HLOG)) - h*5) & (HSIZE - 1)) +# endif #endif /* * IDX works because it is very similar to a multiplicative hash, e.g. * ((h * 57321 >> (3*8 - HLOG)) & (HSIZE - 1)) - * the latter is also quite fast on newer CPUs, and sligthly better + * the latter is also quite fast on newer CPUs, and compresses similarly. * * the next one is also quite good, albeit slow ;) * (int)(cos(h & 0xffffff) * 1e6) @@ -69,7 +73,18 @@ #define MAX_LIT (1 << 5) #define MAX_OFF (1 << 13) -#define MAX_REF ((1 << 8) + (1 << 3)) +#define MAX_REF ((1 << 8) + (1 << 3)) + +#if __GNUC__ >= 3 +# define expect(expr,value) __builtin_expect ((expr),(value)) +# define inline inline +#else +# define expect(expr,value) (expr) +# define inline static +#endif + +#define expect_false(expr) expect ((expr) != 0, 0) +#define expect_true(expr) expect ((expr) != 0, 1) /* * compressed format @@ -81,162 +96,194 @@ */ unsigned int -lzf_compress(const void *const in_data, unsigned int in_len, - void *out_data, unsigned int out_len +lzf_compress (const void *const in_data, unsigned int in_len, + void *out_data, unsigned int out_len #if LZF_STATE_ARG - , LZF_STATE *htab + , LZF_STATE htab #endif - ) + ) { #if !LZF_STATE_ARG - LZF_STATE htab; + LZF_STATE htab; #endif - const u8 **hslot; - const u8 *ip = (const u8 *)in_data; - u8 *op = (u8 *)out_data; - const u8 *in_end = ip + in_len; - u8 *out_end = op + out_len; - const u8 *ref; + const u8 **hslot; + const u8 *ip = (const u8 *)in_data; + u8 *op = (u8 *)out_data; + const u8 *in_end = ip + in_len; + u8 *out_end = op + out_len; + const u8 *ref; - unsigned int hval = FRST(ip); - unsigned int off; - int lit = 0; + /* off requires a type wide enough to hold a general pointer difference. + * ISO C doesn't have that (size_t might not be enough and ptrdiff_t only + * works for differences within a single object). We also assume that no + * no bit pattern traps. Since the only platform that is both non-POSIX + * and fails to support both assumptions is windows 64 bit, we make a + * special workaround for it. + */ +#if defined (WIN32) && defined (_M_X64) + unsigned _int64 off; /* workaround for missing POSIX compliance */ +#else + unsigned long off; +#endif + unsigned int hval; + int lit; + + if (!in_len || !out_len) + return 0; #if INIT_HTAB -# if USE_MEMCPY - memset(htab, 0, sizeof(htab)); -# else - for (hslot = htab; hslot < htab + HSIZE; hslot++) - *hslot++ = ip; + memset (htab, 0, sizeof (htab)); +# if 0 + for (hslot = htab; hslot < htab + HSIZE; hslot++) + *hslot++ = ip; # endif #endif - for (;;) - { - if (ip < in_end - 2) - { - hval = NEXT(hval, ip); - hslot = htab + IDX(hval); - ref = *hslot; *hslot = ip; + lit = 0; op++; /* start run */ - if (1 -#if INIT_HTAB && !USE_MEMCPY - && ref < ip /* the next test will actually take care of this, but this is faster */ + hval = FRST (ip); + while (ip < in_end - 2) + { + hval = NEXT (hval, ip); + hslot = htab + IDX (hval); + ref = *hslot; *hslot = ip; + + if (1 +#if INIT_HTAB + && ref < ip /* the next test will actually take care of this, but this is faster */ #endif - && (off = ip - ref - 1) < MAX_OFF - && ip + 4 < in_end - && ref > (u8 *)in_data + && (off = ip - ref - 1) < MAX_OFF + && ip + 4 < in_end + && ref > (u8 *)in_data #if STRICT_ALIGN - && ref[0] == ip[0] - && ref[1] == ip[1] - && ref[2] == ip[2] + && ref[0] == ip[0] + && ref[1] == ip[1] + && ref[2] == ip[2] #else - && *(u16 *)ref == *(u16 *)ip - && ref[2] == ip[2] + && *(u16 *)ref == *(u16 *)ip + && ref[2] == ip[2] #endif - ) - { - /* match found at *ref++ */ - unsigned int len = 2; - unsigned int maxlen = in_end - ip - len; - maxlen = maxlen > MAX_REF ? MAX_REF : maxlen; - - if (op + lit + 1 + 3 >= out_end) - return 0; - - do - len++; - while (len < maxlen && ref[len] == ip[len]); - - if (lit) - { - *op++ = lit - 1; - lit = -lit; - do - *op++ = ip[lit]; - while (++lit); - } - - len -= 2; - ip++; - - if (len < 7) - { - *op++ = (off >> 8) + (len << 5); - } - else - { - *op++ = (off >> 8) + (7 << 5); - *op++ = len - 7; - } - - *op++ = off; - -#if ULTRA_FAST || VERY_FAST - ip += len; -#if VERY_FAST && !ULTRA_FAST - --ip; -#endif - hval = FRST(ip); - - hval = NEXT(hval, ip); - htab[IDX(hval)] = ip; - ip++; - -#if VERY_FAST && !ULTRA_FAST - hval = NEXT(hval, ip); - htab[IDX(hval)] = ip; - ip++; -#endif -#else - do - { - hval = NEXT(hval, ip); - htab[IDX(hval)] = ip; - ip++; - } - while (len--); -#endif - continue; - } - } - else if (ip == in_end) - break; - - /* one more literal byte we must copy */ - lit++; - ip++; - - if (lit == MAX_LIT) + ) { - if (op + 1 + MAX_LIT >= out_end) - return 0; + /* match found at *ref++ */ + unsigned int len = 2; + unsigned int maxlen = in_end - ip - len; + maxlen = maxlen > MAX_REF ? MAX_REF : maxlen; - *op++ = MAX_LIT - 1; -#if USE_MEMCPY - memcpy(op, ip - MAX_LIT, MAX_LIT); - op += MAX_LIT; - lit = 0; -#else - lit = -lit; - do - *op++ = ip[lit]; - while (++lit); -#endif - } - } + op [- lit - 1] = lit - 1; /* stop run */ + op -= !lit; /* undo run if length is zero */ - if (lit) - { - if (op + lit + 1 >= out_end) + if (expect_false (op + 3 + 1 >= out_end)) return 0; - *op++ = lit - 1; - lit = -lit; - do - *op++ = ip[lit]; - while (++lit); + for (;;) + { + if (expect_true (maxlen > 16)) + { + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + len++; if (ref [len] != ip [len]) break; + } + + do + len++; + while (len < maxlen && ref[len] == ip[len]); + + break; + } + + len -= 2; + ip++; + + if (len < 7) + { + *op++ = (off >> 8) + (len << 5); + } + else + { + *op++ = (off >> 8) + ( 7 << 5); + *op++ = len - 7; + } + + *op++ = off; + +#if ULTRA_FAST || VERY_FAST + ip += len; +#if VERY_FAST && !ULTRA_FAST + --ip; +#endif + hval = FRST (ip); + + hval = NEXT (hval, ip); + htab[IDX (hval)] = ip; + ip++; + +#if VERY_FAST && !ULTRA_FAST + hval = NEXT (hval, ip); + htab[IDX (hval)] = ip; + ip++; +#endif +#else + do + { + hval = NEXT (hval, ip); + htab[IDX (hval)] = ip; + ip++; + } + while (len--); +#endif + + lit = 0; op++; /* start run */ + } + else + { + /* one more literal byte we must copy */ + if (expect_false (op >= out_end)) + return 0; + + lit++; *op++ = *ip++; + + if (expect_false (lit == MAX_LIT)) + { + op [- lit - 1] = lit - 1; /* stop run */ + lit = 0; op++; /* start run */ + } + } } - return op - (u8 *) out_data; + if (op + 3 > out_end) /* at most 3 bytes can be missing here */ + return 0; + + while (ip < in_end) + { + lit++; *op++ = *ip++; + + if (expect_false (lit == MAX_LIT)) + { + op [- lit - 1] = lit - 1; /* stop run */ + lit = 0; op++; /* start run */ + } + } + + op [- lit - 1] = lit - 1; /* end run */ + op -= !lit; /* undo run if length is zero */ + + return op - (u8 *)out_data; } + diff --git a/polymer/build/src/lzf_d.c b/polymer/build/src/lzf_d.c index d2ddb8b7a..9e2cd829c 100644 --- a/polymer/build/src/lzf_d.c +++ b/polymer/build/src/lzf_d.c @@ -1,19 +1,16 @@ /* - * Copyright (c) 2000-2005 Marc Alexander Lehmann - * + * Copyright (c) 2000-2007 Marc Alexander Lehmann + * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO @@ -26,14 +23,15 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License version 2 (the "GPL"), in which case the - * provisions of the GPL are applicable instead of the above. If you wish to - * allow the use of your version of this file only under the terms of the - * GPL and not to allow others to use your version of this file under the - * BSD license, indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by the GPL. If - * you do not delete the provisions above, a recipient may use your version - * of this file under either the BSD or the GPL. + * the GNU General Public License ("GPL") version 2 or any later version, + * in which case the provisions of the GPL are applicable instead of + * the above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use your + * version of this file under the BSD license, indicate your decision + * by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete the + * provisions above, a recipient may use your version of this file under + * either the BSD or the GPL. */ #include "lzfP.h" @@ -45,72 +43,106 @@ # define SET_ERRNO(n) errno = (n) #endif -unsigned int -lzf_decompress(const void *const in_data, unsigned int in_len, - void *out_data, unsigned int out_len) +#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 + +unsigned int +lzf_decompress (const void *const in_data, unsigned int in_len, + void *out_data, unsigned int out_len) { - u8 const *ip = (const u8 *)in_data; - u8 *op = (u8 *)out_data; - u8 const *const in_end = ip + in_len; - u8 *const out_end = op + out_len; + u8 const *ip = (const u8 *)in_data; + u8 *op = (u8 *)out_data; + u8 const *const in_end = ip + in_len; + u8 *const out_end = op + out_len; - do + do { - unsigned int ctrl = *ip++; + unsigned int ctrl = *ip++; - if (ctrl < (1 << 5)) /* literal run */ + if (ctrl < (1 << 5)) /* literal run */ { - ctrl++; + ctrl++; - if (op + ctrl > out_end) + if (op + ctrl > out_end) { - SET_ERRNO(E2BIG); - return 0; + SET_ERRNO (E2BIG); + return 0; } -#if USE_MEMCPY - memcpy(op, ip, ctrl); - op += ctrl; - ip += ctrl; +#if CHECK_INPUT + if (ip + ctrl > in_end) + { + SET_ERRNO (EINVAL); + return 0; + } +#endif + +#ifdef lzf_movsb + lzf_movsb (op, ip, ctrl); #else - do - *op++ = *ip++; - while (--ctrl); + do + *op++ = *ip++; + while (--ctrl); #endif } - else /* back reference */ + else /* back reference */ { - unsigned int len = ctrl >> 5; + unsigned int len = ctrl >> 5; - u8 *ref = op - ((ctrl & 0x1f) << 8) - 1; + u8 *ref = op - ((ctrl & 0x1f) << 8) - 1; - if (len == 7) - len += *ip++; - - ref -= *ip++; - - if (op + len + 2 > out_end) +#if CHECK_INPUT + if (ip >= in_end) { - SET_ERRNO(E2BIG); - return 0; + SET_ERRNO (EINVAL); + return 0; + } +#endif + if (len == 7) + { + len += *ip++; +#if CHECK_INPUT + if (ip >= in_end) + { + SET_ERRNO (EINVAL); + return 0; + } +#endif } - if (ref < (u8 *)out_data) + ref -= *ip++; + + if (op + len + 2 > out_end) { - SET_ERRNO(EINVAL); - return 0; + SET_ERRNO (E2BIG); + return 0; } - *op++ = *ref++; - *op++ = *ref++; + if (ref < (u8 *)out_data) + { + SET_ERRNO (EINVAL); + return 0; + } - do - *op++ = *ref++; - while (--len); +#ifdef lzf_movsb + len += 2; + lzf_movsb (op, ref, len); +#else + *op++ = *ref++; + *op++ = *ref++; + + do + *op++ = *ref++; + while (--len); +#endif } } - while (op < out_end && ip < in_end); + while (ip < in_end); - return op - (u8 *)out_data; + return op - (u8 *)out_data; }