From f00a81927431565d76ecd763567191b2afbb99b5 Mon Sep 17 00:00:00 2001 From: Amar Takhar Date: Mon, 14 Jul 2025 16:44:47 -0400 Subject: [PATCH] contrib: Import FastLZ 0.1.0 URL https://github.com/ariya/FastLZ/ Hash f1217348a868bdb9ee0730244475aee05ab329c5 --- contrib/cpukit/fastlz/6pack.c | 636 +++++++++++++++++++++++++++++++ contrib/cpukit/fastlz/6unpack.c | 478 +++++++++++++++++++++++ contrib/cpukit/fastlz/LICENSE | 24 ++ contrib/cpukit/fastlz/README.TXT | 75 ++++ contrib/cpukit/fastlz/fastlz.c | 551 ++++++++++++++++++++++++++ contrib/cpukit/fastlz/fastlz.h | 100 +++++ 6 files changed, 1864 insertions(+) create mode 100644 contrib/cpukit/fastlz/6pack.c create mode 100644 contrib/cpukit/fastlz/6unpack.c create mode 100644 contrib/cpukit/fastlz/LICENSE create mode 100644 contrib/cpukit/fastlz/README.TXT create mode 100644 contrib/cpukit/fastlz/fastlz.c create mode 100644 contrib/cpukit/fastlz/fastlz.h diff --git a/contrib/cpukit/fastlz/6pack.c b/contrib/cpukit/fastlz/6pack.c new file mode 100644 index 0000000000..89a1128db5 --- /dev/null +++ b/contrib/cpukit/fastlz/6pack.c @@ -0,0 +1,636 @@ +/* + 6PACK - file compressor using FastLZ (lightning-fast compression library) + + Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#include +#include +#include + +#define SIXPACK_VERSION_MAJOR 0 +#define SIXPACK_VERSION_MINOR 1 +#define SIXPACK_VERSION_REVISION 0 +#define SIXPACK_VERSION_STRING "snapshot 20070615" + +#include "fastlz.h" + +#undef PATH_SEPARATOR + +#if defined(MSDOS) || defined(__MSDOS__) || defined(MSDOS) +#define PATH_SEPARATOR '\\' +#endif + +#if defined(WIN32) || defined(__NT__) || defined(_WIN32) || defined(__WIN32__) +#define PATH_SEPARATOR '\\' +#if defined(__BORLANDC__) || defined(_MSC_VER) +#define inline __inline +#endif +#endif + +#ifndef PATH_SEPARATOR +#define PATH_SEPARATOR '/' +#endif + +#undef SIXPACK_BENCHMARK_WIN32 +#if defined(WIN32) || defined(__NT__) || defined(_WIN32) || defined(__WIN32__) +#if defined(_MSC_VER) || defined(__GNUC__) +#define SIXPACK_BENCHMARK_WIN32 +#include +#endif +#endif + +/* magic identifier for 6pack file */ +static unsigned char sixpack_magic[8] = {137, '6', 'P', 'K', 13, 10, 26, 10}; + +#define BLOCK_SIZE (2*64*1024) + +/* prototypes */ +static inline unsigned long update_adler32(unsigned long checksum, const void *buf, int len); +void usage(void); +int detect_magic(FILE *f); +void write_magic(FILE *f); +void write_chunk_header(FILE* f, int id, int options, unsigned long size, +unsigned long checksum, unsigned long extra); +unsigned long block_compress(const unsigned char* input, unsigned long length, unsigned char* output); +int pack_file_compressed(const char* input_file, int method, int level, FILE* f); +int pack_file(int compress_level, const char* input_file, const char* output_file); + +/* for Adler-32 checksum algorithm, see RFC 1950 Section 8.2 */ +#define ADLER32_BASE 65521 +static inline unsigned long update_adler32(unsigned long checksum, const void *buf, int len) +{ + const unsigned char* ptr = (const unsigned char*)buf; + unsigned long s1 = checksum & 0xffff; + unsigned long s2 = (checksum >> 16) & 0xffff; + + while(len>0) + { + unsigned k = len < 5552 ? len : 5552; + len -= k; + + while(k >= 8) + { + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + k -= 8; + } + + while(k-- > 0) + { + s1 += *ptr++; s2 += s1; + } + s1 = s1 % ADLER32_BASE; + s2 = s2 % ADLER32_BASE; + } + return (s2 << 16) + s1; +} + +void usage(void) +{ + printf("6pack: high-speed file compression tool\n"); + printf("Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)\n"); + printf("\n"); + printf("Usage: 6pack [options] input-file output-file\n"); + printf("\n"); + printf("Options:\n"); + printf(" -1 compress faster\n"); + printf(" -2 compress better\n"); + printf(" -v show program version\n"); +#ifdef SIXPACK_BENCHMARK_WIN32 + printf(" -mem check in-memory compression speed\n"); +#endif + printf("\n"); +} + +/* return non-zero if magic sequence is detected */ +/* warning: reset the read pointer to the beginning of the file */ +int detect_magic(FILE *f) +{ + unsigned char buffer[8]; + size_t bytes_read; + int c; + + fseek(f, SEEK_SET, 0); + bytes_read = fread(buffer, 1, 8, f); + fseek(f, SEEK_SET, 0); + if(bytes_read < 8) + return 0; + + for(c = 0; c < 8; c++) + if(buffer[c] != sixpack_magic[c]) + return 0; + + return -1; +} + +void write_magic(FILE *f) +{ + fwrite(sixpack_magic, 8, 1, f); +} + +void write_chunk_header(FILE* f, int id, int options, unsigned long size, + unsigned long checksum, unsigned long extra) +{ + unsigned char buffer[16]; + + buffer[0] = id & 255; + buffer[1] = id >> 8; + buffer[2] = options & 255; + buffer[3] = options >> 8; + buffer[4] = size & 255; + buffer[5] = (size >> 8) & 255; + buffer[6] = (size >> 16) & 255; + buffer[7] = (size >> 24) & 255; + buffer[8] = checksum & 255; + buffer[9] = (checksum >> 8) & 255; + buffer[10] = (checksum >> 16) & 255; + buffer[11] = (checksum >> 24) & 255; + buffer[12] = extra & 255; + buffer[13] = (extra >> 8) & 255; + buffer[14] = (extra >> 16) & 255; + buffer[15] = (extra >> 24) & 255; + + fwrite(buffer, 16, 1, f); +} + +int pack_file_compressed(const char* input_file, int method, int level, FILE* f) +{ + FILE* in; + unsigned long fsize; + unsigned long checksum; + const char* shown_name; + unsigned char buffer[BLOCK_SIZE]; + unsigned char result[BLOCK_SIZE*2]; /* FIXME twice is too large */ + unsigned char progress[20]; + int c; + unsigned long percent; + unsigned long total_read; + unsigned long total_compressed; + int chunk_size; + + /* sanity check */ + in = fopen(input_file, "rb"); + if(!in) + { + printf("Error: could not open %s\n", input_file); + return -1; + } + + /* find size of the file */ + fseek(in, 0, SEEK_END); + fsize = ftell(in); + fseek(in, 0, SEEK_SET); + + /* already a 6pack archive? */ + if(detect_magic(in)) + { + printf("Error: file %s is already a 6pack archive!\n", input_file); + fclose(in); + return -1; + } + + /* truncate directory prefix, e.g. "foo/bar/FILE.txt" becomes "FILE.txt" */ + shown_name = input_file + strlen(input_file) - 1; + while(shown_name > input_file) + if(*(shown_name-1) == PATH_SEPARATOR) + break; + else + shown_name--; + + /* chunk for File Entry */ + buffer[0] = fsize & 255; + buffer[1] = (fsize >> 8) & 255; + buffer[2] = (fsize >> 16) & 255; + buffer[3] = (fsize >> 24) & 255; +#if 0 + buffer[4] = (fsize >> 32) & 255; + buffer[5] = (fsize >> 40) & 255; + buffer[6] = (fsize >> 48) & 255; + buffer[7] = (fsize >> 56) & 255; +#else + /* because fsize is only 32-bit */ + buffer[4] = 0; + buffer[5] = 0; + buffer[6] = 0; + buffer[7] = 0; +#endif + buffer[8] = (strlen(shown_name)+1) & 255; + buffer[9] = (strlen(shown_name)+1) >> 8; + checksum = 1L; + checksum = update_adler32(checksum, buffer, 10); + checksum = update_adler32(checksum, shown_name, strlen(shown_name)+1); + write_chunk_header(f, 1, 0, 10+strlen(shown_name)+1, checksum, 0); + fwrite(buffer, 10, 1, f); + fwrite(shown_name, strlen(shown_name)+1, 1, f); + total_compressed = 16 + 10 + strlen(shown_name)+1; + + /* for progress status */ + memset(progress, ' ', 20); + if(strlen(shown_name) < 16) + for(c = 0; c < (int)strlen(shown_name); c++) + progress[c] = shown_name[c]; + else + { + for(c = 0; c < 13; c++) + progress[c] = shown_name[c]; + progress[13] = '.'; + progress[14] = '.'; + progress[15] = ' '; + } + progress[16] = '['; + progress[17] = 0; + printf("%s", progress); + for(c = 0; c < 50; c++) + printf("."); + printf("]\r"); + printf("%s", progress); + + /* read file and place in archive */ + total_read = 0; + percent = 0; + for(;;) + { + int compress_method = method; + int last_percent = (int)percent; + size_t bytes_read = fread(buffer, 1, BLOCK_SIZE, in); + if(bytes_read == 0) + break; + total_read += bytes_read; + + /* for progress */ + if(fsize < (1<<24)) + percent = total_read * 100 / fsize; + else + percent = total_read/256 * 100 / (fsize >>8); + percent >>= 1; + while(last_percent < (int)percent) + { + printf("#"); + last_percent++; + } + + /* too small, don't bother to compress */ + if(bytes_read < 32) + compress_method = 0; + + /* write to output */ + switch(compress_method) + { + /* FastLZ */ + case 1: + chunk_size = fastlz_compress_level(level, buffer, bytes_read, result); + checksum = update_adler32(1L, result, chunk_size); + write_chunk_header(f, 17, 1, chunk_size, checksum, bytes_read); + fwrite(result, 1, chunk_size, f); + total_compressed += 16; + total_compressed += chunk_size; + break; + + /* uncompressed, also fallback method */ + case 0: + default: + checksum = 1L; + checksum = update_adler32(checksum, buffer, bytes_read); + write_chunk_header(f, 17, 0, bytes_read, checksum, bytes_read); + fwrite(buffer, 1, bytes_read, f); + total_compressed += 16; + total_compressed += bytes_read; + break; + } + } + + fclose(in); + if(total_read != fsize) + { + printf("\n"); + printf("Error: reading %s failed!\n", input_file); + return -1; + } + else + { + printf("] "); + if(total_compressed < fsize) + { + if(fsize < (1<<20)) + percent = total_compressed * 1000 / fsize; + else + percent = total_compressed/256 * 1000 / (fsize >>8); + percent = 1000 - percent; + printf("%2d.%d%% saved", (int)percent/10, (int)percent%10); + } + printf("\n"); + } + + return 0; +} + +int pack_file(int compress_level, const char* input_file, const char* output_file) +{ + FILE* f; + int result; + + f = fopen(output_file, "rb"); + if(f) + { + fclose(f); + printf("Error: file %s already exists. Aborted.\n\n", output_file); + return -1; + } + + f = fopen(output_file, "wb"); + if(!f) + { + printf("Error: could not create %s. Aborted.\n\n", output_file); + return -1; + } + + write_magic(f); + + result = pack_file_compressed(input_file, 1, compress_level, f); + fclose(f); + + return result; +} + +#ifdef SIXPACK_BENCHMARK_WIN32 +int benchmark_speed(int compress_level, const char* input_file); + +int benchmark_speed(int compress_level, const char* input_file) +{ + FILE* in; + unsigned long fsize; + unsigned long maxout; + const char* shown_name; + unsigned char* buffer; + unsigned char* result; + size_t bytes_read; + + /* sanity check */ + in = fopen(input_file, "rb"); + if(!in) + { + printf("Error: could not open %s\n", input_file); + return -1; + } + + /* find size of the file */ + fseek(in, 0, SEEK_END); + fsize = ftell(in); + fseek(in, 0, SEEK_SET); + + /* already a 6pack archive? */ + if(detect_magic(in)) + { + printf("Error: no benchmark for 6pack archive!\n"); + fclose(in); + return -1; + } + + /* truncate directory prefix, e.g. "foo/bar/FILE.txt" becomes "FILE.txt" */ + shown_name = input_file + strlen(input_file) - 1; + while(shown_name > input_file) + if(*(shown_name-1) == PATH_SEPARATOR) + break; + else + shown_name--; + + maxout = 1.05 * fsize; + maxout = (maxout < 66) ? 66 : maxout; + buffer = (unsigned char*)malloc(fsize); + result = (unsigned char*)malloc(maxout); + if(!buffer || !result) + { + printf("Error: not enough memory!\n"); + free(buffer); + free(result); + fclose(in); + return -1; + } + + printf("Reading source file....\n"); + bytes_read = fread(buffer, 1, fsize, in); + if(bytes_read != fsize) + { + printf("Error reading file %s!\n", shown_name); + printf("Read %d bytes, expecting %d bytes\n", bytes_read, fsize); + free(buffer); + free(result); + fclose(in); + return -1; + } + +/* shamelessly copied from QuickLZ 1.20 test program */ + { + unsigned int j, y; + size_t i, u = 0; + double mbs, fastest; + unsigned long compressed_size; + + printf("Setting HIGH_PRIORITY_CLASS...\n"); + SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); + + printf("Benchmarking FastLZ Level %d, please wait...\n", compress_level); + + i = bytes_read; + fastest = 0.0; + for (j = 0; j < 3; j++) + { + y = 0; + mbs = GetTickCount(); + while(GetTickCount() == mbs); + mbs = GetTickCount(); + while(GetTickCount() - mbs < 3000) /* 1% accuracy with 18.2 timer */ + { + u = fastlz_compress_level(compress_level, buffer, bytes_read, result); + y++; + } + + mbs = ((double)i*(double)y)/((double)(GetTickCount() - mbs)/1000.)/1000000.; + /*printf(" %.1f Mbyte/s ", mbs);*/ + if (fastest < mbs) + fastest = mbs; + } + + printf("\nCompressed %d bytes into %d bytes (%.1f%%) at %.1f Mbyte/s.\n", (unsigned int)i, (unsigned int)u, (double)u/(double)i*100., fastest); + +#if 1 + fastest = 0.0; + compressed_size = u; + for (j = 0; j < 3; j++) + { + y = 0; + mbs = GetTickCount(); + while(GetTickCount() == mbs); + mbs = GetTickCount(); + while(GetTickCount() - mbs < 3000) /* 1% accuracy with 18.2 timer */ + { + u = fastlz_decompress(result, compressed_size, buffer, bytes_read); + y++; + } + + mbs = ((double)i*(double)y)/((double)(GetTickCount() - mbs)/1000.)/1000000.; + /*printf(" %.1f Mbyte/s ", mbs);*/ + if (fastest < mbs) + fastest = mbs; + } + + printf("\nDecompressed at %.1f Mbyte/s.\n\n(1 MB = 1000000 byte)\n", fastest); +#endif + } + + fclose(in); + return 0; +} +#endif /* SIXPACK_BENCHMARK_WIN32 */ + + +int main(int argc, char** argv) +{ + int i; + int compress_level; + int benchmark; + char* input_file; + char* output_file; + + /* show help with no argument at all*/ + if(argc == 1) + { + usage(); + return 0; + } + + /* default compression level, not the fastest */ + compress_level = 2; + + /* do benchmark only when explicitly specified */ + benchmark = 0; + + /* no file is specified */ + input_file = 0; + output_file = 0; + + for(i = 1; i <= argc; i++) + { + char* argument = argv[i]; + + if(!argument) + continue; + + /* display help on usage */ + if(!strcmp(argument, "-h") || !strcmp(argument, "--help")) + { + usage(); + return 0; + } + + /* check for version information */ + if(!strcmp(argument, "-v") || !strcmp(argument, "--version")) + { + printf("6pack: high-speed file compression tool\n"); + printf("Version %s (using FastLZ %s)\n", + SIXPACK_VERSION_STRING, FASTLZ_VERSION_STRING); + printf("Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)\n"); + printf("\n"); + return 0; + } + + /* test compression speed? */ + if(!strcmp(argument, "-mem")) + { + benchmark = 1; + continue; + } + + /* compression level */ + if(!strcmp(argument, "-1") || !strcmp(argument, "--fastest")) + { + compress_level = 1; + continue; + } + if(!strcmp(argument, "-2")) + { + compress_level = 2; + continue; + } + + /* unknown option */ + if(argument[0] == '-') + { + printf("Error: unknown option %s\n\n", argument); + printf("To get help on usage:\n"); + printf(" 6pack --help\n\n"); + return -1; + } + + /* first specified file is input */ + if(!input_file) + { + input_file = argument; + continue; + } + + /* next specified file is output */ + if(!output_file) + { + output_file = argument; + continue; + } + + /* files are already specified */ + printf("Error: unknown option %s\n\n", argument); + printf("To get help on usage:\n"); + printf(" 6pack --help\n\n"); + return -1; + } + + if(!input_file) + { + printf("Error: input file is not specified.\n\n"); + printf("To get help on usage:\n"); + printf(" 6pack --help\n\n"); + return -1; + } + + if(!output_file && !benchmark) + { + printf("Error: output file is not specified.\n\n"); + printf("To get help on usage:\n"); + printf(" 6pack --help\n\n"); + return -1; + } + +#ifdef SIXPACK_BENCHMARK_WIN32 + if(benchmark) + return benchmark_speed(compress_level, input_file); + else +#endif + return pack_file(compress_level, input_file, output_file); + + /* unreachable */ + return 0; +} diff --git a/contrib/cpukit/fastlz/6unpack.c b/contrib/cpukit/fastlz/6unpack.c new file mode 100644 index 0000000000..b0215f9f51 --- /dev/null +++ b/contrib/cpukit/fastlz/6unpack.c @@ -0,0 +1,478 @@ +/* + 6PACK - file compressor using FastLZ (lightning-fast compression library) + + Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#include +#include +#include + +#define SIXPACK_VERSION_MAJOR 0 +#define SIXPACK_VERSION_MINOR 1 +#define SIXPACK_VERSION_REVISION 0 +#define SIXPACK_VERSION_STRING "0.1.0" + +#include "fastlz.h" + +#if defined(WIN32) || defined(__NT__) || defined(_WIN32) || defined(__WIN32__) +#if defined(__BORLANDC__) || defined(_MSC_VER) +#define inline __inline +#endif +#endif + +/* magic identifier for 6pack file */ +static unsigned char sixpack_magic[8] = {137, '6', 'P', 'K', 13, 10, 26, 10}; + +#define BLOCK_SIZE 65536 + +/* prototypes */ +static inline unsigned long update_adler32(unsigned long checksum, const void *buf, int len); +void usage(void); +int detect_magic(FILE *f); +static inline unsigned long readU16(const unsigned char* ptr); +static inline unsigned long readU32(const unsigned char* ptr); +void read_chunk_header(FILE* f, int* id, int* options, unsigned long* size, +unsigned long* checksum, unsigned long* extra); +int unpack_file(const char* archive_file); + +/* for Adler-32 checksum algorithm, see RFC 1950 Section 8.2 */ +#define ADLER32_BASE 65521 +static inline unsigned long update_adler32(unsigned long checksum, const void *buf, int len) +{ + const unsigned char* ptr = (const unsigned char*)buf; + unsigned long s1 = checksum & 0xffff; + unsigned long s2 = (checksum >> 16) & 0xffff; + + while(len>0) + { + unsigned k = len < 5552 ? len : 5552; + len -= k; + + while(k >= 8) + { + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + k -= 8; + } + + while(k-- > 0) + { + s1 += *ptr++; s2 += s1; + } + s1 = s1 % ADLER32_BASE; + s2 = s2 % ADLER32_BASE; + } + return (s2 << 16) + s1; +} + +void usage(void) +{ + printf("6unpack: uncompress 6pack archive\n"); + printf("Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)\n"); + printf("\n"); + printf("Usage: 6unpack archive-file\n"); + printf("\n"); +} + +/* return non-zero if magic sequence is detected */ +/* warning: reset the read pointer to the beginning of the file */ +int detect_magic(FILE *f) +{ + unsigned char buffer[8]; + size_t bytes_read; + int c; + + fseek(f, SEEK_SET, 0); + bytes_read = fread(buffer, 1, 8, f); + fseek(f, SEEK_SET, 0); + if(bytes_read < 8) + return 0; + + for(c = 0; c < 8; c++) + if(buffer[c] != sixpack_magic[c]) + return 0; + + return -1; +} + +static inline unsigned long readU16( const unsigned char* ptr ) +{ + return ptr[0]+(ptr[1]<<8); +} + +static inline unsigned long readU32( const unsigned char* ptr ) +{ + return ptr[0]+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24); +} + +void read_chunk_header(FILE* f, int* id, int* options, unsigned long* size, +unsigned long* checksum, unsigned long* extra) +{ + unsigned char buffer[16]; + fread(buffer, 1, 16, f); + + *id = readU16(buffer) & 0xffff; + *options = readU16(buffer+2) & 0xffff; + *size = readU32(buffer+4) & 0xffffffff; + *checksum = readU32(buffer+8) & 0xffffffff; + *extra = readU32(buffer+12) & 0xffffffff; +} + +int unpack_file(const char* input_file) +{ + FILE* in; + unsigned long fsize; + int c; + unsigned long percent; + unsigned char progress[20]; + int chunk_id; + int chunk_options; + unsigned long chunk_size; + unsigned long chunk_checksum; + unsigned long chunk_extra; + unsigned char buffer[BLOCK_SIZE]; + unsigned long checksum; + + unsigned long decompressed_size; + unsigned long total_extracted; + int name_length; + char* output_file; + FILE* f; + + unsigned char* compressed_buffer; + unsigned char* decompressed_buffer; + unsigned long compressed_bufsize; + unsigned long decompressed_bufsize; + + /* sanity check */ + in = fopen(input_file, "rb"); + if(!in) + { + printf("Error: could not open %s\n", input_file); + return -1; + } + + /* find size of the file */ + fseek(in, 0, SEEK_END); + fsize = ftell(in); + fseek(in, 0, SEEK_SET); + + /* not a 6pack archive? */ + if(!detect_magic(in)) + { + fclose(in); + printf("Error: file %s is not a 6pack archive!\n", input_file); + return -1; + } + + printf("Archive: %s", input_file); + + /* position of first chunk */ + fseek(in, 8, SEEK_SET); + + /* initialize */ + output_file = 0; + f = 0; + total_extracted = 0; + decompressed_size = 0; + percent = 0; + compressed_buffer = 0; + decompressed_buffer = 0; + compressed_bufsize = 0; + decompressed_bufsize = 0; + + /* main loop */ + for(;;) + { + /* end of file? */ + size_t pos = ftell(in); + if(pos >= fsize) + break; + + read_chunk_header(in, &chunk_id, &chunk_options, + &chunk_size, &chunk_checksum, &chunk_extra); + + if((chunk_id == 1) && (chunk_size > 10) && (chunk_size < BLOCK_SIZE)) + { + /* close current file, if any */ + printf("\n"); + free(output_file); + output_file = 0; + if(f) + fclose(f); + + /* file entry */ + fread(buffer, 1, chunk_size, in); + checksum = update_adler32(1L, buffer, chunk_size); + if(checksum != chunk_checksum) + { + free(output_file); + output_file = 0; + fclose(in); + printf("\nError: checksum mismatch!\n"); + printf("Got %08lX Expecting %08lX\n", checksum, chunk_checksum); + return -1; + } + + decompressed_size = readU32(buffer); + total_extracted = 0; + percent = 0; + + /* get file to extract */ + name_length = (int)readU16(buffer+8); + if(name_length > (int)chunk_size - 10) + name_length = chunk_size - 10; + output_file = (char*)malloc(name_length+1); + memset(output_file, 0, name_length+1); + for(c = 0; c < name_length; c++) + output_file[c] = buffer[10+c]; + + /* check if already exists */ + f = fopen(output_file, "rb"); + if(f) + { + fclose(f); + printf("File %s already exists. Skipped.\n", output_file); + free(output_file); + output_file = 0; + f = 0; + } + else + { + /* create the file */ + f = fopen(output_file, "wb"); + if(!f) + { + printf("Can't create file %s. Skipped.\n", output_file); + free(output_file); + output_file = 0; + f = 0; + } + else + { + /* for progress status */ + printf("\n"); + memset(progress, ' ', 20); + if(strlen(output_file) < 16) + for(c = 0; c < (int)strlen(output_file); c++) + progress[c] = output_file[c]; + else + { + for(c = 0; c < 13; c++) + progress[c] = output_file[c]; + progress[13] = '.'; + progress[14] = '.'; + progress[15] = ' '; + } + progress[16] = '['; + progress[17] = 0; + printf("%s", progress); + for(c = 0; c < 50; c++) + printf("."); + printf("]\r"); + printf("%s", progress); + } + } + } + + if((chunk_id == 17) && f && output_file && decompressed_size) + { + unsigned long remaining; + + /* uncompressed */ + switch(chunk_options) + { + /* stored, simply copy to output */ + case 0: + /* read one block at at time, write and update checksum */ + total_extracted += chunk_size; + remaining = chunk_size; + checksum = 1L; + for(;;) + { + unsigned long r = (BLOCK_SIZE < remaining) ? BLOCK_SIZE: remaining; + size_t bytes_read = fread(buffer, 1, r, in); + if(bytes_read == 0) + break; + fwrite(buffer, 1, bytes_read, f); + checksum = update_adler32(checksum, buffer, bytes_read); + remaining -= bytes_read; + } + + /* verify everything is written correctly */ + if(checksum != chunk_checksum) + { + fclose(f); + f = 0; + free(output_file); + output_file = 0; + printf("\nError: checksum mismatch. Aborted.\n"); + printf("Got %08lX Expecting %08lX\n", checksum, chunk_checksum); + } + break; + + /* compressed using FastLZ */ + case 1: + /* enlarge input buffer if necessary */ + if(chunk_size > compressed_bufsize) + { + compressed_bufsize = chunk_size; + free(compressed_buffer); + compressed_buffer = (unsigned char*)malloc(compressed_bufsize); + } + + /* enlarge output buffer if necessary */ + if(chunk_extra > decompressed_bufsize) + { + decompressed_bufsize = chunk_extra; + free(decompressed_buffer); + decompressed_buffer = (unsigned char*)malloc(decompressed_bufsize); + } + + /* read and check checksum */ + fread(compressed_buffer, 1, chunk_size, in); + checksum = update_adler32(1L, compressed_buffer, chunk_size); + total_extracted += chunk_extra; + + /* verify that the chunk data is correct */ + if(checksum != chunk_checksum) + { + fclose(f); + f = 0; + free(output_file); + output_file = 0; + printf("\nError: checksum mismatch. Skipped.\n"); + printf("Got %08lX Expecting %08lX\n", checksum, chunk_checksum); + } + else + { + /* decompress and verify */ + remaining = fastlz_decompress(compressed_buffer, chunk_size, decompressed_buffer, chunk_extra); + if(remaining != chunk_extra) + { + fclose(f); + f = 0; + free(output_file); + output_file = 0; + printf("\nError: decompression failed. Skipped.\n"); + } + else + fwrite(decompressed_buffer, 1, chunk_extra, f); + } + break; + + default: + printf("\nError: unknown compression method (%d)\n", chunk_options); + fclose(f); + f = 0; + free(output_file); + output_file = 0; + break; + } + + /* for progress, if everything is fine */ + if(f) + { + int last_percent = (int)percent; + if(decompressed_size < (1<<24)) + percent = total_extracted * 100 / decompressed_size; + else + percent = total_extracted / 256 * 100 / (decompressed_size >>8); + percent >>= 1; + while(last_percent < (int)percent) + { + printf("#"); + last_percent++; + } + } + } + + /* position of next chunk */ + fseek(in, pos + 16 + chunk_size, SEEK_SET); + } + printf("\n\n"); + + /* free allocated stuff */ + free(compressed_buffer); + free(decompressed_buffer); + free(output_file); + + /* close working files */ + if(f) + fclose(f); + fclose(in); + + /* so far so good */ + return 0; +} + +int main(int argc, char** argv) +{ + int i; + const char* archive_file; + + /* show help with no argument at all*/ + if(argc == 1) + { + usage(); + return 0; + } + + /* check for help on usage */ + for(i = 1; i <= argc; i++) + if(argv[i]) + if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) + { + usage(); + return 0; + } + + /* check for version information */ + for(i = 1; i <= argc; i++) + if(argv[i]) + if(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) + { + printf("6unpack: high-speed file compression tool\n"); + printf("Version %s (using FastLZ %s)\n", + SIXPACK_VERSION_STRING, FASTLZ_VERSION_STRING); + printf("Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)\n"); + printf("\n"); + return 0; + } + + /* needs at least two arguments */ + if(argc <= 1) + { + usage(); + return 0; + } + + archive_file = argv[1]; + + return unpack_file(archive_file); +} diff --git a/contrib/cpukit/fastlz/LICENSE b/contrib/cpukit/fastlz/LICENSE new file mode 100644 index 0000000000..4a6abd6acb --- /dev/null +++ b/contrib/cpukit/fastlz/LICENSE @@ -0,0 +1,24 @@ +FastLZ - lightning-fast lossless compression library + +Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) +Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) +Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/contrib/cpukit/fastlz/README.TXT b/contrib/cpukit/fastlz/README.TXT new file mode 100644 index 0000000000..581e9e8a63 --- /dev/null +++ b/contrib/cpukit/fastlz/README.TXT @@ -0,0 +1,75 @@ +FastLZ - lightning-fast lossless compression library + +Author: Ariya Hidayat +Official website: http://www.fastlz.org + +FastLZ is distributed using the MIT license, see file LICENSE +for details. + +FastLZ consists of two files: fastlz.h and fastlz.c. Just add these +files to your project in order to use FastLZ. For information on +compression and decompression routines, see fastlz.h. + +A simple file compressor called 6pack is included as an example +on how to use FastLZ. The corresponding decompressor is 6unpack. + +To compile using GCC: + + gcc -o 6pack 6pack.c fastlz.c + gcc -o 6unpack 6unpack.c fastlz.c + +To compile using MinGW: + + mingw32-gcc -o 6pack 6pack.c fastlz.c + mingw32-gcc -o 6unpack 6unpack.c fastlz.c + +To compile using Microsoft Visual C++: + + cl 6pack.c fastlz.c + cl 6unpack.c fastlz.c + +To compile using Borland C++: + + bcc32 6pack.c fastlz.c + bcc32 6unpack.c fastlz.c + +To compile using OpenWatcom C/C++: + + cl386 6pack.c fastlz.c + cl386 6unpack.c fastlz.c + +To compile using Intel C++ compiler for Windows: + + icl 6pack.c fastlz.c + icl 6unpack.c fastlz.c + +To compile using Intel C++ compiler for Linux: + + icc -o 6pack 6pack.c fastlz.c + icc -o 6unpack 6unpack.c fastlz.c + +To compile 6pack using LCC-Win32: + + lc 6pack.c fastlz.c + lc 6unpack.c fastlz.c + +To compile 6pack using Pelles C: + + pocc 6pack.c + pocc 6unpack.c + pocc fastlz.c + polink 6pack.obj fastlz.obj + polink 6unpack.obj fastlz.obj + +For speed optimization, always use proper compile flags for optimization options. +Typical compiler flags are given below: + +* GCC (pre 4.2): -march=pentium -O3 -fomit-frame-pointer -mtune=pentium +* GCC 4.2 or later: -march=pentium -O3 -fomit-frame-pointer -mtune=generic +* Digital Mars C/C++: -o+all -5 +* Intel C++ (Windows): /O3 /Qipo +* Intel C++ (Linux): -O2 -march=pentium -mtune=pentium +* Borland C++: -O2 -5 +* LCC-Win32: -O +* Pelles C: /O2 + diff --git a/contrib/cpukit/fastlz/fastlz.c b/contrib/cpukit/fastlz/fastlz.c new file mode 100644 index 0000000000..3c9d6f6f86 --- /dev/null +++ b/contrib/cpukit/fastlz/fastlz.c @@ -0,0 +1,551 @@ +/* + FastLZ - lightning-fast lossless compression library + + Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) + +/* + * Always check for bound when decompressing. + * Generally it is best to leave it defined. + */ +#define FASTLZ_SAFE + +/* + * Give hints to the compiler for branch prediction optimization. + */ +#if defined(__GNUC__) && (__GNUC__ > 2) +#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1)) +#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0)) +#else +#define FASTLZ_EXPECT_CONDITIONAL(c) (c) +#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c) +#endif + +/* + * Use inlined functions for supported systems. + */ +#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C) +#define FASTLZ_INLINE inline +#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__) +#define FASTLZ_INLINE __inline +#else +#define FASTLZ_INLINE +#endif + +/* + * Prevent accessing more than 8-bit at once, except on x86 architectures. + */ +#if !defined(FASTLZ_STRICT_ALIGN) +#define FASTLZ_STRICT_ALIGN +#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */ +#undef FASTLZ_STRICT_ALIGN +#elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */ +#undef FASTLZ_STRICT_ALIGN +#elif defined(_M_IX86) /* Intel, MSVC */ +#undef FASTLZ_STRICT_ALIGN +#elif defined(__386) +#undef FASTLZ_STRICT_ALIGN +#elif defined(_X86_) /* MinGW */ +#undef FASTLZ_STRICT_ALIGN +#elif defined(__I86__) /* Digital Mars */ +#undef FASTLZ_STRICT_ALIGN +#endif +#endif + +/* + * FIXME: use preprocessor magic to set this on different platforms! + */ +typedef unsigned char flzuint8; +typedef unsigned short flzuint16; +typedef unsigned int flzuint32; + +/* prototypes */ +int fastlz_compress(const void* input, int length, void* output); +int fastlz_compress_level(int level, const void* input, int length, void* output); +int fastlz_decompress(const void* input, int length, void* output, int maxout); + +#define MAX_COPY 32 +#define MAX_LEN 264 /* 256 + 8 */ +#define MAX_DISTANCE 8192 + +#if !defined(FASTLZ_STRICT_ALIGN) +#define FASTLZ_READU16(p) *((const flzuint16*)(p)) +#else +#define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8) +#endif + +#define HASH_LOG 13 +#define HASH_SIZE (1<< HASH_LOG) +#define HASH_MASK (HASH_SIZE-1) +#define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; } + +#undef FASTLZ_LEVEL +#define FASTLZ_LEVEL 1 + +#undef FASTLZ_COMPRESSOR +#undef FASTLZ_DECOMPRESSOR +#define FASTLZ_COMPRESSOR fastlz1_compress +#define FASTLZ_DECOMPRESSOR fastlz1_decompress +static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output); +static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout); +#include "fastlz.c" + +#undef FASTLZ_LEVEL +#define FASTLZ_LEVEL 2 + +#undef MAX_DISTANCE +#define MAX_DISTANCE 8191 +#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1) + +#undef FASTLZ_COMPRESSOR +#undef FASTLZ_DECOMPRESSOR +#define FASTLZ_COMPRESSOR fastlz2_compress +#define FASTLZ_DECOMPRESSOR fastlz2_decompress +static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output); +static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout); +#include "fastlz.c" + +int fastlz_compress(const void* input, int length, void* output) +{ + /* for short block, choose fastlz1 */ + if(length < 65536) + return fastlz1_compress(input, length, output); + + /* else... */ + return fastlz2_compress(input, length, output); +} + +int fastlz_decompress(const void* input, int length, void* output, int maxout) +{ + /* magic identifier for compression level */ + int level = ((*(const flzuint8*)input) >> 5) + 1; + + if(level == 1) + return fastlz1_decompress(input, length, output, maxout); + if(level == 2) + return fastlz2_decompress(input, length, output, maxout); + + /* unknown level, trigger error */ + return 0; +} + +int fastlz_compress_level(int level, const void* input, int length, void* output) +{ + if(level == 1) + return fastlz1_compress(input, length, output); + if(level == 2) + return fastlz2_compress(input, length, output); + + return 0; +} + +#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */ + +static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output) +{ + const flzuint8* ip = (const flzuint8*) input; + const flzuint8* ip_bound = ip + length - 2; + const flzuint8* ip_limit = ip + length - 12; + flzuint8* op = (flzuint8*) output; + + const flzuint8* htab[HASH_SIZE]; + const flzuint8** hslot; + flzuint32 hval; + + flzuint32 copy; + + /* sanity check */ + if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4)) + { + if(length) + { + /* create literal copy only */ + *op++ = length-1; + ip_bound++; + while(ip <= ip_bound) + *op++ = *ip++; + return length+1; + } + else + return 0; + } + + /* initializes hash table */ + for (hslot = htab; hslot < htab + HASH_SIZE; hslot++) + *hslot = ip; + + /* we start with literal copy */ + copy = 2; + *op++ = MAX_COPY-1; + *op++ = *ip++; + *op++ = *ip++; + + /* main loop */ + while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit)) + { + const flzuint8* ref; + flzuint32 distance; + + /* minimum match length */ + flzuint32 len = 3; + + /* comparison starting-point */ + const flzuint8* anchor = ip; + + /* check for a run */ +#if FASTLZ_LEVEL==2 + if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1)) + { + distance = 1; + ip += 3; + ref = anchor - 1 + 3; + goto match; + } +#endif + + /* find potential match */ + HASH_FUNCTION(hval,ip); + hslot = htab + hval; + ref = htab[hval]; + + /* calculate distance to the match */ + distance = anchor - ref; + + /* update hash table */ + *hslot = anchor; + + /* is this a match? check the first 3 bytes */ + if(distance==0 || +#if FASTLZ_LEVEL==1 + (distance >= MAX_DISTANCE) || +#else + (distance >= MAX_FARDISTANCE) || +#endif + *ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++) + goto literal; + +#if FASTLZ_LEVEL==2 + /* far, needs at least 5-byte match */ + if(distance >= MAX_DISTANCE) + { + if(*ip++ != *ref++ || *ip++!= *ref++) + goto literal; + len += 2; + } + + match: +#endif + + /* last matched byte */ + ip = anchor + len; + + /* distance is biased */ + distance--; + + if(!distance) + { + /* zero distance means a run */ + flzuint8 x = ip[-1]; + while(ip < ip_bound) + if(*ref++ != x) break; else ip++; + } + else + for(;;) + { + /* safe because the outer check against ip limit */ + if(*ref++ != *ip++) break; + if(*ref++ != *ip++) break; + if(*ref++ != *ip++) break; + if(*ref++ != *ip++) break; + if(*ref++ != *ip++) break; + if(*ref++ != *ip++) break; + if(*ref++ != *ip++) break; + if(*ref++ != *ip++) break; + while(ip < ip_bound) + if(*ref++ != *ip++) break; + break; + } + + /* if we have copied something, adjust the copy count */ + if(copy) + /* copy is biased, '0' means 1 byte copy */ + *(op-copy-1) = copy-1; + else + /* back, to overwrite the copy count */ + op--; + + /* reset literal counter */ + copy = 0; + + /* length is biased, '1' means a match of 3 bytes */ + ip -= 3; + len = ip - anchor; + + /* encode the match */ +#if FASTLZ_LEVEL==2 + if(distance < MAX_DISTANCE) + { + if(len < 7) + { + *op++ = (len << 5) + (distance >> 8); + *op++ = (distance & 255); + } + else + { + *op++ = (7 << 5) + (distance >> 8); + for(len-=7; len >= 255; len-= 255) + *op++ = 255; + *op++ = len; + *op++ = (distance & 255); + } + } + else + { + /* far away, but not yet in the another galaxy... */ + if(len < 7) + { + distance -= MAX_DISTANCE; + *op++ = (len << 5) + 31; + *op++ = 255; + *op++ = distance >> 8; + *op++ = distance & 255; + } + else + { + distance -= MAX_DISTANCE; + *op++ = (7 << 5) + 31; + for(len-=7; len >= 255; len-= 255) + *op++ = 255; + *op++ = len; + *op++ = 255; + *op++ = distance >> 8; + *op++ = distance & 255; + } + } +#else + + if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2)) + while(len > MAX_LEN-2) + { + *op++ = (7 << 5) + (distance >> 8); + *op++ = MAX_LEN - 2 - 7 -2; + *op++ = (distance & 255); + len -= MAX_LEN-2; + } + + if(len < 7) + { + *op++ = (len << 5) + (distance >> 8); + *op++ = (distance & 255); + } + else + { + *op++ = (7 << 5) + (distance >> 8); + *op++ = len - 7; + *op++ = (distance & 255); + } +#endif + + /* update the hash at match boundary */ + HASH_FUNCTION(hval,ip); + htab[hval] = ip++; + HASH_FUNCTION(hval,ip); + htab[hval] = ip++; + + /* assuming literal copy */ + *op++ = MAX_COPY-1; + + continue; + + literal: + *op++ = *anchor++; + ip = anchor; + copy++; + if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY)) + { + copy = 0; + *op++ = MAX_COPY-1; + } + } + + /* left-over as literal copy */ + ip_bound++; + while(ip <= ip_bound) + { + *op++ = *ip++; + copy++; + if(copy == MAX_COPY) + { + copy = 0; + *op++ = MAX_COPY-1; + } + } + + /* if we have copied something, adjust the copy length */ + if(copy) + *(op-copy-1) = copy-1; + else + op--; + +#if FASTLZ_LEVEL==2 + /* marker for fastlz2 */ + *(flzuint8*)output |= (1 << 5); +#endif + + return op - (flzuint8*)output; +} + +static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout) +{ + const flzuint8* ip = (const flzuint8*) input; + const flzuint8* ip_limit = ip + length; + flzuint8* op = (flzuint8*) output; + flzuint8* op_limit = op + maxout; + flzuint32 ctrl = (*ip++) & 31; + int loop = 1; + + do + { + const flzuint8* ref = op; + flzuint32 len = ctrl >> 5; + flzuint32 ofs = (ctrl & 31) << 8; + + if(ctrl >= 32) + { +#if FASTLZ_LEVEL==2 + flzuint8 code; +#endif + len--; + ref -= ofs; + if (len == 7-1) +#if FASTLZ_LEVEL==1 + len += *ip++; + ref -= *ip++; +#else + do + { + code = *ip++; + len += code; + } while (code==255); + code = *ip++; + ref -= code; + + /* match from 16-bit distance */ + if(FASTLZ_UNEXPECT_CONDITIONAL(code==255)) + if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8))) + { + ofs = (*ip++) << 8; + ofs += *ip++; + ref = op - ofs - MAX_DISTANCE; + } +#endif + +#ifdef FASTLZ_SAFE + if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit)) + return 0; + + if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output)) + return 0; +#endif + + if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit)) + ctrl = *ip++; + else + loop = 0; + + if(ref == op) + { + /* optimize copy for a run */ + flzuint8 b = ref[-1]; + *op++ = b; + *op++ = b; + *op++ = b; + for(; len; --len) + *op++ = b; + } + else + { +#if !defined(FASTLZ_STRICT_ALIGN) + const flzuint16* p; + flzuint16* q; +#endif + /* copy from reference */ + ref--; + *op++ = *ref++; + *op++ = *ref++; + *op++ = *ref++; + +#if !defined(FASTLZ_STRICT_ALIGN) + /* copy a byte, so that now it's word aligned */ + if(len & 1) + { + *op++ = *ref++; + len--; + } + + /* copy 16-bit at once */ + q = (flzuint16*) op; + op += len; + p = (const flzuint16*) ref; + for(len>>=1; len > 4; len-=4) + { + *q++ = *p++; + *q++ = *p++; + *q++ = *p++; + *q++ = *p++; + } + for(; len; --len) + *q++ = *p++; +#else + for(; len; --len) + *op++ = *ref++; +#endif + } + } + else + { + ctrl++; +#ifdef FASTLZ_SAFE + if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit)) + return 0; + if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit)) + return 0; +#endif + + *op++ = *ip++; + for(--ctrl; ctrl; ctrl--) + *op++ = *ip++; + + loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit); + if(loop) + ctrl = *ip++; + } + } + while(FASTLZ_EXPECT_CONDITIONAL(loop)); + + return op - (flzuint8*)output; +} + +#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */ diff --git a/contrib/cpukit/fastlz/fastlz.h b/contrib/cpukit/fastlz/fastlz.h new file mode 100644 index 0000000000..f87bc7be31 --- /dev/null +++ b/contrib/cpukit/fastlz/fastlz.h @@ -0,0 +1,100 @@ +/* + FastLZ - lightning-fast lossless compression library + + Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef FASTLZ_H +#define FASTLZ_H + +#define FASTLZ_VERSION 0x000100 + +#define FASTLZ_VERSION_MAJOR 0 +#define FASTLZ_VERSION_MINOR 0 +#define FASTLZ_VERSION_REVISION 0 + +#define FASTLZ_VERSION_STRING "0.1.0" + +#if defined (__cplusplus) +extern "C" { +#endif + +/** + Compress a block of data in the input buffer and returns the size of + compressed block. The size of input buffer is specified by length. The + minimum input buffer size is 16. + + The output buffer must be at least 5% larger than the input buffer + and can not be smaller than 66 bytes. + + If the input is not compressible, the return value might be larger than + length (input buffer size). + + The input buffer and the output buffer can not overlap. +*/ + +int fastlz_compress(const void* input, int length, void* output); + +/** + Decompress a block of compressed data and returns the size of the + decompressed block. If error occurs, e.g. the compressed data is + corrupted or the output buffer is not large enough, then 0 (zero) + will be returned instead. + + The input buffer and the output buffer can not overlap. + + Decompression is memory safe and guaranteed not to write the output buffer + more than what is specified in maxout. + */ + +int fastlz_decompress(const void* input, int length, void* output, int maxout); + +/** + Compress a block of data in the input buffer and returns the size of + compressed block. The size of input buffer is specified by length. The + minimum input buffer size is 16. + + The output buffer must be at least 5% larger than the input buffer + and can not be smaller than 66 bytes. + + If the input is not compressible, the return value might be larger than + length (input buffer size). + + The input buffer and the output buffer can not overlap. + + Compression level can be specified in parameter level. At the moment, + only level 1 and level 2 are supported. + Level 1 is the fastest compression and generally useful for short data. + Level 2 is slightly slower but it gives better compression ratio. + + Note that the compressed data, regardless of the level, can always be + decompressed using the function fastlz_decompress above. +*/ + +int fastlz_compress_level(int level, const void* input, int length, void* output); + +#if defined (__cplusplus) +} +#endif + +#endif /* FASTLZ_H */