author | dessaya
<dessaya> 2005-03-13 05:11:50 UTC |
committer | dessaya
<dessaya> 2005-03-13 05:11:50 UTC |
parent | 12e9c168c24f85a80d82a57e5d8640e6786d49e2 |
PR/src/lib/compression/lzg_compress.c | +204 | -0 |
PR/src/lib/compression/lzg_decompress.c | +95 | -0 |
stuff/contest/lzg/Makefile | +15 | -0 |
stuff/contest/lzg/lzg.c | +172 | -0 |
stuff/contest/lzg/lzg_compress.c | +204 | -0 |
stuff/contest/lzg/lzg_compress.h | +7 | -0 |
stuff/contest/lzg/lzg_uncompress.c | +95 | -0 |
stuff/contest/lzg/lzg_uncompress.h | +7 | -0 |
stuff/contest/lzg/test | +15 | -1 |
stuff/contest/lzg/uncompress.c | +0 | -137 |
diff --git a/PR/src/lib/compression/lzg_compress.c b/PR/src/lib/compression/lzg_compress.c new file mode 100644 index 0000000..b0a076a --- /dev/null +++ b/PR/src/lib/compression/lzg_compress.c @@ -0,0 +1,204 @@ +/* + * LZG compression + * + * ---------------------------------------------------------------------------- + * + * Authors: + * Enrique Calot <ecalot.cod@princed.com.ar> + * Diego Essaya <dessaya@fi.uba.ar> + * + * Research: Tammo Jan Dijkemma, Anke Balderer, Enrique Calot + * + * ---------------------------------------------------------------------------- + * + * Copyright (C) 2004, 2005 the Princed Team + * + * This file is part of the Princed project. + * + * Princed is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Princed is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * Modus operandi of the compression algorithm + * ------------------------------------------- + * + * For each input byte we take a window containing the 1023 previous bytes. + * If the window goes out of bounds (ie, when the current input byte is + * before position 1024), we consider it filled with zeros. + * + * 00000000000000000000******************************** + * ^ ^ + * input start current input byte + * |--------------------------------| + * window size=1023 + * + * The algorithm works as follows: + * + * While there is unread input data: + * Create a maskbyte. + * For each bit in the maskbyte (and there is still unread input data): + * Compare the following input bytes with the bytes in the window, + * and search the longest pattern that is equal to the next bytes. + * If we found a pattern of length n > 2: + * Assign 0 to the current bit of the maskbyte. + * In the next 2 bytes of the output, specify the relative + * position and length of the pattern. + * Advance output pointer by 2. + * Advance input pointer by n. + * Else: + * Assign 1 to the current bit of the maskbyte. + * Copy the current input byte in the next output byte. + * Advance output pointer by 1. + * Advance input pointer by 1. + */ + +#include <string.h> /* memchr() */ +#include <stdio.h> +#include "lzg_compress.h" + +/* Window size */ +#define WIN_SIZE 1024 + +/* A repetition pattern must have a length of at least MIN_PATTERN_SIZE + * to be accepted (ie, to be worth for compressing) */ +#define MIN_PATTERN_SIZE 3 +#define MAX_PATTERN_SIZE 66 + +/* search the longest pattern in the window that matches the first bytes + * of the input */ +void search_best_pattern(unsigned char *input, int inputSize, + unsigned char *window, + unsigned char **best_pattern, + int *best_pattern_len) +{ + unsigned char *pattern; + int pattern_len; + int window_len = WIN_SIZE - 1; + + *best_pattern_len = 0; + + while ((pattern = (unsigned char *)memchr(window, *input, window_len))) + { + unsigned char *ic = input + 1; + unsigned char *wc = pattern + 1; + pattern_len = 1; + + while ( (ic < (input + inputSize)) && + (wc < (window + window_len)) && + (*ic == *wc) && + pattern_len < MAX_PATTERN_SIZE) + { + ic++; wc++; pattern_len++; + } + + if (pattern_len > *best_pattern_len) + { + *best_pattern_len = pattern_len; + *best_pattern = pattern; + } + + window_len -= wc - window; + window = wc; + } +} + +/* Insert the specified bit in the current maskByte. If the maskByte is full, + * start a new one. */ +void pushMaskBit(int b, unsigned char **maskByte, int *maskBit, + unsigned char *output, int *outputPos) +{ + if ( (!(*maskByte)) || (*maskBit == 8) ) + { + /* start a new maskByte */ + *maskByte = output + *outputPos; + (*outputPos)++; + **maskByte = 0; + *maskBit = 0; +printf("maskbyte i=%d\n", *outputPos - 1); + } + + **maskByte >>= 1; + **maskByte += b << 7; + (*maskBit)++; +} + +/* Insert the two bytes describing the pattern repetition to the output. */ +void addPattern(unsigned char *input, int inputPos, + unsigned char *output, int outputPos, + unsigned char *pattern, int pattern_len) +{ + int loc = (pattern - input) + 1024 - 66; +printf("pattern i=%d o=%d rep=%d loc=%d\n", outputPos, inputPos, pattern_len, inputPos-(pattern-input)); + output[outputPos] = + (((pattern_len - 3) << 2) & 0xfc) + ((loc & 0x0300) >> 8); + output[outputPos + 1] = (loc & 0x00FF); +} + +/* Compress using the LZG algorithm */ +/* Assume output has been allocated and the size is very big */ +void compressLzg(unsigned char* input, int inputSize, + unsigned char* output, int *outputSize) +{ + int inputPos = 0, outputPos = 0; + unsigned char *maskByte = NULL; + int maskBit = 0; + int i; + + /* Create ghost window filled with zeros before input data: */ + for (i = inputSize - 1; i >= 0; i--) + input[i + WIN_SIZE] = input[i]; + for (i = 0; i < WIN_SIZE; i++) + input[i] = 0; + input += WIN_SIZE; + + while (inputPos < inputSize) + { + unsigned char *best_pattern; + int best_pattern_len; + unsigned char *window; + + /* Determine window position: */ + window = input + inputPos - (WIN_SIZE - 1); + + search_best_pattern(input + inputPos, inputSize - inputPos, + window, + &best_pattern, &best_pattern_len); + + if (best_pattern_len < MIN_PATTERN_SIZE) + { + /* No suitable pattern found. Just copy the current byte. */ + pushMaskBit(1, &maskByte, &maskBit, output, &outputPos); + output[outputPos] = input[inputPos]; +printf("copy i=%d o=%d data=%02x\n", outputPos, inputPos, output[outputPos]); + inputPos++; + outputPos++; + } + else + { + /* Can compress. Repeat the best pattern. */ + pushMaskBit(0, &maskByte, &maskBit, output, &outputPos); + addPattern(input, inputPos, output, outputPos, + best_pattern, best_pattern_len); + inputPos += best_pattern_len; + outputPos += 2; + } + } + + /* finish last maskByte: */ + *maskByte >>= (8 - maskBit); + + *outputSize = outputPos; +} + diff --git a/PR/src/lib/compression/lzg_decompress.c b/PR/src/lib/compression/lzg_decompress.c new file mode 100644 index 0000000..bd84c86 --- /dev/null +++ b/PR/src/lib/compression/lzg_decompress.c @@ -0,0 +1,95 @@ +/* + * LZG extraction + * + * ---------------------------------------------------------------------------- + * + * Authors: + * Enrique Calot <ecalot.cod@princed.com.ar> + * + * Research: Tammo Jan Dijkemma, Anke Balderer, Enrique Calot + * + * ---------------------------------------------------------------------------- + * + * Copyright (C) 2004, 2005 the Princed Team + * + * This file is part of the Princed project. + * + * Princed is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Princed is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include "lzg_uncompress.h" + +/* modulus to be used in the 10 bits of the algorithm */ +#define LZG_WINDOW_SIZE 0x400 /* =1024=1<<10 */ + +/* LZG expansion algorithm sub function */ +unsigned char popBit(unsigned char *byte) { + register unsigned char bit=(*byte)&1; + (*byte)>>=1; + return bit; +} + +/* Expands LZ Groody algorithm. This is the core of PR */ +int expandLzg(const unsigned char* input, int inputSize, + unsigned char* output, int *outputSize) { + + int loc, oCursor=0, iCursor=0; + unsigned char maskbyte=0, rep, k; + + /* initialize the first 1024 bytes of the window with zeros */ + for(oCursor=0;oCursor<LZG_WINDOW_SIZE;output[oCursor++]=0); + + /* main loop */ + while (iCursor<inputSize) { + maskbyte=input[iCursor++]; +printf("maskbyte i=%d\n", iCursor - 1); + for (k=8;k&&(iCursor<inputSize);k--) { + if (popBit(&maskbyte)) { + output[oCursor++]=input[iCursor++]; /* copy input to output */ +printf("copy i=%d o=%d data=%02x\n", iCursor - 1, oCursor - (LZG_WINDOW_SIZE + 1), output[oCursor-1]); + } else { + /* + * loc: + * 10 bits for the slide iCursorition (S). Add 66 to this number, + * substract the result to the current oCursor and take the last 10 bits. + * rep: + * 6 bits for the repetition number (R). Add 3 to this number. + */ + loc= 66 + ((input[iCursor] & 0x03 /*00000011*/) <<8) + input[iCursor+1]; + rep= 3 + ((input[iCursor] & 0xfc /*11111100*/) >>2); + + iCursor+=2; /* move the cursor 2 bytes ahead */ + + loc=(oCursor-loc)&0x3ff; /* this is the real loc number (allways positive!) */ +printf("pattern i=%d o=%d rep=%d loc=%d\n", iCursor - 2, oCursor-LZG_WINDOW_SIZE, rep, loc); + + while (rep--) { /* repeat pattern in output */ + output[oCursor]=output[oCursor-loc]; + + oCursor++; + } + } + } + } + + /* ignore the first 1024 bytes */ + for(iCursor=LZG_WINDOW_SIZE;iCursor<oCursor;iCursor++) + output[iCursor-LZG_WINDOW_SIZE]=output[iCursor]; + + *outputSize=oCursor-LZG_WINDOW_SIZE; + return maskbyte; +} + diff --git a/stuff/contest/lzg/Makefile b/stuff/contest/lzg/Makefile new file mode 100644 index 0000000..287a509 --- /dev/null +++ b/stuff/contest/lzg/Makefile @@ -0,0 +1,15 @@ +# Makefile for the lzg compressor/extractor + +CC=gcc +CPPFLAGS=-Wall -ansi -pedantic -g + +all: lzg + +lzg: lzg.o lzg_compress.o lzg_uncompress.o + +lzg.o: lzg.c lzg_compress.h lzg_uncompress.h +lzg_compress.o: lzg_compress.h +lzg_uncompress.o: lzg_uncompress.h + +clean: + rm -fv *.o lzg diff --git a/stuff/contest/lzg/lzg.c b/stuff/contest/lzg/lzg.c new file mode 100644 index 0000000..fa3f2f1 --- /dev/null +++ b/stuff/contest/lzg/lzg.c @@ -0,0 +1,172 @@ +/* + * LZG compressor/extractor + * + * This sample code is to test the LZG algorithm + * + * Usage: + * ./lzg [-x] (input file) (output file) + * + * Use -x to uncompress. + * + * ---------------------------------------------------------------------------- + * + * Authors: + * Enrique Calot <ecalot.cod@princed.com.ar> + * Diego Essaya <dessaya@fi.uba.ar> + * + * Research: Tammo Jan Dijkemma, Anke Balderer, Enrique Calot + * + * ---------------------------------------------------------------------------- + * + * Copyright (C) 2004, 2005 the Princed Team + * + * This file is part of the Princed project. + * + * Princed is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Princed is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <string.h> +#include "lzg_compress.h" +#include "lzg_uncompress.h" + +typedef enum {COMPRESS, EXPAND, HELP, ERROR} action_t; + +struct t_options { + char *input_file; + char *output_file; +}; + +/* A big number (the input/output must be less that that) */ +#define LZG_MAX_MEMSIZE 65536 + +void print_syntax() +{ + fprintf(stderr, "Syntax: lzg [-x] input [output]\n"); +} + +action_t process_args(int argc, char *argv[], struct t_options *opts) +{ + action_t action = COMPRESS; + int i; + + opts->input_file = opts->output_file = NULL; + + for(i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-x")) { + action = EXPAND; + } + else { /* filename */ + if (!opts->input_file || !strcmp(opts->input_file, "-")) + opts->input_file = argv[i]; + else if (!opts->output_file || !strcmp(opts->output_file, "-")) + opts->output_file = argv[i]; + else + { + fprintf(stderr, "Invalid argument: %s\n", argv[i]); + return ERROR; + } + } + } + + return action; +} + +int main(int argc, char *argv[]) +{ + action_t action; + struct t_options opts; + unsigned char input[LZG_MAX_MEMSIZE]; + unsigned char output[LZG_MAX_MEMSIZE]; + int inputSize, outputSize; + FILE* fp; + int result; + + action = process_args(argc, argv, &opts); + if (action == ERROR) + { + print_syntax(); + return 1; + } + if (action == HELP) + { + print_syntax(); + return 0; + } + + if (!opts.input_file) + { + fprintf(stderr, "warning: Reading from stdin.\n"); + fp = stdin; + } + else + { + fp = fopen(opts.input_file, "rb"); + if (!fp) { + fprintf(stderr, "Error opening file '%s' for reading.\n", opts.input_file); + return 1; + } + } + + inputSize = fread(input, 1, sizeof(input), fp); + if (inputSize <= 0) + { + fprintf(stderr, "Error reading input file.\n"); + return 1; + } + + fclose(fp); + + if (!opts.output_file) + { + fprintf(stderr, "warning: Writing to stdout.\n"); + fp = stdout; + } + else + { + fp = fopen(opts.output_file, "wb"); + if (!fp) { + fprintf(stderr, "Error opening file '%s' for writing.\n", opts.output_file); + return 1; + } + } + + if (action == EXPAND) + { + result=expandLzg(input, inputSize, output, &outputSize); + if (result) + fprintf(stderr,"Maskbyte not clean, possible data corruption\n"); + } + else + { + compressLzg(input, inputSize, output, &outputSize); + } + + if (fwrite(output, outputSize, 1, fp) <= 0) + { + fprintf(stderr, "Error writing output.\n"); + return 1; + } + + fclose(fp); + + /* show results on screen */ + printf("Results:\n Input file: %s (%d)\n Output file: %s (%d)\n", + opts.input_file ? opts.input_file : "stdin", inputSize, + opts.output_file ? opts.output_file : "stdout", outputSize); + + return 0; +} + diff --git a/stuff/contest/lzg/lzg_compress.c b/stuff/contest/lzg/lzg_compress.c new file mode 100644 index 0000000..b0a076a --- /dev/null +++ b/stuff/contest/lzg/lzg_compress.c @@ -0,0 +1,204 @@ +/* + * LZG compression + * + * ---------------------------------------------------------------------------- + * + * Authors: + * Enrique Calot <ecalot.cod@princed.com.ar> + * Diego Essaya <dessaya@fi.uba.ar> + * + * Research: Tammo Jan Dijkemma, Anke Balderer, Enrique Calot + * + * ---------------------------------------------------------------------------- + * + * Copyright (C) 2004, 2005 the Princed Team + * + * This file is part of the Princed project. + * + * Princed is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Princed is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * Modus operandi of the compression algorithm + * ------------------------------------------- + * + * For each input byte we take a window containing the 1023 previous bytes. + * If the window goes out of bounds (ie, when the current input byte is + * before position 1024), we consider it filled with zeros. + * + * 00000000000000000000******************************** + * ^ ^ + * input start current input byte + * |--------------------------------| + * window size=1023 + * + * The algorithm works as follows: + * + * While there is unread input data: + * Create a maskbyte. + * For each bit in the maskbyte (and there is still unread input data): + * Compare the following input bytes with the bytes in the window, + * and search the longest pattern that is equal to the next bytes. + * If we found a pattern of length n > 2: + * Assign 0 to the current bit of the maskbyte. + * In the next 2 bytes of the output, specify the relative + * position and length of the pattern. + * Advance output pointer by 2. + * Advance input pointer by n. + * Else: + * Assign 1 to the current bit of the maskbyte. + * Copy the current input byte in the next output byte. + * Advance output pointer by 1. + * Advance input pointer by 1. + */ + +#include <string.h> /* memchr() */ +#include <stdio.h> +#include "lzg_compress.h" + +/* Window size */ +#define WIN_SIZE 1024 + +/* A repetition pattern must have a length of at least MIN_PATTERN_SIZE + * to be accepted (ie, to be worth for compressing) */ +#define MIN_PATTERN_SIZE 3 +#define MAX_PATTERN_SIZE 66 + +/* search the longest pattern in the window that matches the first bytes + * of the input */ +void search_best_pattern(unsigned char *input, int inputSize, + unsigned char *window, + unsigned char **best_pattern, + int *best_pattern_len) +{ + unsigned char *pattern; + int pattern_len; + int window_len = WIN_SIZE - 1; + + *best_pattern_len = 0; + + while ((pattern = (unsigned char *)memchr(window, *input, window_len))) + { + unsigned char *ic = input + 1; + unsigned char *wc = pattern + 1; + pattern_len = 1; + + while ( (ic < (input + inputSize)) && + (wc < (window + window_len)) && + (*ic == *wc) && + pattern_len < MAX_PATTERN_SIZE) + { + ic++; wc++; pattern_len++; + } + + if (pattern_len > *best_pattern_len) + { + *best_pattern_len = pattern_len; + *best_pattern = pattern; + } + + window_len -= wc - window; + window = wc; + } +} + +/* Insert the specified bit in the current maskByte. If the maskByte is full, + * start a new one. */ +void pushMaskBit(int b, unsigned char **maskByte, int *maskBit, + unsigned char *output, int *outputPos) +{ + if ( (!(*maskByte)) || (*maskBit == 8) ) + { + /* start a new maskByte */ + *maskByte = output + *outputPos; + (*outputPos)++; + **maskByte = 0; + *maskBit = 0; +printf("maskbyte i=%d\n", *outputPos - 1); + } + + **maskByte >>= 1; + **maskByte += b << 7; + (*maskBit)++; +} + +/* Insert the two bytes describing the pattern repetition to the output. */ +void addPattern(unsigned char *input, int inputPos, + unsigned char *output, int outputPos, + unsigned char *pattern, int pattern_len) +{ + int loc = (pattern - input) + 1024 - 66; +printf("pattern i=%d o=%d rep=%d loc=%d\n", outputPos, inputPos, pattern_len, inputPos-(pattern-input)); + output[outputPos] = + (((pattern_len - 3) << 2) & 0xfc) + ((loc & 0x0300) >> 8); + output[outputPos + 1] = (loc & 0x00FF); +} + +/* Compress using the LZG algorithm */ +/* Assume output has been allocated and the size is very big */ +void compressLzg(unsigned char* input, int inputSize, + unsigned char* output, int *outputSize) +{ + int inputPos = 0, outputPos = 0; + unsigned char *maskByte = NULL; + int maskBit = 0; + int i; + + /* Create ghost window filled with zeros before input data: */ + for (i = inputSize - 1; i >= 0; i--) + input[i + WIN_SIZE] = input[i]; + for (i = 0; i < WIN_SIZE; i++) + input[i] = 0; + input += WIN_SIZE; + + while (inputPos < inputSize) + { + unsigned char *best_pattern; + int best_pattern_len; + unsigned char *window; + + /* Determine window position: */ + window = input + inputPos - (WIN_SIZE - 1); + + search_best_pattern(input + inputPos, inputSize - inputPos, + window, + &best_pattern, &best_pattern_len); + + if (best_pattern_len < MIN_PATTERN_SIZE) + { + /* No suitable pattern found. Just copy the current byte. */ + pushMaskBit(1, &maskByte, &maskBit, output, &outputPos); + output[outputPos] = input[inputPos]; +printf("copy i=%d o=%d data=%02x\n", outputPos, inputPos, output[outputPos]); + inputPos++; + outputPos++; + } + else + { + /* Can compress. Repeat the best pattern. */ + pushMaskBit(0, &maskByte, &maskBit, output, &outputPos); + addPattern(input, inputPos, output, outputPos, + best_pattern, best_pattern_len); + inputPos += best_pattern_len; + outputPos += 2; + } + } + + /* finish last maskByte: */ + *maskByte >>= (8 - maskBit); + + *outputSize = outputPos; +} + diff --git a/stuff/contest/lzg/lzg_compress.h b/stuff/contest/lzg/lzg_compress.h new file mode 100644 index 0000000..252145d --- /dev/null +++ b/stuff/contest/lzg/lzg_compress.h @@ -0,0 +1,7 @@ +#ifndef _LZG_COMPRESS_H_ +#define _LZG_COMPRESS_H_ + +void compressLzg(unsigned char* input, int inputSize, + unsigned char* output, int *outputSize); + +#endif diff --git a/stuff/contest/lzg/lzg_uncompress.c b/stuff/contest/lzg/lzg_uncompress.c new file mode 100644 index 0000000..bd84c86 --- /dev/null +++ b/stuff/contest/lzg/lzg_uncompress.c @@ -0,0 +1,95 @@ +/* + * LZG extraction + * + * ---------------------------------------------------------------------------- + * + * Authors: + * Enrique Calot <ecalot.cod@princed.com.ar> + * + * Research: Tammo Jan Dijkemma, Anke Balderer, Enrique Calot + * + * ---------------------------------------------------------------------------- + * + * Copyright (C) 2004, 2005 the Princed Team + * + * This file is part of the Princed project. + * + * Princed is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Princed is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include "lzg_uncompress.h" + +/* modulus to be used in the 10 bits of the algorithm */ +#define LZG_WINDOW_SIZE 0x400 /* =1024=1<<10 */ + +/* LZG expansion algorithm sub function */ +unsigned char popBit(unsigned char *byte) { + register unsigned char bit=(*byte)&1; + (*byte)>>=1; + return bit; +} + +/* Expands LZ Groody algorithm. This is the core of PR */ +int expandLzg(const unsigned char* input, int inputSize, + unsigned char* output, int *outputSize) { + + int loc, oCursor=0, iCursor=0; + unsigned char maskbyte=0, rep, k; + + /* initialize the first 1024 bytes of the window with zeros */ + for(oCursor=0;oCursor<LZG_WINDOW_SIZE;output[oCursor++]=0); + + /* main loop */ + while (iCursor<inputSize) { + maskbyte=input[iCursor++]; +printf("maskbyte i=%d\n", iCursor - 1); + for (k=8;k&&(iCursor<inputSize);k--) { + if (popBit(&maskbyte)) { + output[oCursor++]=input[iCursor++]; /* copy input to output */ +printf("copy i=%d o=%d data=%02x\n", iCursor - 1, oCursor - (LZG_WINDOW_SIZE + 1), output[oCursor-1]); + } else { + /* + * loc: + * 10 bits for the slide iCursorition (S). Add 66 to this number, + * substract the result to the current oCursor and take the last 10 bits. + * rep: + * 6 bits for the repetition number (R). Add 3 to this number. + */ + loc= 66 + ((input[iCursor] & 0x03 /*00000011*/) <<8) + input[iCursor+1]; + rep= 3 + ((input[iCursor] & 0xfc /*11111100*/) >>2); + + iCursor+=2; /* move the cursor 2 bytes ahead */ + + loc=(oCursor-loc)&0x3ff; /* this is the real loc number (allways positive!) */ +printf("pattern i=%d o=%d rep=%d loc=%d\n", iCursor - 2, oCursor-LZG_WINDOW_SIZE, rep, loc); + + while (rep--) { /* repeat pattern in output */ + output[oCursor]=output[oCursor-loc]; + + oCursor++; + } + } + } + } + + /* ignore the first 1024 bytes */ + for(iCursor=LZG_WINDOW_SIZE;iCursor<oCursor;iCursor++) + output[iCursor-LZG_WINDOW_SIZE]=output[iCursor]; + + *outputSize=oCursor-LZG_WINDOW_SIZE; + return maskbyte; +} + diff --git a/stuff/contest/lzg/lzg_uncompress.h b/stuff/contest/lzg/lzg_uncompress.h new file mode 100644 index 0000000..242894f --- /dev/null +++ b/stuff/contest/lzg/lzg_uncompress.h @@ -0,0 +1,7 @@ +#ifndef _LZG_UNCOMPRESS_H_ +#define _LZG_UNCOMPRESS_H_ + +int expandLzg(const unsigned char* input, int inputSize, + unsigned char* output, int *outputSize); + +#endif diff --git a/stuff/contest/lzg/test b/stuff/contest/lzg/test index 17dcccb..8493c62 100755 --- a/stuff/contest/lzg/test +++ b/stuff/contest/lzg/test @@ -1 +1,15 @@ -ls cmp|sed -e 's/\([0-9]*\).cmp/\1/'|while read i; do ./uncompress cmp/$i.cmp roo/$i.roo>/dev/null; diff raw/$i.raw roo/$i.roo;done +#!/bin/bash + +# test compress & uncompress functions + +[ -d samples ] || { echo "samples dir not found!"; exit 1; } + +if [ "x$1" = "xuncompress" ]; then + [ -d raw ] || mkdir raw + + ls samples/*cmp | sed -e 's/[^0-9]*\([0-9]*\).cmp/\1/' | while read i; do ./lzg -x samples/$i.cmp raw/$i.raw >/dev/null; diff samples/$i.raw raw/$i.raw;done +else + [ -d cmp ] || mkdir cmp + + ls samples/*raw | sed -e 's/[^0-9]*\([0-9]*\).raw/\1/' | while read i; do ./lzg samples/$i.raw cmp/$i.cmp >/dev/null; ./lzg -x cmp/$i.cmp cmp/$i.raw >/dev/null; diff samples/$i.raw cmp/$i.raw;done +fi diff --git a/stuff/contest/lzg/uncompress.c b/stuff/contest/lzg/uncompress.c deleted file mode 100644 index 828925d..0000000 --- a/stuff/contest/lzg/uncompress.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * This sample code is to test the LZG algorithm - * - * Compile with: - * gcc -o uncompress uncompress.c - * - * Usage: - * ./uncompress (input file) (output file) - * - * note that input file must be a valid LZG compressed file with - * permission to be read and output file should be a nonexistent file - * or it will be overwritten. - * - * This document is GPL - * Source Author: Enrique Calot - * Research: Tammo Jan Dijkemma, Anke Balderer, Enrique Calot - */ - -#include <stdio.h> - -/* BEGIN of page pasted part */ - -/* A big number (the output must be less that that) */ -#define LZG_MAX_MEMSIZE 32001 - -/* modulus to be used in the 10 bits of the algorithm */ -#define LZG_WINDOW_SIZE 0x400 /* =1024=1<<10 */ - -/* LZG expansion algorithm sub function */ -unsigned char popBit(unsigned char *byte) { - register unsigned char bit=(*byte)&1; - (*byte)>>=1; - return bit; -} - -/* Expands LZ Groody algorithm. This is the core of PR */ -int expandLzg(const unsigned char* input, int inputSize, - unsigned char* output, int *outputSize) { - - int loc, oCursor=0, iCursor=0; - unsigned char maskbyte=0, rep, k; - - /* initialize the first 1024 bytes of the window with zeros */ - for(oCursor=0;oCursor<LZG_WINDOW_SIZE;output[oCursor++]=0); - - /* main loop */ - while (iCursor<inputSize) { - maskbyte=input[iCursor++]; - for (k=8;k&&(iCursor<inputSize);k--) { - if (popBit(&maskbyte)) { - output[oCursor++]=input[iCursor++]; /* copy input to output */ -printf("print %02x@%d from input(%d)\n",output[oCursor-1],oCursor-1025,iCursor-1); - } else { - /* - * loc: - * 10 bits for the slide iCursorition (S). Add 66 to this number, - * substract the result to the current oCursor and take the last 10 bits. - * rep: - * 6 bits for the repetition number (R). Add 3 to this number. - */ - loc= 66 + ((input[iCursor] & 0x03 /*00000011*/) <<8) + input[iCursor+1]; - rep= 3 + ((input[iCursor] & 0xfc /*11111100*/) >>2); - - iCursor+=2; /* move the cursor 2 bytes ahead */ - - loc=(oCursor-loc)&0x3ff; /* this is the real loc number (allways positive!) */ - - while (rep--) { /* repeat pattern in output */ - output[oCursor]=output[oCursor-loc]; - - printf("print %02x@%d copied from %d (loc=%d)\n",output[oCursor],oCursor-LZG_WINDOW_SIZE,oCursor-loc-LZG_WINDOW_SIZE,loc); - - oCursor++; - } - } - } - } - - /* ignore the first 1024 bytes */ - for(iCursor=LZG_WINDOW_SIZE;iCursor<oCursor;iCursor++) - output[iCursor-LZG_WINDOW_SIZE]=output[iCursor]; - - *outputSize=oCursor-LZG_WINDOW_SIZE; - return maskbyte; -} - -/* END of page pasted part */ - -int main(int argc, char** argv) { - /* declare variables */ - unsigned char uncompressed[LZG_MAX_MEMSIZE]; - unsigned char compressed[LZG_MAX_MEMSIZE]; - int uncompressedSize, compressedSize; - FILE* fp; - int result; - - /* validate input */ - if (argc!=3) { - fprintf(stderr,"Syntax: %s [cmp file] [target raw file]\n",*argv); - return 1; - } - - /* open file */ - fp=fopen(argv[1],"rb"); - if (!fp) { - fprintf(stderr,"Error opening '%s'. Does it exist?\n",argv[1]); - return 2; - } - - /* read file to array */ - uncompressedSize=fread(uncompressed,1,sizeof(uncompressed),fp); - - /* close file */ - fclose(fp); - - /* compress file */ - result=expandLzg(uncompressed,uncompressedSize,compressed,&compressedSize); - - if (result) fprintf(stderr,"Maskbyte not clean, possible data corruption\n"); - - /* save results */ - fp=fopen(argv[2],"wb"); - if (!fp) { - fprintf(stderr,"Error opening '%s' for writting. Do you have permissions?\n",argv[2]); - return 4; - } - fwrite(compressed,compressedSize,1,fp); - fclose(fp); - - /* show results on screen */ - printf ("Results:\n Input file: %s (%d)\n Output file: %s (%d)\n", - argv[1],uncompressedSize,argv[2],compressedSize); - - /* end */ - return 0; -} -