// Based on ilia muraviev's CRUSH compressor program which falls under public domain #include "lzconfig.h" #include #ifdef LZP_USE_MALLOC #include #endif #include "bit.h" #include "lzp.h" // Internal structure for hash table allocation sizes #ifndef LZP_NO_COMPRESS struct { short WindowSize; // Window size (17 - 23) short Hash1Size; // Hash 1 table size (10 - 21) short Hash2Size; // Hash 2 table size (12 - 24) } lzHashParam = { LZP_WINDOW_SIZE, LZP_HASH1_SIZE, LZP_HASH2_SIZE }; #endif // Defines and macros for lz77 compression/decompression (don't touch) #define W_BITS lzHashParam.WindowSize #define HASH1_BITS lzHashParam.Hash1Size #define HASH2_BITS lzHashParam.Hash2Size #define W_SIZE (1<b?a:b); } int get_penalty(int a, int b) { int p=0; while(a > b) { a >>= 3; ++p; } return(p); } int lzCompress(void* outBuff, const void* inBuff, int inSize, int level) { #ifndef LZP_USE_MALLOC int head[HASH1_SIZE+HASH2_SIZE]; int prev[W_SIZE]; #else int* head = malloc(4*(HASH1_SIZE+HASH2_SIZE)); int* prev = malloc(4*W_SIZE); #endif int max_chain[] = {4, 256, 1<<12}; int i,s; int h1=0; int h2=0; int p=0; int len; int offset; int max_match; int limit; int chain_len; int next_p; int max_lazy; int log; inPtr = (unsigned char*)inBuff; outPtr = (unsigned char*)outBuff; outBytes = 0; for (i=0; i= limit) { s = head[h1]; if (inPtr[s] == inPtr[p]) { i = 0; while(++i < max_match) { if (inPtr[s+i] != inPtr[p+i]) break; } if (i > len) { len = i; offset = p-s; } } } if (len < MAX_MATCH) { chain_len = max_chain[level]; s = head[h2+HASH1_SIZE]; while((chain_len-- != 0) && (s >= limit)) { if ((inPtr[s+len] == inPtr[p+len]) && (inPtr[s] == inPtr[p])) { i = 0; while(++i < max_match) { if (inPtr[s+i] != inPtr[p+i]) break; } if (i > len+get_penalty((p-s)>>4, offset)) { len = i; offset = p-s; } if (i == max_match) break; } s=prev[s&W_MASK]; } } if ((len == MIN_MATCH) && (offset > TOO_FAR)) len=0; if ((level >= 2) && (len >= MIN_MATCH) && (len < max_match)) { next_p = p+1; max_lazy = get_min(len+4, max_match); chain_len = max_chain[level]; s = head[update_hash2(h2, inPtr[next_p+(HASH2_LEN-1)])+HASH1_SIZE]; while((chain_len-- != 0) && (s >= limit)) { if ((inPtr[s+len] == inPtr[next_p+len]) && (inPtr[s] == inPtr[next_p])) { i = 0; while(++i < max_lazy) { if (inPtr[s+i] != inPtr[next_p+i]) break; } if (i > len+get_penalty(next_p-s, offset)) { len = 0; break; } if (i == max_lazy) break; } s = prev[s&W_MASK]; } } if (len >= MIN_MATCH) { // Match put_bits(1, 1); i = len-MIN_MATCH; if (i < A) { put_bits(1, 1); // 1 put_bits(A_BITS, i); } else if (i < B) { put_bits(2, 1<<1); // 01 put_bits(B_BITS, i-A); } else if (i < C) { put_bits(3, 1<<2); // 001 put_bits(C_BITS, i-B); } else if (i < D) { put_bits(4, 1<<3); // 0001 put_bits(D_BITS, i-C); } else if (i < E) { put_bits(5, 1<<4); // 00001 put_bits(E_BITS, i-D); } else { put_bits(5, 0); // 00000 put_bits(F_BITS, i-E); } --offset; log = W_BITS-NUM_SLOTS; while(offset >= (2<(W_BITS-NUM_SLOTS)) put_bits(log, offset-(1<(windowSize-NUM_SLOTS) ? get_bits(log)+(1<(windowSize-NUM_SLOTS) ? get_bits(log)+(1<= outSize) break; outPtr[p++] = outPtr[s++]; if (p >= outSize) break; outPtr[p++] = outPtr[s++]; if (p >= outSize) break; while(len-- != 0) { outPtr[p++] = outPtr[s++]; if (p >= outSize) break; } if (p >= outSize) break; } else { outPtr[p++] = get_bits(8); } if (p >= outSize) break; } return(p); }