├── Changes ├── LICENSE ├── Makefile.in ├── README ├── bench.c ├── configure.ac ├── crc32.h ├── cs ├── CLZF.cs └── README ├── lzf.c ├── lzf.h ├── lzfP.h ├── lzf_c.c ├── lzf_c_best.c └── lzf_d.c /Changes: -------------------------------------------------------------------------------- 1 | 2 | TODO: try unaligned copy again in decompressor 3 | TODO: allow size-optimised binaries by avoiding unrolling 4 | TODO: implement lzf_c_best in lzf. 5 | 6 | 3.8 (unreleased) 7 | - support a state arg for lzf_c_best. 8 | 9 | 3.7 (unreleased) 10 | - add lzf_c_best.c, a slower but better compressor. 11 | - switch to a multiplicative hash (developed with Steinar Gunderson), 12 | which is faster on modern cpus and compresses a bit better. The old 13 | hash function which uses only shifts is still available. 14 | - allow user configurable hash table slots, which makes it possible 15 | to use e.g. 16 bit offsets for a smaller hashtable (if your data is 16 | always < 64kb). 17 | - use _WIN32, not WIN32, when testing for windows (fails with bcc), 18 | patch by Tamas Tevesz. 19 | - try to port to win64+gcc, which is non-posix but doesn't have _int64 20 | (reported by Maciej Adamczyk). 21 | 22 | 3.6 Mon Feb 7 17:37:31 CET 2011 23 | - fixed hash calculation in C♯ version (Tiago Freitas Leal). 24 | - unroll copy for small sizes, use memcpy for larger sizes, 25 | greatly speeding up decompression in most cases. 26 | - finally disable rep movsb - it's a big loss on modern intel cpus, 27 | and only a small win on amd cpus. 28 | - improve C++ compatibility of the code. 29 | - slightly improve compressor speed. 30 | - halved memory requirements for compressor on 64 bit architectures, 31 | which can improve the speed quite a bit on older cpus. 32 | 33 | 3.5 Fri May 1 02:28:42 CEST 2009 34 | - lzf_compress did sometimes write one octet past the given output 35 | buffer (analyzed and nice testcase by Salvatore Sanfilippo). 36 | 37 | 3.4 Tue Sep 2 06:45:00 CEST 2008 38 | - the fix from 3.3 introduced a compression bug, which is fixed in 39 | this release (which explains the mysterious prerelease...). Thanks 40 | once more to Clément Calmels. 41 | 42 | 3.3 Mon Aug 25 03:17:42 CEST 2008 43 | - lzf_compress could access memory after the given input buffer 44 | when outputting back references. reported with nice testcase 45 | by Clément Calmels. 46 | 47 | 3.2 Fri May 9 18:52:23 CEST 2008 48 | - include a workaround for failing POSIX and real-world compliance 49 | on 64 bit windows (microsoft claims to support POSIX, but is far 50 | from it). (bug found and analysed nicely by John Lilley). 51 | 52 | 3.1 Fri Nov 30 11:33:04 CET 2007 53 | - IMPORTANT BUGFIX: a too long final literal run would corrupt data 54 | in the encoder (this was introduced in 3.0 only, earlier versions 55 | are safe). 56 | 57 | 3.0 Tue Nov 13 22:13:09 CET 2007 58 | - switched to 2-clause bsd with "GPL v2 or any later version" option. 59 | - speed up compression by ~10-15% in common cases 60 | by some manual unrolling. 61 | - import some compiler tricks from JSON::XS, for further speed-ups. 62 | - tune hash functions depending on ULTRA_FAST or VERY_FAST settings. 63 | - for typical binary data (e.g. /bin/bash, memory dumps, 64 | canterbury corpus etc.), speed is now comparable to fastlz, but 65 | with better compression ratio. with ULTRA_FAST, it's typically 66 | 3-15% faster than fastlz while still maintaining a similar ratio. 67 | (amd64 and core 2 duo, ymmv). thanks a lot for the competition :) 68 | - undo inline assembly in compressor, it is no longer helpful. 69 | - no changes to the decompressor. 70 | - use a HLOG of 16 by default now (formerly 15). 71 | 72 | 2.1 Fri Nov 2 13:34:42 CET 2007 73 | - switched to a 2-clause bsd license with GPL exception. 74 | - get rid of memcpy. 75 | - tentatively use rep movsb on x86 and x86_64 (gcc only) for a 76 | moderate speed improvement. 77 | - applied patch by Kein-Hong Man to maske lzf.c compile under 78 | the crippled mingw32 environment. 79 | 80 | 2.0 Fri Feb 16 23:11:18 CET 2007 81 | - replaced lzf demo by industrial-strength lzf utility with behaviour 82 | similar other compression utilities. Thanks for Stefan Traby for 83 | rewriting it! 84 | - fix state arg prototype. 85 | 86 | 1.7 Wed Sep 27 17:29:15 CEST 2006 87 | - remove bogus "unlzf" patch. 88 | note to self: never accept well-meant patches. 89 | - make lzf more robust in presence of padding bytes or sudden eof. 90 | 91 | 1.6 Fri Jul 7 17:31:26 CEST 2006 92 | - the lzf example utility will now uncompress if invoked 93 | as "unlzf" (patch by Scott Feeney). 94 | - add CHECK_INPUT option that adds more checks for input 95 | data validity. 96 | - help applications that do not pass in the correct length 97 | (such as php) by returning either EINVAL or E2BIG. 98 | - default HLOG size is now 15 (cpu caches have increased). 99 | - documentation fixes. 100 | 101 | 1.51 Thu Apr 14 22:15:46 CEST 2005 102 | - incorporated C♯ implementation of both the en- and decoder, 103 | written by "Oren J. Maurice". 104 | You can find it in the cs/ subdirectory. 105 | - make FRST, NEXT IDX overridable if lzf_c.c is directly included 106 | in the code. 107 | 108 | 1.5 Tue Mar 8 20:23:23 CET 2005 109 | - incorporated improvements by Adam D. Moss, 110 | which includes a new VERY_FAST mode which is 111 | a bit slower than ULTRA_FAST but much better, 112 | and enabled it as default. 113 | 114 | 1.401 Thu Mar 3 18:00:52 CET 2005 115 | - use cstring in c++, not string.h. 116 | - change of contact address. 117 | 118 | 1.4 Wed Dec 15 08:08:49 CET 2004 119 | - very very slight tuning of the hashing function. 120 | 121 | 1.3 Thu Mar 25 15:41:17 CET 2004 122 | - changed license of lzf core code to explicitly allow 123 | relicensing under the GPLv2. 124 | - added VPATH support as suggested by Björn Eriksson. 125 | 126 | 1.2 Mon Dec 29 13:47:28 CET 2003 127 | - avoid spurious memory accesses after the to-be-compressed 128 | memory region. originally reported by Michal Zalewski. 129 | - flip LZF_STACK_ARG meaning (to be correct). 130 | 131 | 1.1 Tue Dec 23 05:48:32 CET 2003 132 | - removed #warn directive, it's not worth the hassle. 133 | - add LZF_STACK_ARG and AVOID_ERRNO configurations 134 | for embedded systems. 135 | - make it compile cleanly as c++. 136 | - some small documentation and code fixes. 137 | 138 | 1.0 Sun Nov 17 12:37:37 CET 2002 139 | - slightly better compression ratio, almost unmeasurably 140 | slower. 141 | - some documentation fixes. 142 | 143 | 0.4 Thu Jun 13 14:11:10 CEST 2002 144 | - typoe fix. 145 | - lzf demo program now properly decompresses small files. 146 | - fix another 64 bit issue, found by Laurent Deniel. 147 | 148 | 0.3 Tue Jan 16 13:21:14 CET 2001 149 | - fix silly beginners 32/64 bit mistake. 150 | 151 | 0.2 Thu Jan 4 05:56:42 CET 2001 152 | - now totally independent of autoconfig, for 153 | easy inclusion into other programs. 154 | - much better fine-tuning, faster and better than 0.1. 155 | 156 | 0.1 2000 157 | - initial release. 158 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2000-2009 Marc Alexander Lehmann 2 | 3 | Redistribution and use in source and binary forms, with or without modifica- 4 | tion, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 14 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 15 | CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 16 | EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 17 | CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 19 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 21 | ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 22 | OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | Alternatively, the following files carry an additional notice that 25 | explicitly allows relicensing under the GPLv2: lzf.c lzf.h lzfP.h lzf_c.c 26 | lzf_d.c 27 | 28 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | VERSION = 3.6 2 | 3 | prefix = @prefix@ 4 | exec_prefix = @exec_prefix@ 5 | libdir = @libdir@ 6 | bindir = @bindir@ 7 | includedir = @includedir@ 8 | 9 | VPATH = @srcdir@ 10 | 11 | CC = @CC@ 12 | CPPFLAGS = -I. @CPPFLAGS@ 13 | CFLAGS = @CFLAGS@ 14 | LDFLAGS = @LDFLAGS@ 15 | RANLIB = @RANLIB@ 16 | INSTALL = @INSTALL@ 17 | INSTALL_DATA = @INSTALL_DATA@ 18 | 19 | all: Makefile lzf 20 | 21 | clean: 22 | -rm -f *.o *.a lzf bench 23 | 24 | lzf_c.o: lzf_c.c lzfP.h 25 | 26 | lzf_d.o: lzf_d.c lzfP.h 27 | 28 | lzf.o: lzf.c 29 | 30 | lzf: lzf.o liblzf.a 31 | 32 | lzfP.h: lzf.h config.h 33 | 34 | liblzf.a: lzf_c.o lzf_d.o 35 | rm -f $@ 36 | $(AR) rc $@ $^ 37 | $(RANLIB) $@ 38 | 39 | install: all 40 | $(INSTALL) -d $(bindir) 41 | $(INSTALL) -m 755 lzf $(bindir) 42 | $(INSTALL) -d $(includedir) 43 | $(INSTALL_DATA) lzf.h $(includedir) 44 | $(INSTALL) -d $(libdir) 45 | $(INSTALL_DATA) liblzf.a $(libdir) 46 | 47 | dist: 48 | mkdir liblzf-$(VERSION) 49 | tar c LICENSE README Makefile.in config.h.in \ 50 | configure configure.ac install-sh \ 51 | cs/README cs/CLZF.cs \ 52 | lzf.h lzfP.h lzf_c.c lzf_d.c \ 53 | crc32.h lzf.c Changes \ 54 | | tar xpC liblzf-$(VERSION) 55 | -chown -R root.root liblzf-$(VERSION) 56 | chmod -R u=rwX,go=rX liblzf-$(VERSION) 57 | tar cvf - liblzf-$(VERSION) | gzip -9 >liblzf-$(VERSION).tar.gz 58 | rm -rf liblzf-$(VERSION) 59 | ls -l liblzf-$(VERSION).tar.gz 60 | 61 | Makefile: Makefile.in 62 | ./config.status 63 | 64 | bench: Makefile liblzf.a bench.c 65 | $(CC) $(CPPFLAGS) $(CFLAGS) -g -o bench bench.c -L. -llzf 66 | 67 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | DESCRIPTION 2 | LZF is an extremely fast (not that much slower than a pure memcpy) 3 | compression algorithm. It is ideal for applications where you want to 4 | save *some* space but not at the cost of speed. It is ideal for 5 | repetitive data as well. The module is self-contained and very small. 6 | 7 | It's written in ISO-C with no external dependencies other than what 8 | C provides and can easily be #include'd into your code, no makefile 9 | changes or library builds requires. 10 | 11 | A C♯ implementation without external dependencies is available, too. 12 | 13 | I do not know for certain whether any patents in any countries apply 14 | to this algorithm, but at the moment it is believed that it is free 15 | from any patents. More importantly, it is also free to use in every 16 | software package (see LICENSE). 17 | 18 | See the lzf.h file for details on how the functions in this 19 | mini-library are to be used. 20 | 21 | NOTE: This package contains a very bare-bones command-line utility 22 | which is neither optimized for speed nor for compression. This library 23 | is really intended to be used inside larger programs. 24 | 25 | AUTHOR 26 | This library was written by Marc Lehmann (See also 27 | http://software.schmorp.de/pkg/liblzf). 28 | 29 | 30 | -------------------------------------------------------------------------------- /bench.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "lzf.h" 19 | //#include "fastlz.c" 20 | 21 | typedef unsigned long tval; 22 | typedef unsigned long long stamp64; 23 | 24 | extern inline tval stamp(void) 25 | { 26 | tval tsc; long dummy; 27 | asm volatile("cpuid; rdtsc" : "=a" (tsc), "=d" (dummy) : "a" (0) : "ebx", "ecx"); 28 | return tsc; 29 | } 30 | 31 | extern inline tval measure(tval t) 32 | { 33 | tval tsc; long dummy; 34 | asm volatile("cpuid; rdtsc" : "=a" (tsc), "=d" (dummy) : "a" (0) : "ebx", "ecx"); 35 | if (tsc>t) 36 | return tsc-t; 37 | else 38 | return t-tsc; 39 | } 40 | 41 | static void sigu (int signum) 42 | { 43 | } 44 | 45 | #define DSIZE 17318440 46 | //#define DSIZE 32768 47 | 48 | #include "lzf_c_best.c" 49 | 50 | unsigned char data[DSIZE], data2[DSIZE*2], data3[DSIZE*2]; 51 | 52 | int main(void) 53 | { 54 | tval s; 55 | tval si[1000]; 56 | int i, j, k, l; 57 | int min = 1<<30; 58 | int lp; 59 | char buf[8192]; 60 | int p[2]; 61 | long ctr = 1; 62 | struct stat sbuf; 63 | 64 | pipe (p); 65 | 66 | FILE *f = fopen ("data", "r"); 67 | fread (data, DSIZE, 1, f); 68 | fclose (f); 69 | 70 | signal (SIGURG, sigu); 71 | 72 | for (lp = 0; lp < 1000000; lp++) { 73 | s=stamp(); 74 | 75 | //struct timespec ts; clock_gettime (CLOCK_THREAD_CPUTIME_ID, &ts); 76 | //printf ("%9ld\n", ts.tv_nsec);//D 77 | //struct rusage usage; getrusage (RUSAGE_SELF, &usage); 78 | //struct tms tms; times (&tms); 79 | 80 | //kill (0, SIGURG); 81 | //write (evfd, &ctr, 8); 82 | //read (evfd, &ctr, 8); 83 | //write (p[1], &buf, 1); 84 | //read (p[0], &buf, 4); 85 | //stat ("/etc/passwd", &sbuf); 86 | //struct timeval tv; gettimeofday (&tv, 0); 87 | //void *x = mmap (0, 16384, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE,-1,0); 88 | 89 | l = lzf_compress_best (data, DSIZE, data2, DSIZE*2); 90 | //for (k = 0; k < l; ++k) 91 | //printf ("1 %2d: %02x\n", k, data2[k]); 92 | assert(l); 93 | 94 | j = lzf_decompress (data2, l, data3, DSIZE*2); 95 | //for (k = 0; k < j; ++k) 96 | //printf ("2 %2d: %02x\n", k, data3[k]); 97 | assert (j == DSIZE); 98 | 99 | si[0]=measure(s); 100 | 101 | assert (!memcmp (data, data3, DSIZE)); 102 | 103 | printf ("\r%10d (%d) ", si[0], l); 104 | if (si[0] < min && si[0] > 0) 105 | { 106 | printf ("\n"); 107 | min = si[0]; 108 | } 109 | 110 | fflush (stdout); 111 | 112 | //assert (memcmp (data, data3, DSIZE) == 0); 113 | } 114 | return 0; 115 | } 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT 2 | AC_CONFIG_SRCDIR([lzfP.h]) 3 | 4 | AC_CONFIG_HEADER(config.h) 5 | 6 | AC_GNU_SOURCE 7 | AC_SYS_LARGEFILE 8 | AC_PROG_CC 9 | AC_PROG_RANLIB 10 | AC_PROG_INSTALL 11 | AC_HEADER_STDC 12 | 13 | AC_C_CONST 14 | AC_C_INLINE 15 | AC_CHECK_HEADERS(getopt.h) 16 | AC_CHECK_FUNCS(getopt_long) 17 | 18 | if test "$GCC" = yes; then 19 | CFLAGS="$CFLAGS -O3 -funroll-all-loops" 20 | else 21 | AC_MSG_RESULT(no gcc) 22 | fi 23 | 24 | AC_CONFIG_FILES([Makefile]) 25 | AC_OUTPUT 26 | -------------------------------------------------------------------------------- /crc32.h: -------------------------------------------------------------------------------- 1 | #ifndef CRC32_H 2 | #define CRC32_H 3 | 4 | /* crc32 0xdebb20e3 table and supplementary functions. */ 5 | 6 | static const u32 crc_32_tab[] = 7 | { 8 | 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, 9 | 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, 10 | 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, 11 | 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, 12 | 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, 13 | 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, 14 | 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, 15 | 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, 16 | 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, 17 | 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, 18 | 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, 19 | 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, 20 | 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, 21 | 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, 22 | 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, 23 | 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, 24 | 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, 25 | 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, 26 | 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, 27 | 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, 28 | 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, 29 | 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, 30 | 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, 31 | 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, 32 | 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, 33 | 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, 34 | 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, 35 | 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, 36 | 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, 37 | 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, 38 | 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, 39 | 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, 40 | 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, 41 | 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, 42 | 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, 43 | 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, 44 | 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, 45 | 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, 46 | 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, 47 | 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, 48 | 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, 49 | 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, 50 | 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, 51 | 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, 52 | 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, 53 | 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, 54 | 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, 55 | 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, 56 | 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, 57 | 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, 58 | 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, 59 | 0x2d02ef8dL 60 | }; 61 | 62 | #define crc32(crc,byte) (crc_32_tab[(u8)(crc) ^ (u8)(byte)] ^ ((crc) >> 8)) 63 | 64 | #endif 65 | 66 | -------------------------------------------------------------------------------- /cs/CLZF.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Oren J. Maurice 3 | * 4 | * Redistribution and use in source and binary forms, with or without modifica- 5 | * tion, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * 3. The name of the author may not be used to endorse or promote products 15 | * derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License version 2 (the "GPL"), in which case the 30 | * provisions of the GPL are applicable instead of the above. If you wish to 31 | * allow the use of your version of this file only under the terms of the 32 | * GPL and not to allow others to use your version of this file under the 33 | * BSD license, indicate your decision by deleting the provisions above and 34 | * replace them with the notice and other provisions required by the GPL. If 35 | * you do not delete the provisions above, a recipient may use your version 36 | * of this file under either the BSD or the GPL. 37 | */ 38 | 39 | using System; 40 | 41 | namespace LZF.NET 42 | { 43 | 44 | /// 45 | /// Summary description for CLZF. 46 | /// 47 | public class CLZF 48 | { 49 | // CRC32 data & function 50 | UInt32 []crc_32_tab = new UInt32[256] 51 | { 52 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 53 | 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 54 | 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 55 | 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 56 | 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 57 | 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 58 | 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 59 | 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 60 | 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 61 | 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 62 | 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 63 | 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 64 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 65 | 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 66 | 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 67 | 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 68 | 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 69 | 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 70 | 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 71 | 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 72 | 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 73 | 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 74 | 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 75 | 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 76 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 77 | 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 78 | 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 79 | 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 80 | 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 81 | 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 82 | 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 83 | 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 84 | 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 85 | 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 86 | 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 87 | 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 88 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 89 | 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 90 | 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 91 | 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 92 | 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 93 | 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 94 | 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 95 | 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 96 | 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 97 | 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 98 | 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 99 | 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 100 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 101 | 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 102 | 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 103 | 0x2d02ef8d 104 | }; 105 | 106 | public UInt32 crc32(UInt32 OldCRC,byte NewData) 107 | { 108 | return crc_32_tab[(OldCRC & 0xff) ^ NewData] ^ (OldCRC >> 8); 109 | } 110 | 111 | 112 | /// 113 | /// LZF Compressor 114 | /// 115 | 116 | UInt32 HLOG=14; 117 | UInt32 HSIZE=(1<<14); 118 | 119 | /* 120 | * don't play with this unless you benchmark! 121 | * decompression is not dependent on the hash function 122 | * the hashing function might seem strange, just believe me 123 | * it works ;) 124 | */ 125 | UInt32 MAX_LIT=(1 << 5); 126 | UInt32 MAX_OFF=(1 << 13); 127 | UInt32 MAX_REF=((1 << 8) + (1 << 3)); 128 | 129 | UInt32 FRST(byte[] Array,UInt32 ptr) 130 | { 131 | return (UInt32)(((Array[ptr]) << 8) | Array[ptr+1]); 132 | } 133 | 134 | UInt32 NEXT(UInt32 v,byte[] Array,UInt32 ptr) 135 | { 136 | return ((v) << 8) | Array[ptr+2]; 137 | } 138 | 139 | UInt32 IDX(UInt32 h) 140 | { 141 | return ((((h ^ (h << 5)) >> (int) (3*8 - HLOG)) - h*5) & (HSIZE - 1)); 142 | } 143 | 144 | /* 145 | * compressed format 146 | * 147 | * 000LLLLL ; literal 148 | * LLLOOOOO oooooooo ; backref L 149 | * 111OOOOO LLLLLLLL oooooooo ; backref L+7 150 | * 151 | */ 152 | 153 | public int lzf_compress (byte[] in_data, int in_len,byte[] out_data, int out_len) 154 | { 155 | int c; 156 | long []htab=new long[1<<14]; 157 | for (c=0;c<1<<14;c++) 158 | { 159 | htab[c]=0; 160 | } 161 | 162 | long hslot; 163 | UInt32 iidx = 0; 164 | UInt32 oidx = 0; 165 | //byte *in_end = ip + in_len; 166 | //byte *out_end = op + out_len; 167 | long reference; 168 | 169 | UInt32 hval = FRST (in_data,iidx); 170 | long off; 171 | int lit = 0; 172 | 173 | for (;;) 174 | { 175 | if (iidx < in_len - 2) 176 | { 177 | hval = NEXT (hval, in_data,iidx); 178 | hslot = IDX (hval); 179 | reference = htab[hslot]; 180 | htab[hslot] = (long)iidx; 181 | 182 | if ((off = iidx - reference - 1) < MAX_OFF 183 | && iidx + 4 < in_len 184 | && reference > 0 185 | && in_data[reference+0] == in_data[iidx+0] 186 | && in_data[reference+1] == in_data[iidx+1] 187 | && in_data[reference+2] == in_data[iidx+2] 188 | ) 189 | { 190 | /* match found at *reference++ */ 191 | UInt32 len = 2; 192 | UInt32 maxlen = (UInt32)in_len - iidx - len; 193 | maxlen = maxlen > MAX_REF ? MAX_REF : maxlen; 194 | 195 | if (oidx + lit + 1 + 3 >= out_len) 196 | return 0; 197 | 198 | do 199 | len++; 200 | while (len < maxlen && in_data[reference+len] == in_data[iidx+len]); 201 | 202 | if (lit!=0) 203 | { 204 | out_data[oidx++] = (byte)(lit - 1); 205 | lit = -lit; 206 | do 207 | out_data[oidx++] = in_data[iidx+lit]; 208 | while ((++lit)!=0); 209 | } 210 | 211 | len -= 2; 212 | iidx++; 213 | 214 | if (len < 7) 215 | { 216 | out_data[oidx++] = (byte)((off >> 8) + (len << 5)); 217 | } 218 | else 219 | { 220 | out_data[oidx++] = (byte)((off >> 8) + ( 7 << 5)); 221 | out_data[oidx++] = (byte)(len - 7); 222 | } 223 | 224 | out_data[oidx++] = (byte)off; 225 | 226 | iidx += len-1; 227 | hval = FRST (in_data,iidx); 228 | 229 | hval = NEXT (hval,in_data, iidx); 230 | htab[IDX (hval)] = iidx; 231 | iidx++; 232 | 233 | hval = NEXT (hval, in_data,iidx); 234 | htab[IDX (hval)] = iidx; 235 | iidx++; 236 | continue; 237 | } 238 | } 239 | else if (iidx == in_len) 240 | break; 241 | 242 | /* one more literal byte we must copy */ 243 | lit++; 244 | iidx++; 245 | 246 | if (lit == MAX_LIT) 247 | { 248 | if (oidx + 1 + MAX_LIT >= out_len) 249 | return 0; 250 | 251 | out_data[oidx++] = (byte)(MAX_LIT - 1); 252 | lit = -lit; 253 | do 254 | out_data[oidx++] = in_data[iidx+lit]; 255 | while ((++lit)!=0); 256 | } 257 | } 258 | 259 | if (lit!=0) 260 | { 261 | if (oidx + lit + 1 >= out_len) 262 | return 0; 263 | 264 | out_data[oidx++] = (byte)(lit - 1); 265 | lit = -lit; 266 | do 267 | out_data[oidx++] = in_data[iidx+lit]; 268 | while ((++lit)!=0); 269 | } 270 | 271 | return (int)oidx; 272 | } 273 | 274 | /// 275 | /// LZF Decompressor 276 | /// 277 | public int lzf_decompress ( byte[] in_data, int in_len, byte[] out_data, int out_len) 278 | { 279 | UInt32 iidx=0; 280 | UInt32 oidx=0; 281 | 282 | do 283 | { 284 | UInt32 ctrl = in_data[iidx++]; 285 | 286 | if (ctrl < (1 << 5)) /* literal run */ 287 | { 288 | ctrl++; 289 | 290 | if (oidx + ctrl > out_len) 291 | { 292 | //SET_ERRNO (E2BIG); 293 | return 0; 294 | } 295 | 296 | do 297 | out_data[oidx++] = in_data[iidx++]; 298 | while ((--ctrl)!=0); 299 | } 300 | else /* back reference */ 301 | { 302 | UInt32 len = ctrl >> 5; 303 | 304 | int reference = (int)(oidx - ((ctrl & 0x1f) << 8) - 1); 305 | 306 | if (len == 7) 307 | len += in_data[iidx++]; 308 | 309 | reference -= in_data[iidx++]; 310 | 311 | if (oidx + len + 2 > out_len) 312 | { 313 | //SET_ERRNO (E2BIG); 314 | return 0; 315 | } 316 | 317 | if (reference < 0) 318 | { 319 | //SET_ERRNO (EINVAL); 320 | return 0; 321 | } 322 | 323 | out_data[oidx++]=out_data[reference++]; 324 | out_data[oidx++]=out_data[reference++]; 325 | 326 | do 327 | out_data[oidx++]=out_data[reference++]; 328 | while ((--len)!=0); 329 | } 330 | } 331 | while (iidx < in_len); 332 | 333 | return (int)oidx; 334 | } 335 | 336 | public CLZF() 337 | { 338 | // 339 | // TODO: Add ructor logic here 340 | // 341 | } 342 | } 343 | } 344 | 345 | -------------------------------------------------------------------------------- /cs/README: -------------------------------------------------------------------------------- 1 | The C♯ implementation of the LZF en-/decoder functions in this 2 | directory was written (and is maintained) by 3 | 4 | Oren J. Maurice . 5 | 6 | If you have any questions or improvements, you should contact the 7 | original author (and maybe CC me, Marc Lehmann ). 8 | -------------------------------------------------------------------------------- /lzf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006 Stefan Traby 3 | * Copyright (c) 2012 Marc Lehmann 4 | * 5 | * Redistribution and use in source and binary forms, with or without modifica- 6 | * tion, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 16 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 17 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 19 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 23 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 24 | * OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * the GNU General Public License ("GPL") version 2 or any later version, 28 | * in which case the provisions of the GPL are applicable instead of 29 | * the above. If you wish to allow the use of your version of this file 30 | * only under the terms of the GPL and not to allow others to use your 31 | * version of this file under the BSD license, indicate your decision 32 | * by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL. If you do not delete the 34 | * provisions above, a recipient may use your version of this file under 35 | * either the BSD or the GPL. 36 | */ 37 | 38 | #include "config.h" 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include "lzf.h" 49 | #include "lzf_c_best.c" 50 | 51 | #ifdef HAVE_GETOPT_H 52 | # include 53 | #endif 54 | 55 | #define BLOCKSIZE (1024 * 64 - 1) 56 | #define MAX_BLOCKSIZE BLOCKSIZE 57 | 58 | typedef unsigned char u8; 59 | 60 | static off_t nr_read, nr_written; 61 | 62 | static const char *imagename; 63 | static enum { compress, uncompress, lzcat } mode = compress; 64 | static int verbose = 0; 65 | static int best = 0; 66 | static int force = 0; 67 | static long blocksize = BLOCKSIZE; 68 | 69 | #ifdef HAVE_GETOPT_LONG 70 | 71 | struct option longopts[] = { 72 | {"compress" , 0, 0, 'c'}, 73 | {"decompress", 0, 0, 'd'}, 74 | {"uncompress", 0, 0, 'd'}, 75 | {"best" , 0, 0, '9'}, 76 | {"force" , 0, 0, 'f'}, 77 | {"help" , 0, 0, 'h'}, 78 | {"verbose" , 0, 0, 'v'}, 79 | {"blocksize" , 1, 0, 'b'}, 80 | {0 , 0, 0, 0} 81 | }; 82 | 83 | static const char *opt = 84 | "-c --compress compress\n" 85 | "-d --decompress decompress\n" 86 | "-9 --best best compression\n" 87 | "-f --force force overwrite of output file\n" 88 | "-h --help give this help\n" 89 | "-v --verbose verbose mode\n" 90 | "-b # --blocksize # set blocksize\n" 91 | "\n"; 92 | 93 | #else 94 | 95 | static const char *opt = 96 | "-c compress\n" 97 | "-d decompress\n" 98 | "-9 best compression\n" 99 | "-f force overwrite of output file\n" 100 | "-h give this help\n" 101 | "-v verbose mode\n" 102 | "-b # set blocksize\n" 103 | "\n"; 104 | 105 | #endif 106 | 107 | static void 108 | usage (int rc) 109 | { 110 | fprintf (stderr, "\n" 111 | "lzf, a very lightweight compression/decompression utility written by Stefan Traby.\n" 112 | "uses liblzf written by Marc Lehmann You can find more info at\n" 113 | "http://liblzf.plan9.de/\n" 114 | "\n" 115 | "usage: lzf [-dufhvb9] [file ...]\n" 116 | " unlzf [file ...]\n" 117 | " lzcat [file ...]\n" 118 | "\n%s", 119 | opt); 120 | 121 | exit (rc); 122 | } 123 | 124 | static inline ssize_t 125 | rread (int fd, void *buf, size_t len) 126 | { 127 | ssize_t rc = 0, offset = 0; 128 | char *p = buf; 129 | 130 | while (len && (rc = read (fd, &p[offset], len)) > 0) 131 | { 132 | offset += rc; 133 | len -= rc; 134 | } 135 | 136 | nr_read += offset; 137 | 138 | if (rc < 0) 139 | return rc; 140 | 141 | return offset; 142 | } 143 | 144 | /* returns 0 if all written else -1 */ 145 | static inline ssize_t 146 | wwrite (int fd, void *buf, size_t len) 147 | { 148 | ssize_t rc; 149 | char *b = buf; 150 | size_t l = len; 151 | 152 | while (l) 153 | { 154 | rc = write (fd, b, l); 155 | if (rc < 0) 156 | { 157 | fprintf (stderr, "%s: write error: ", imagename); 158 | perror (""); 159 | return -1; 160 | } 161 | 162 | l -= rc; 163 | b += rc; 164 | } 165 | 166 | nr_written += len; 167 | return 0; 168 | } 169 | 170 | /* 171 | * Anatomy: an lzf file consists of any number of blocks in the following format: 172 | * 173 | * \x00 EOF (optional) 174 | * "ZV\0" 2-byte-usize 175 | * "ZV\1" 2-byte-csize 2-byte-usize 176 | * "ZV\2" 4-byte-crc32-0xdebb20e3 (NYI) 177 | */ 178 | 179 | 180 | #define TYPE0_HDR_SIZE 5 181 | #define TYPE1_HDR_SIZE 7 182 | #define MAX_HDR_SIZE 7 183 | #define MIN_HDR_SIZE 5 184 | 185 | static int 186 | compress_fd (int from, int to) 187 | { 188 | ssize_t us, cs, len; 189 | u8 buf1[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16]; 190 | u8 buf2[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16]; 191 | u8 *header; 192 | 193 | nr_read = nr_written = 0; 194 | while ((us = rread (from, &buf1[MAX_HDR_SIZE], blocksize)) > 0) 195 | { 196 | cs = (best ? lzf_compress_best : lzf_compress) (&buf1[MAX_HDR_SIZE], us, &buf2[MAX_HDR_SIZE], us > 4 ? us - 4 : us); 197 | if (cs) 198 | { 199 | header = &buf2[MAX_HDR_SIZE - TYPE1_HDR_SIZE]; 200 | header[0] = 'Z'; 201 | header[1] = 'V'; 202 | header[2] = 1; 203 | header[3] = cs >> 8; 204 | header[4] = cs & 0xff; 205 | header[5] = us >> 8; 206 | header[6] = us & 0xff; 207 | len = cs + TYPE1_HDR_SIZE; 208 | } 209 | else 210 | { // write uncompressed 211 | header = &buf1[MAX_HDR_SIZE - TYPE0_HDR_SIZE]; 212 | header[0] = 'Z'; 213 | header[1] = 'V'; 214 | header[2] = 0; 215 | header[3] = us >> 8; 216 | header[4] = us & 0xff; 217 | len = us + TYPE0_HDR_SIZE; 218 | } 219 | 220 | if (wwrite (to, header, len) == -1) 221 | return -1; 222 | } 223 | 224 | return 0; 225 | } 226 | 227 | static int 228 | uncompress_fd (int from, int to) 229 | { 230 | u8 header[MAX_HDR_SIZE]; 231 | u8 buf1[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16]; 232 | u8 buf2[MAX_BLOCKSIZE + MAX_HDR_SIZE + 16]; 233 | u8 *p; 234 | int l, rd; 235 | ssize_t rc, cs, us, bytes, over = 0; 236 | 237 | nr_read = nr_written = 0; 238 | while (1) 239 | { 240 | rc = rread (from, header + over, MAX_HDR_SIZE - over); 241 | if (rc < 0) 242 | { 243 | fprintf (stderr, "%s: read error: ", imagename); 244 | perror (""); 245 | return -1; 246 | } 247 | 248 | rc += over; 249 | over = 0; 250 | if (!rc || header[0] == 0) 251 | return 0; 252 | 253 | if (rc < MIN_HDR_SIZE || header[0] != 'Z' || header[1] != 'V') 254 | { 255 | fprintf (stderr, "%s: invalid data stream - magic not found or short header\n", imagename); 256 | return -1; 257 | } 258 | 259 | switch (header[2]) 260 | { 261 | case 0: 262 | cs = -1; 263 | us = (header[3] << 8) | header[4]; 264 | p = &header[TYPE0_HDR_SIZE]; 265 | break; 266 | case 1: 267 | if (rc < TYPE1_HDR_SIZE) 268 | { 269 | goto short_read; 270 | } 271 | cs = (header[3] << 8) | header[4]; 272 | us = (header[5] << 8) | header[6]; 273 | p = &header[TYPE1_HDR_SIZE]; 274 | break; 275 | default: 276 | fprintf (stderr, "%s: unknown blocktype\n", imagename); 277 | return -1; 278 | } 279 | 280 | bytes = cs == -1 ? us : cs; 281 | l = &header[rc] - p; 282 | 283 | if (l > 0) 284 | memcpy (buf1, p, l); 285 | 286 | if (l > bytes) 287 | { 288 | over = l - bytes; 289 | memmove (header, &p[bytes], over); 290 | } 291 | 292 | p = &buf1[l]; 293 | rd = bytes - l; 294 | if (rd > 0) 295 | if ((rc = rread (from, p, rd)) != rd) 296 | goto short_read; 297 | 298 | if (cs == -1) 299 | { 300 | if (wwrite (to, buf1, us)) 301 | return -1; 302 | } 303 | else 304 | { 305 | if (lzf_decompress (buf1, cs, buf2, us) != us) 306 | { 307 | fprintf (stderr, "%s: decompress: invalid stream - data corrupted\n", imagename); 308 | return -1; 309 | } 310 | 311 | if (wwrite (to, buf2, us)) 312 | return -1; 313 | } 314 | } 315 | 316 | return 0; 317 | 318 | short_read: 319 | fprintf (stderr, "%s: short data\n", imagename); 320 | return -1; 321 | } 322 | 323 | static int 324 | open_out (const char *name) 325 | { 326 | int fd; 327 | int m = O_EXCL; 328 | 329 | if (force) 330 | m = 0; 331 | 332 | fd = open (name, O_CREAT | O_WRONLY | O_TRUNC | m, 600); 333 | #if defined(__MINGW32__) 334 | _setmode(fd, _O_BINARY); 335 | #endif 336 | return fd; 337 | } 338 | 339 | static int 340 | compose_name (const char *fname, char *oname) 341 | { 342 | char *p; 343 | 344 | if (mode == compress) 345 | { 346 | if (strlen (fname) > PATH_MAX - 4) 347 | { 348 | fprintf (stderr, "%s: %s.lzf: name too long", imagename, fname); 349 | return -1; 350 | } 351 | 352 | strcpy (oname, fname); 353 | strcat (oname, ".lzf"); 354 | } 355 | else 356 | { 357 | if (strlen (fname) > PATH_MAX) 358 | { 359 | fprintf (stderr, "%s: %s: name too long\n", imagename, fname); 360 | return -1; 361 | } 362 | 363 | strcpy (oname, fname); 364 | p = &oname[strlen (oname)] - 4; 365 | if (p < oname || strcmp (p, ".lzf")) 366 | { 367 | fprintf (stderr, "%s: %s: unknown suffix\n", imagename, fname); 368 | return -1; 369 | } 370 | 371 | *p = 0; 372 | } 373 | 374 | return 0; 375 | } 376 | 377 | static int 378 | run_file (const char *fname) 379 | { 380 | int fd, fd2; 381 | int rc; 382 | struct stat mystat; 383 | char oname[PATH_MAX + 1]; 384 | 385 | if (mode != lzcat) 386 | if (compose_name (fname, oname)) 387 | return -1; 388 | 389 | #if !defined(__MINGW32__) 390 | rc = lstat (fname, &mystat); 391 | #else 392 | rc = stat (fname, &mystat); 393 | #endif 394 | fd = open (fname, O_RDONLY); 395 | #if defined(__MINGW32__) 396 | _setmode(fd, _O_BINARY); 397 | #endif 398 | if (rc || fd == -1) 399 | { 400 | fprintf (stderr, "%s: %s: ", imagename, fname); 401 | perror (""); 402 | return -1; 403 | } 404 | 405 | if (!S_ISREG (mystat.st_mode)) 406 | { 407 | fprintf (stderr, "%s: %s: not a regular file.\n", imagename, fname); 408 | close (fd); 409 | return -1; 410 | } 411 | 412 | if (mode == lzcat) 413 | { 414 | rc = uncompress_fd (fd, 1); 415 | close (fd); 416 | return rc; 417 | } 418 | 419 | fd2 = open_out (oname); 420 | if (fd2 == -1) 421 | { 422 | fprintf (stderr, "%s: %s: ", imagename, oname); 423 | perror (""); 424 | close (fd); 425 | return -1; 426 | } 427 | 428 | if (mode == compress) 429 | { 430 | rc = compress_fd (fd, fd2); 431 | if (!rc && verbose) 432 | fprintf (stderr, "%s: %5.1f%% -- replaced with %s\n", 433 | fname, nr_read == 0 ? 0 : 100.0 - nr_written / ((double) nr_read / 100.0), oname); 434 | } 435 | else 436 | { 437 | rc = uncompress_fd (fd, fd2); 438 | if (!rc && verbose) 439 | fprintf (stderr, "%s: %5.1f%% -- replaced with %s\n", 440 | fname, nr_written == 0 ? 0 : 100.0 - nr_read / ((double) nr_written / 100.0), oname); 441 | } 442 | 443 | #if !defined(__MINGW32__) 444 | fchmod (fd2, mystat.st_mode); 445 | #else 446 | chmod (oname, mystat.st_mode); 447 | #endif 448 | close (fd); 449 | close (fd2); 450 | 451 | if (!rc) 452 | unlink (fname); 453 | 454 | return rc; 455 | } 456 | 457 | int 458 | main (int argc, char *argv[]) 459 | { 460 | char *p = argv[0]; 461 | int optc; 462 | int rc = 0; 463 | 464 | errno = 0; 465 | p = getenv ("LZF_BLOCKSIZE"); 466 | if (p) 467 | { 468 | blocksize = strtoul (p, 0, 0); 469 | if (errno || !blocksize || blocksize > MAX_BLOCKSIZE) 470 | blocksize = BLOCKSIZE; 471 | } 472 | 473 | p = strrchr (argv[0], '/'); 474 | imagename = p ? ++p : argv[0]; 475 | 476 | if (!strncmp (imagename, "un", 2) || !strncmp (imagename, "de", 2)) 477 | mode = uncompress; 478 | 479 | if (strstr (imagename, "cat")) 480 | mode = lzcat; 481 | 482 | #ifdef HAVE_GETOPT_LONG 483 | while ((optc = getopt_long (argc, argv, "cd9fhvb:", longopts, 0)) != -1) 484 | #else 485 | while ((optc = getopt (argc, argv, "cd9fhvb:")) != -1) 486 | #endif 487 | { 488 | switch (optc) 489 | { 490 | case 'c': 491 | mode = compress; 492 | break; 493 | case 'd': 494 | mode = uncompress; 495 | break; 496 | case '9': 497 | best = 1; 498 | break; 499 | case 'f': 500 | force = 1; 501 | break; 502 | case 'h': 503 | usage (0); 504 | break; 505 | case 'v': 506 | verbose = 1; 507 | break; 508 | case 'b': 509 | errno = 0; 510 | blocksize = strtoul (optarg, 0, 0); 511 | if (errno || !blocksize || blocksize > MAX_BLOCKSIZE) 512 | blocksize = BLOCKSIZE; 513 | break; 514 | default: 515 | usage (1); 516 | break; 517 | } 518 | } 519 | 520 | if (optind == argc) 521 | { // stdin stdout 522 | if (!force) 523 | { 524 | if ((mode == uncompress || mode == lzcat) && isatty (0)) 525 | { 526 | fprintf (stderr, "%s: compressed data not read from a terminal. Use -f to force decompression.\n", imagename); 527 | exit (1); 528 | } 529 | if (mode == compress && isatty (1)) 530 | { 531 | fprintf (stderr, "%s: compressed data not written to a terminal. Use -f to force compression.\n", imagename); 532 | exit (1); 533 | } 534 | } 535 | 536 | if (mode == compress) 537 | rc = compress_fd (0, 1); 538 | else 539 | rc = uncompress_fd (0, 1); 540 | 541 | exit (rc ? 1 : 0); 542 | } 543 | 544 | while (optind < argc) 545 | rc |= run_file (argv[optind++]); 546 | 547 | exit (rc ? 1 : 0); 548 | } 549 | 550 | -------------------------------------------------------------------------------- /lzf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2008 Marc Alexander Lehmann 3 | * 4 | * Redistribution and use in source and binary forms, with or without modifica- 5 | * tion, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 16 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 17 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 18 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 22 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 23 | * OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * the GNU General Public License ("GPL") version 2 or any later version, 27 | * in which case the provisions of the GPL are applicable instead of 28 | * the above. If you wish to allow the use of your version of this file 29 | * only under the terms of the GPL and not to allow others to use your 30 | * version of this file under the BSD license, indicate your decision 31 | * by deleting the provisions above and replace them with the notice 32 | * and other provisions required by the GPL. If you do not delete the 33 | * provisions above, a recipient may use your version of this file under 34 | * either the BSD or the GPL. 35 | */ 36 | 37 | #ifndef LZF_H 38 | #define LZF_H 39 | 40 | /*********************************************************************** 41 | ** 42 | ** lzf -- an extremely fast/free compression/decompression-method 43 | ** http://liblzf.plan9.de/ 44 | ** 45 | ** This algorithm is believed to be patent-free. 46 | ** 47 | ***********************************************************************/ 48 | 49 | /* API version (major * 256 + minor) 50 | * major API version gets bumped on incompatible changes. 51 | * minor API version gets bumped on compatible changes. 52 | * 1.5 => 1.6: add LZF_MAX_COMPRESSED_SIZE 53 | */ 54 | #define LZF_VERSION 0x0106 55 | 56 | /* 57 | * Compress in_len bytes stored at the memory block starting at 58 | * in_data and write the result to out_data, up to a maximum length 59 | * of out_len bytes. 60 | * 61 | * If the output buffer is not large enough or any error occurs return 0, 62 | * otherwise return the number of bytes used, which might be considerably 63 | * more than in_len (but less than 1 + 104% of the original size), so it 64 | * makes sense to always use out_len == in_len - 1), to ensure _some_ 65 | * compression, and store the data uncompressed otherwise (with a flag, of 66 | * course. 67 | * 68 | * lzf_compress might use different algorithms on different systems and 69 | * even different runs, thus might result in different compressed strings 70 | * depending on the phase of the moon or similar factors. However, all 71 | * these strings are architecture-independent and will result in the 72 | * original data when decompressed using lzf_decompress. 73 | * 74 | * The buffers must not be overlapping. 75 | * 76 | * If the option LZF_STATE_ARG is enabled, an extra argument must be 77 | * supplied which is not reflected in this header file. Refer to lzfP.h 78 | * and lzf_c.c. 79 | * 80 | */ 81 | unsigned int 82 | lzf_compress (const void *const in_data, unsigned int in_len, 83 | void *out_data, unsigned int out_len); 84 | 85 | /* 86 | * The maximum out_len that needs to be allocated to make sure 87 | * any input data can be compressed without overflowing the output 88 | * buffer, i.e. maximum out_len = LZF_MAX_COMPRESSED_SIZE (in_len). 89 | * This is useful if you don't want to bother with the case of 90 | * incompressible data and just want to provide a buffer that is 91 | * guaranteeed to be big enough. 92 | * This macro can be used at preprocessing time. 93 | */ 94 | #define LZF_MAX_COMPRESSED_SIZE(n) ((((n) * 33) >> 5 ) + 1) 95 | 96 | /* 97 | * Decompress data compressed with some version of the lzf_compress 98 | * function and stored at location in_data and length in_len. The result 99 | * will be stored at out_data up to a maximum of out_len characters. 100 | * 101 | * If the output buffer is not large enough to hold the decompressed 102 | * data, a 0 is returned and errno is set to E2BIG. Otherwise the number 103 | * of decompressed bytes (i.e. the original length of the data) is 104 | * returned. 105 | * 106 | * If an error in the compressed data is detected, a zero is returned and 107 | * errno is set to EINVAL. 108 | * 109 | * This function is very fast, about as fast as a copying loop. 110 | */ 111 | unsigned int 112 | lzf_decompress (const void *const in_data, unsigned int in_len, 113 | void *out_data, unsigned int out_len); 114 | 115 | #endif 116 | 117 | -------------------------------------------------------------------------------- /lzfP.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2007 Marc Alexander Lehmann 3 | * 4 | * Redistribution and use in source and binary forms, with or without modifica- 5 | * tion, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 16 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 17 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 18 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 22 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 23 | * OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * the GNU General Public License ("GPL") version 2 or any later version, 27 | * in which case the provisions of the GPL are applicable instead of 28 | * the above. If you wish to allow the use of your version of this file 29 | * only under the terms of the GPL and not to allow others to use your 30 | * version of this file under the BSD license, indicate your decision 31 | * by deleting the provisions above and replace them with the notice 32 | * and other provisions required by the GPL. If you do not delete the 33 | * provisions above, a recipient may use your version of this file under 34 | * either the BSD or the GPL. 35 | */ 36 | 37 | #ifndef LZFP_h 38 | #define LZFP_h 39 | 40 | #define STANDALONE 1 /* at the moment, this is ok. */ 41 | 42 | #ifndef STANDALONE 43 | # include "lzf.h" 44 | #endif 45 | 46 | /* 47 | * Size of hashtable is (1 << HLOG) * sizeof (char *) 48 | * decompression is independent of the hash table size 49 | * the difference between 15 and 14 is very small 50 | * for small blocks (and 14 is usually a bit faster). 51 | * For a low-memory/faster configuration, use HLOG == 13; 52 | * For best compression, use 15 or 16 (or more, up to 22). 53 | */ 54 | #ifndef HLOG 55 | # define HLOG 16 56 | #endif 57 | 58 | /* 59 | * Sacrifice very little compression quality in favour of compression speed. 60 | * This gives almost the same compression as the default code, and is 61 | * (very roughly) 15% faster. This is the preferred mode of operation. 62 | */ 63 | #ifndef VERY_FAST 64 | # define VERY_FAST 1 65 | #endif 66 | 67 | /* 68 | * Sacrifice some more compression quality in favour of compression speed. 69 | * (roughly 1-2% worse compression for large blocks and 70 | * 9-10% for small, redundant, blocks and >>20% better speed in both cases) 71 | * In short: when in need for speed, enable this for binary data, 72 | * possibly disable this for text data. 73 | */ 74 | #ifndef ULTRA_FAST 75 | # define ULTRA_FAST 0 76 | #endif 77 | 78 | /* 79 | * Unconditionally aligning does not cost very much, so do it if unsure 80 | */ 81 | #ifndef STRICT_ALIGN 82 | # define STRICT_ALIGN !(defined(__i386) || defined (__amd64)) 83 | #endif 84 | 85 | /* 86 | * You may choose to pre-set the hash table (might be faster on some 87 | * modern cpus and large (>>64k) blocks, and also makes compression 88 | * deterministic/repeatable when the configuration otherwise is the same). 89 | */ 90 | #ifndef INIT_HTAB 91 | # define INIT_HTAB 1 92 | #endif 93 | 94 | /* 95 | * Avoid assigning values to errno variable? for some embedding purposes 96 | * (linux kernel for example), this is necessary. NOTE: this breaks 97 | * the documentation in lzf.h. Avoiding errno has no speed impact. 98 | */ 99 | #ifndef AVOID_ERRNO 100 | # define AVOID_ERRNO 0 101 | #endif 102 | 103 | /* 104 | * Whether to pass the LZF_STATE variable as argument, or allocate it 105 | * on the stack. For small-stack environments, define this to 1. 106 | * NOTE: this breaks the prototype in lzf.h. 107 | */ 108 | #ifndef LZF_STATE_ARG 109 | # define LZF_STATE_ARG 0 110 | #endif 111 | 112 | /* 113 | * Whether to add extra checks for input validity in lzf_decompress 114 | * and return EINVAL if the input stream has been corrupted. This 115 | * only shields against overflowing the input buffer and will not 116 | * detect most corrupted streams. 117 | * This check is not normally noticeable on modern hardware 118 | * (<1% slowdown), but might slow down older cpus considerably. 119 | */ 120 | #ifndef CHECK_INPUT 121 | # define CHECK_INPUT 1 122 | #endif 123 | 124 | /* 125 | * Whether the target CPU has a slow multiplication. This affects 126 | * the default hash function for the compressor, and enables a slightly 127 | * worse hash function that needs only shifts. 128 | */ 129 | #ifndef MULTIPLICATION_IS_SLOW 130 | # define MULTIPLICATION_IS_SLOW 0 131 | #endif 132 | 133 | /* 134 | * If defined, then this data type will be used for storing offsets. 135 | * This can be useful if you want to use a huge hashtable, want to 136 | * conserve memory, or both, and your data fits into e.g. 64kb. 137 | * If instead you want to compress data > 4GB, then it's better to 138 | * to "#define LZF_USE_OFFSETS 0" instead. 139 | */ 140 | /*#define LZF_HSLOT unsigned short*/ 141 | 142 | /* 143 | * Whether to store pointers or offsets inside the hash table. On 144 | * 64 bit architetcures, pointers take up twice as much space, 145 | * and might also be slower. Default is to autodetect. 146 | */ 147 | /*#define LZF_USE_OFFSETS autodetect */ 148 | 149 | /* 150 | * Whether to optimise code for size, at the expense of speed. Use 151 | * this when you are extremely tight on memory, perhaps in combination 152 | * with AVOID_ERRNO 1 and CHECK_INPUT 0. 153 | */ 154 | #ifndef OPTIMISE_SIZE 155 | # ifdef __OPTIMIZE_SIZE__ 156 | # define OPTIMISE_SIZE 1 157 | # else 158 | # define OPTIMISE_SIZE 0 159 | # endif 160 | #endif 161 | 162 | /*****************************************************************************/ 163 | /* nothing should be changed below */ 164 | 165 | #ifdef __cplusplus 166 | # include 167 | # include 168 | using namespace std; 169 | #else 170 | # include 171 | # include 172 | #endif 173 | 174 | #if ULTRA_FAST 175 | # undef VERY_FAST 176 | #endif 177 | 178 | #ifndef LZF_USE_OFFSETS 179 | # ifdef _WIN32 180 | # define LZF_USE_OFFSETS defined(_M_X64) 181 | # else 182 | # if __cplusplus > 199711L 183 | # include 184 | # else 185 | # include 186 | # endif 187 | # define LZF_USE_OFFSETS (UINTPTR_MAX > 0xffffffffU) 188 | # endif 189 | #endif 190 | 191 | typedef unsigned char u8; 192 | 193 | #ifdef LZF_HSLOT 194 | # define LZF_HSLOT_BIAS ((const u8 *)in_data) 195 | #else 196 | # if LZF_USE_OFFSETS 197 | # define LZF_HSLOT_BIAS ((const u8 *)in_data) 198 | typedef unsigned int LZF_HSLOT; 199 | # else 200 | # define LZF_HSLOT_BIAS 0 201 | typedef const u8 *LZF_HSLOT; 202 | # endif 203 | #endif 204 | 205 | #if USHRT_MAX == 65535 206 | typedef unsigned short u16; 207 | #elif UINT_MAX == 65535 208 | typedef unsigned int u16; 209 | #else 210 | # undef STRICT_ALIGN 211 | # define STRICT_ALIGN 1 212 | #endif 213 | 214 | #define LZF_MAX_LIT (1 << 5) 215 | #define LZF_MAX_OFF (1 << 13) 216 | #define LZF_MAX_REF ((1 << 8) + (1 << 3)) 217 | 218 | typedef LZF_HSLOT LZF_STATE[1 << (HLOG)]; 219 | 220 | typedef struct 221 | { 222 | const u8 *first [1 << (6+8)]; /* most recent occurance of a match */ 223 | u16 prev [LZF_MAX_OFF]; /* how many bytes to go backwards for the next match */ 224 | } LZF_STATE_BEST[1]; 225 | 226 | #endif 227 | 228 | -------------------------------------------------------------------------------- /lzf_c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2010,2012 Marc Alexander Lehmann 3 | * 4 | * Redistribution and use in source and binary forms, with or without modifica- 5 | * tion, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 16 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 17 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 18 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 22 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 23 | * OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * the GNU General Public License ("GPL") version 2 or any later version, 27 | * in which case the provisions of the GPL are applicable instead of 28 | * the above. If you wish to allow the use of your version of this file 29 | * only under the terms of the GPL and not to allow others to use your 30 | * version of this file under the BSD license, indicate your decision 31 | * by deleting the provisions above and replace them with the notice 32 | * and other provisions required by the GPL. If you do not delete the 33 | * provisions above, a recipient may use your version of this file under 34 | * either the BSD or the GPL. 35 | */ 36 | 37 | #include "lzfP.h" 38 | 39 | #define HSIZE (1 << (HLOG)) 40 | 41 | /* 42 | * don't play with this unless you benchmark! 43 | * the data format is not dependent on the hash function. 44 | * the hash function might seem strange, just believe me, 45 | * it works ;) 46 | */ 47 | #ifndef FRST 48 | # define FRST(p) (((p[0]) << 8) | p[1]) 49 | # define NEXT(v,p) (((v) << 8) | p[2]) 50 | # if MULTIPLICATION_IS_SLOW 51 | # if ULTRA_FAST 52 | # define IDX(h) ((( h >> (3*8 - HLOG)) - h ) & (HSIZE - 1)) 53 | # elif VERY_FAST 54 | # define IDX(h) ((( h >> (3*8 - HLOG)) - h*5) & (HSIZE - 1)) 55 | # else 56 | # define IDX(h) ((((h ^ (h << 5)) >> (3*8 - HLOG)) - h*5) & (HSIZE - 1)) 57 | # endif 58 | # else 59 | /* this one was developed with sesse, 60 | * and is very similar to the one in snappy. 61 | * it does need a modern enough cpu with a fast multiplication. 62 | */ 63 | # define IDX(h) (((h * 0x1e35a7bdU) >> (32 - HLOG - 8)) & (HSIZE - 1)) 64 | # endif 65 | #endif 66 | 67 | #if 0 68 | /* original lzv-like hash function, much worse and thus slower */ 69 | # define FRST(p) (p[0] << 5) ^ p[1] 70 | # define NEXT(v,p) ((v) << 5) ^ p[2] 71 | # define IDX(h) ((h) & (HSIZE - 1)) 72 | #endif 73 | 74 | #if __GNUC__ >= 3 75 | # define expect(expr,value) __builtin_expect ((expr),(value)) 76 | # define inline inline 77 | #else 78 | # define expect(expr,value) (expr) 79 | # define inline static 80 | #endif 81 | 82 | #define expect_false(expr) expect ((expr) != 0, 0) 83 | #define expect_true(expr) expect ((expr) != 0, 1) 84 | 85 | /* 86 | * compressed format 87 | * 88 | * 000LLLLL ; literal, L+1=1..33 octets 89 | * LLLooooo oooooooo ; backref L+1=1..7 octets, o+1=1..4096 offset 90 | * 111ooooo LLLLLLLL oooooooo ; backref L+8 octets, o+1=1..4096 offset 91 | * 92 | */ 93 | 94 | unsigned int 95 | lzf_compress (const void *const in_data, unsigned int in_len, 96 | void *out_data, unsigned int out_len 97 | #if LZF_STATE_ARG 98 | , LZF_STATE htab 99 | #endif 100 | ) 101 | { 102 | #if !LZF_STATE_ARG 103 | LZF_STATE htab; 104 | #endif 105 | const u8 *ip = (const u8 *)in_data; 106 | u8 *op = (u8 *)out_data; 107 | const u8 *in_end = ip + in_len; 108 | u8 *out_end = op + out_len; 109 | const u8 *ref; 110 | 111 | /* off requires a type wide enough to hold a general pointer difference. 112 | * ISO C doesn't have that (size_t might not be enough and ptrdiff_t only 113 | * works for differences within a single object). We also assume that 114 | * no bit pattern traps. Since the only platform that is both non-POSIX 115 | * and fails to support both assumptions is windows 64 bit, we make a 116 | * special workaround for it. 117 | */ 118 | #if defined (_WIN32) && defined (_M_X64) 119 | /* workaround for missing POSIX compliance */ 120 | #if __GNUC__ 121 | unsigned long long off; 122 | #else 123 | unsigned __int64 off; 124 | #endif 125 | #else 126 | unsigned long off; 127 | #endif 128 | unsigned int hval; 129 | int lit; 130 | 131 | if (!in_len || !out_len) 132 | return 0; 133 | 134 | #if INIT_HTAB 135 | memset (htab, 0, sizeof (htab)); 136 | #endif 137 | 138 | lit = 0; op++; /* start run */ 139 | 140 | hval = FRST (ip); 141 | while (ip < in_end - 2) 142 | { 143 | LZF_HSLOT *hslot; 144 | 145 | hval = NEXT (hval, ip); 146 | hslot = htab + IDX (hval); 147 | ref = *hslot + LZF_HSLOT_BIAS; *hslot = ip - LZF_HSLOT_BIAS; 148 | 149 | if (1 150 | #if INIT_HTAB 151 | && ref < ip /* the next test will actually take care of this, but this is faster */ 152 | #endif 153 | && (off = ip - ref - 1) < LZF_MAX_OFF 154 | && ref > (u8 *)in_data 155 | && ref[2] == ip[2] 156 | #if STRICT_ALIGN 157 | && ((ref[1] << 8) | ref[0]) == ((ip[1] << 8) | ip[0]) 158 | #else 159 | && *(u16 *)ref == *(u16 *)ip 160 | #endif 161 | ) 162 | { 163 | /* match found at *ref++ */ 164 | unsigned int len = 2; 165 | unsigned int maxlen = in_end - ip - len; 166 | maxlen = maxlen > LZF_MAX_REF ? LZF_MAX_REF : maxlen; 167 | 168 | if (expect_false (op + 3 + 1 >= out_end)) /* first a faster conservative test */ 169 | if (op - !lit + 3 + 1 >= out_end) /* second the exact but rare test */ 170 | return 0; 171 | 172 | op [- lit - 1] = lit - 1; /* stop run */ 173 | op -= !lit; /* undo run if length is zero */ 174 | 175 | for (;;) 176 | { 177 | if (expect_true (maxlen > 16)) 178 | { 179 | len++; if (ref [len] != ip [len]) break; 180 | len++; if (ref [len] != ip [len]) break; 181 | len++; if (ref [len] != ip [len]) break; 182 | len++; if (ref [len] != ip [len]) break; 183 | 184 | len++; if (ref [len] != ip [len]) break; 185 | len++; if (ref [len] != ip [len]) break; 186 | len++; if (ref [len] != ip [len]) break; 187 | len++; if (ref [len] != ip [len]) break; 188 | 189 | len++; if (ref [len] != ip [len]) break; 190 | len++; if (ref [len] != ip [len]) break; 191 | len++; if (ref [len] != ip [len]) break; 192 | len++; if (ref [len] != ip [len]) break; 193 | 194 | len++; if (ref [len] != ip [len]) break; 195 | len++; if (ref [len] != ip [len]) break; 196 | len++; if (ref [len] != ip [len]) break; 197 | len++; if (ref [len] != ip [len]) break; 198 | } 199 | 200 | do 201 | len++; 202 | while (len < maxlen && ref[len] == ip[len]); 203 | 204 | break; 205 | } 206 | 207 | len -= 2; /* len is now #octets - 1 */ 208 | ip++; 209 | 210 | if (len < 7) 211 | { 212 | *op++ = (off >> 8) + (len << 5); 213 | } 214 | else 215 | { 216 | *op++ = (off >> 8) + ( 7 << 5); 217 | *op++ = len - 7; 218 | } 219 | 220 | *op++ = off; 221 | 222 | lit = 0; op++; /* start run */ 223 | 224 | ip += len + 1; 225 | 226 | if (expect_false (ip >= in_end - 2)) 227 | break; 228 | 229 | #if ULTRA_FAST || VERY_FAST 230 | --ip; 231 | # if VERY_FAST && !ULTRA_FAST 232 | --ip; 233 | # endif 234 | hval = FRST (ip); 235 | 236 | hval = NEXT (hval, ip); 237 | htab[IDX (hval)] = ip - LZF_HSLOT_BIAS; 238 | ip++; 239 | 240 | # if VERY_FAST && !ULTRA_FAST 241 | hval = NEXT (hval, ip); 242 | htab[IDX (hval)] = ip - LZF_HSLOT_BIAS; 243 | ip++; 244 | # endif 245 | #else 246 | ip -= len + 1; 247 | 248 | do 249 | { 250 | hval = NEXT (hval, ip); 251 | htab[IDX (hval)] = ip - LZF_HSLOT_BIAS; 252 | ip++; 253 | } 254 | while (len--); 255 | #endif 256 | } 257 | else 258 | { 259 | /* one more literal byte we must copy */ 260 | if (expect_false (op >= out_end)) 261 | return 0; 262 | 263 | lit++; *op++ = *ip++; 264 | 265 | if (expect_false (lit == LZF_MAX_LIT)) 266 | { 267 | op [- lit - 1] = lit - 1; /* stop run */ 268 | lit = 0; op++; /* start run */ 269 | } 270 | } 271 | } 272 | 273 | if (op + 3 > out_end) /* at most 3 bytes can be missing here */ 274 | return 0; 275 | 276 | while (ip < in_end) 277 | { 278 | lit++; *op++ = *ip++; 279 | 280 | if (expect_false (lit == LZF_MAX_LIT)) 281 | { 282 | op [- lit - 1] = lit - 1; /* stop run */ 283 | lit = 0; op++; /* start run */ 284 | } 285 | } 286 | 287 | op [- lit - 1] = lit - 1; /* end run */ 288 | op -= !lit; /* undo run if length is zero */ 289 | 290 | return op - (u8 *)out_data; 291 | } 292 | 293 | -------------------------------------------------------------------------------- /lzf_c_best.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2012 Marc Alexander Lehmann 3 | * 4 | * Redistribution and use in source and binary forms, with or without modifica- 5 | * tion, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 16 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 17 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 18 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 22 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 23 | * OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * the GNU General Public License ("GPL") version 2 or any later version, 27 | * in which case the provisions of the GPL are applicable instead of 28 | * the above. If you wish to allow the use of your version of this file 29 | * only under the terms of the GPL and not to allow others to use your 30 | * version of this file under the BSD license, indicate your decision 31 | * by deleting the provisions above and replace them with the notice 32 | * and other provisions required by the GPL. If you do not delete the 33 | * provisions above, a recipient may use your version of this file under 34 | * either the BSD or the GPL. 35 | */ 36 | 37 | #include "lzfP.h" 38 | 39 | #define HASH(p) (p[0] << 6) ^ (p[1] << 3) ^ p[2] 40 | 41 | #if __GNUC__ >= 3 42 | # define expect(expr,value) __builtin_expect ((expr),(value)) 43 | # define inline inline 44 | #else 45 | # define expect(expr,value) (expr) 46 | # define inline static 47 | #endif 48 | 49 | #define expect_false(expr) expect ((expr) != 0, 0) 50 | #define expect_true(expr) expect ((expr) != 0, 1) 51 | 52 | /* 53 | * compressed format 54 | * 55 | * 000LLLLL ; literal, L+1=1..33 octets 56 | * LLLooooo oooooooo ; backref L+1=1..7 octets, o+1=1..4096 offset 57 | * 111ooooo LLLLLLLL oooooooo ; backref L+8 octets, o+1=1..4096 offset 58 | * 59 | */ 60 | 61 | unsigned int 62 | lzf_compress_best (const void *const in_data, unsigned int in_len, 63 | void *out_data, unsigned int out_len 64 | #if LZF_STATE_ARG 65 | , LZF_STATE_BEST state 66 | #endif 67 | ) 68 | { 69 | const u8 *ip = (const u8 *)in_data; 70 | u8 *op = (u8 *)out_data; 71 | const u8 *in_end = ip + in_len; 72 | u8 *out_end = op + out_len; 73 | 74 | #if !LZF_STATE_ARG 75 | LZF_STATE_BEST state; 76 | #endif 77 | #define STATE state[0] 78 | 79 | int lit; 80 | 81 | if (!in_len || !out_len) 82 | return 0; 83 | 84 | lit = 0; op++; /* start run */ 85 | 86 | lit++; *op++ = *ip++; 87 | 88 | while (ip < in_end - 2) 89 | { 90 | int best_l = 0; 91 | const u8 *best_p; 92 | int e = (in_end - ip < LZF_MAX_REF ? in_end - ip : LZF_MAX_REF) - 1; 93 | unsigned int res = ((unsigned long)ip) & (LZF_MAX_OFF - 1); 94 | u16 hash = HASH (ip); 95 | u16 diff; 96 | const u8 *b = ip < (u8 *)in_data + LZF_MAX_OFF ? in_data : ip - LZF_MAX_OFF; 97 | const u8 *p = STATE.first [hash]; 98 | STATE.prev [res] = ip - p; /* update ptr to previous hash match */ 99 | STATE.first [hash] = ip; /* first hash match is here */ 100 | 101 | if (p < ip) 102 | while (p >= b) 103 | { 104 | if (p[2] == ip[2]) /* first two bytes almost always match */ 105 | if (p[best_l] == ip[best_l]) /* new match must be longer than the old one to qualify */ 106 | if (p[1] == ip[1] && p[0] == ip[0]) /* just to be sure */ 107 | { 108 | int l = 3; 109 | 110 | while (p[l] == ip[l] && l < e) 111 | ++l; 112 | 113 | if (l >= best_l) 114 | { 115 | best_p = p; 116 | best_l = l; 117 | } 118 | } 119 | 120 | diff = STATE.prev [((unsigned long)p) & (LZF_MAX_OFF - 1)]; 121 | p = diff ? p - diff : 0; 122 | } 123 | 124 | if (best_l) 125 | { 126 | int len = best_l; 127 | int off = ip - best_p - 1; 128 | 129 | if (expect_false (op + 3 + 1 >= out_end)) /* first a faster conservative test */ 130 | if (op - !lit + 3 + 1 >= out_end) /* second the exact but rare test */ 131 | return 0; 132 | 133 | op [- lit - 1] = lit - 1; /* stop run */ 134 | op -= !lit; /* undo run if length is zero */ 135 | 136 | len -= 2; /* len is now #octets - 1 */ 137 | ip++; 138 | 139 | if (len < 7) 140 | { 141 | *op++ = (off >> 8) + (len << 5); 142 | } 143 | else 144 | { 145 | *op++ = (off >> 8) + ( 7 << 5); 146 | *op++ = len - 7; 147 | } 148 | 149 | *op++ = off; 150 | 151 | lit = 0; op++; /* start run */ 152 | 153 | ip += len + 1; 154 | 155 | if (expect_false (ip >= in_end - 2)) 156 | break; 157 | 158 | ip -= len + 1; 159 | 160 | //printf (" fill %p for %d\n", ip, len);//D 161 | do 162 | { 163 | u16 hash = HASH (ip); 164 | res = ((unsigned long)ip) & (LZF_MAX_OFF - 1); 165 | 166 | p = STATE.first [hash]; 167 | STATE.prev [res] = ip - p; /* update ptr to previous hash match */ 168 | STATE.first [hash] = ip; /* first hash match is here */ 169 | 170 | ip++; 171 | } 172 | while (len--); 173 | } 174 | else 175 | { 176 | /* one more literal byte we must copy */ 177 | if (expect_false (op >= out_end)) 178 | return 0; 179 | 180 | lit++; *op++ = *ip++; 181 | 182 | if (expect_false (lit == LZF_MAX_LIT)) 183 | { 184 | op [- lit - 1] = lit - 1; /* stop run */ 185 | lit = 0; op++; /* start run */ 186 | } 187 | } 188 | } 189 | 190 | if (op + 3 > out_end) /* at most 3 bytes can be missing here */ 191 | return 0; 192 | 193 | while (ip < in_end) 194 | { 195 | lit++; *op++ = *ip++; 196 | 197 | if (expect_false (lit == LZF_MAX_LIT)) 198 | { 199 | op [- lit - 1] = lit - 1; /* stop run */ 200 | lit = 0; op++; /* start run */ 201 | } 202 | } 203 | 204 | op [- lit - 1] = lit - 1; /* end run */ 205 | op -= !lit; /* undo run if length is zero */ 206 | 207 | return op - (u8 *)out_data; 208 | 209 | #undef STATE 210 | } 211 | 212 | 213 | -------------------------------------------------------------------------------- /lzf_d.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2010 Marc Alexander Lehmann 3 | * 4 | * Redistribution and use in source and binary forms, with or without modifica- 5 | * tion, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 16 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 17 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 18 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 22 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 23 | * OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * the GNU General Public License ("GPL") version 2 or any later version, 27 | * in which case the provisions of the GPL are applicable instead of 28 | * the above. If you wish to allow the use of your version of this file 29 | * only under the terms of the GPL and not to allow others to use your 30 | * version of this file under the BSD license, indicate your decision 31 | * by deleting the provisions above and replace them with the notice 32 | * and other provisions required by the GPL. If you do not delete the 33 | * provisions above, a recipient may use your version of this file under 34 | * either the BSD or the GPL. 35 | */ 36 | 37 | #include "lzfP.h" 38 | 39 | #if AVOID_ERRNO 40 | # define SET_ERRNO(n) 41 | #else 42 | # include 43 | # define SET_ERRNO(n) errno = (n) 44 | #endif 45 | 46 | #if USE_REP_MOVSB /* small win on amd, big loss on intel */ 47 | #if (__i386 || __amd64) && __GNUC__ >= 3 48 | # define lzf_movsb(dst, src, len) \ 49 | asm ("rep movsb" \ 50 | : "=D" (dst), "=S" (src), "=c" (len) \ 51 | : "0" (dst), "1" (src), "2" (len)); 52 | #endif 53 | #endif 54 | 55 | unsigned int 56 | lzf_decompress (const void *const in_data, unsigned int in_len, 57 | void *out_data, unsigned int out_len) 58 | { 59 | u8 const *ip = (const u8 *)in_data; 60 | u8 *op = (u8 *)out_data; 61 | u8 const *const in_end = ip + in_len; 62 | u8 *const out_end = op + out_len; 63 | 64 | do 65 | { 66 | unsigned int ctrl = *ip++; 67 | 68 | if (ctrl < (1 << 5)) /* literal run */ 69 | { 70 | ctrl++; 71 | 72 | if (op + ctrl > out_end) 73 | { 74 | SET_ERRNO (E2BIG); 75 | return 0; 76 | } 77 | 78 | #if CHECK_INPUT 79 | if (ip + ctrl > in_end) 80 | { 81 | SET_ERRNO (EINVAL); 82 | return 0; 83 | } 84 | #endif 85 | 86 | #ifdef lzf_movsb 87 | lzf_movsb (op, ip, ctrl); 88 | #elif OPTIMISE_SIZE 89 | while (ctrl--) 90 | *op++ = *ip++; 91 | #else 92 | switch (ctrl) 93 | { 94 | case 32: *op++ = *ip++; case 31: *op++ = *ip++; case 30: *op++ = *ip++; case 29: *op++ = *ip++; 95 | case 28: *op++ = *ip++; case 27: *op++ = *ip++; case 26: *op++ = *ip++; case 25: *op++ = *ip++; 96 | case 24: *op++ = *ip++; case 23: *op++ = *ip++; case 22: *op++ = *ip++; case 21: *op++ = *ip++; 97 | case 20: *op++ = *ip++; case 19: *op++ = *ip++; case 18: *op++ = *ip++; case 17: *op++ = *ip++; 98 | case 16: *op++ = *ip++; case 15: *op++ = *ip++; case 14: *op++ = *ip++; case 13: *op++ = *ip++; 99 | case 12: *op++ = *ip++; case 11: *op++ = *ip++; case 10: *op++ = *ip++; case 9: *op++ = *ip++; 100 | case 8: *op++ = *ip++; case 7: *op++ = *ip++; case 6: *op++ = *ip++; case 5: *op++ = *ip++; 101 | case 4: *op++ = *ip++; case 3: *op++ = *ip++; case 2: *op++ = *ip++; case 1: *op++ = *ip++; 102 | } 103 | #endif 104 | } 105 | else /* back reference */ 106 | { 107 | unsigned int len = ctrl >> 5; 108 | 109 | u8 *ref = op - ((ctrl & 0x1f) << 8) - 1; 110 | 111 | #if CHECK_INPUT 112 | if (ip >= in_end) 113 | { 114 | SET_ERRNO (EINVAL); 115 | return 0; 116 | } 117 | #endif 118 | if (len == 7) 119 | { 120 | len += *ip++; 121 | #if CHECK_INPUT 122 | if (ip >= in_end) 123 | { 124 | SET_ERRNO (EINVAL); 125 | return 0; 126 | } 127 | #endif 128 | } 129 | 130 | ref -= *ip++; 131 | 132 | if (op + len + 2 > out_end) 133 | { 134 | SET_ERRNO (E2BIG); 135 | return 0; 136 | } 137 | 138 | if (ref < (u8 *)out_data) 139 | { 140 | SET_ERRNO (EINVAL); 141 | return 0; 142 | } 143 | 144 | #ifdef lzf_movsb 145 | len += 2; 146 | lzf_movsb (op, ref, len); 147 | #elif OPTIMISE_SIZE 148 | len += 2; 149 | 150 | do 151 | *op++ = *ref++; 152 | while (--len); 153 | #else 154 | switch (len) 155 | { 156 | default: 157 | len += 2; 158 | 159 | if (op >= ref + len) 160 | { 161 | /* disjunct areas */ 162 | memcpy (op, ref, len); 163 | op += len; 164 | } 165 | else 166 | { 167 | /* overlapping, use octet by octet copying */ 168 | do 169 | *op++ = *ref++; 170 | while (--len); 171 | } 172 | 173 | break; 174 | 175 | case 9: *op++ = *ref++; 176 | case 8: *op++ = *ref++; 177 | case 7: *op++ = *ref++; 178 | case 6: *op++ = *ref++; 179 | case 5: *op++ = *ref++; 180 | case 4: *op++ = *ref++; 181 | case 3: *op++ = *ref++; 182 | case 2: *op++ = *ref++; 183 | case 1: *op++ = *ref++; 184 | case 0: *op++ = *ref++; /* two octets more */ 185 | *op++ = *ref++; 186 | } 187 | #endif 188 | } 189 | } 190 | while (ip < in_end); 191 | 192 | return op - (u8 *)out_data; 193 | } 194 | 195 | --------------------------------------------------------------------------------