/* depend: */
/* cflags: */
-/* linker: */
+/* linker: code.o debug.o */
#include <assert.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "code.h"
+#include "debug.h"
/* constants */
-#define COMPRESS 1
-#define DECOMPRESS 2
-
-#define NB_CHARS 256
#define BUFFER_SIZE 4096
-#define DEBUG 4
-#define INFO 3
-#define WARNING 2
-#define ERROR 1
-
/* macros */
-#define CEIL(x, y) (((x) + (y) - 1) / (y))
-#define MIN(x, y) (((x) < (y)) ? (x) : (y))
-#define MAX(x, y) (((x) > (y)) ? (x) : (y))
-#define VERBOSE(level, statement...) do { if (level <= verbose) { statement; } } while(0)
-#define PRINTF(args...) do { fprintf (stdout, args); fflush (stdout); } while (0)
-
/* gobal variables */
char *progname = NULL;
-int verbose = 2;
/* help function */
int *create_table (char *filename)
{
- char buffer[BUFFER_SIZE] = {0};
+ byte_t buffer[BUFFER_SIZE] = {0};
int nbread;
int *table = NULL;
FILE *fid = NULL;
VERBOSE (DEBUG, PRINTF ("start creating occurence table\n"));
/* memory allocation */
- table = (int *) calloc (NB_CHARS, sizeof (int));
+ table = (int *) calloc (NB_BYTES, sizeof (int));
if (table == NULL) {
VERBOSE (ERROR, printf ("can't allocate memory\n"));
return NULL;
int i;
printf ("Occurence table\n");
- for (i = 0; i < NB_CHARS; i++) {
+ for (i = 0; i < NB_BYTES; i++) {
if (table[i]) {
printf ("0x%02x '%c': %d\n", i, ((i < 32) || (i > 127)) ? '.' : i, table[i]);
}
struct _leaf_t *left;
struct _leaf_t *right;
int occ;
- char c;
+ byte_t c;
} leaf_t;
/* initialize forest */
VERBOSE (DEBUG, PRINTF ("start initiliazing forest\n"));
/* count number of leafs */
- for (i = 0; i < NB_CHARS; i++) {
+ for (i = 0; i < NB_BYTES; i++) {
if (table[i] > 0) {
nb_leafs++;
}
}
/* initialize leafs */
- for (i = 0, l = 0; i < NB_CHARS; i++) {
+ for (i = 0, l = 0; i < NB_BYTES; i++) {
if (table[i] > 0) {
leafs[l] = (leaf_t *) calloc (1, sizeof (leaf_t));
if (leafs[l] == NULL) {
}
}
-/* code structure */
-
-typedef struct {
- char code[NB_CHARS - 1 + 1];
-} code_t;
-
/* explore tree */
void explore_tree (code_t *table, leaf_t *root, char *code, int index)
{
if ((root->left == NULL) && (root->right == NULL)) {
- strcpy ((char *)(table + (int)(root->c)), code);
+ codcpy ((char *)(table + (int)(root->c)), sizeof (code_t), code);
}
else {
- strcpy (code + index, "1");
+ codcpy (code + index, sizeof (code_t), "1");
explore_tree (table, root->left, code, index + 1);
- strcpy (code + index, "0");
+ codcpy (code + index, sizeof (code_t), "0");
explore_tree (table, root->right, code, index + 1);
}
}
VERBOSE (DEBUG, PRINTF ("start creating code table\n"));
/* allocate table */
- table = (code_t *) calloc (NB_CHARS, sizeof (code_t));
+ table = (code_t *) calloc (NB_BYTES, sizeof (code_t));
if (table == NULL) {
VERBOSE (ERROR, printf ("can't allocate memory\n"));
return NULL;
int i;
printf ("Code table\n");
- for (i = 0; i < NB_CHARS; i++) {
+ for (i = 0; i < NB_BYTES; i++) {
code = (char *)(codes + i);
- if (strlen (code) == 0) {
+ if (codlen (code) == 0) {
continue;
}
printf ("0x%02x '%c': %s\n", i, ((i < 32) || (i > 127)) ? '.' : i, code);
/* encode header and code table */
-char *encode_header_table (code_t *codes, int *occ)
+byte_t *encode_header_table (code_t *codes, int *occ)
{
- unsigned char buffer[NB_CHARS * (NB_CHARS - 1) / 2 / 8 + NB_CHARS + 6] = {0};
- char bits[(NB_CHARS - 1) + 8 + 1] = {0};
+ byte_t buffer[NB_BYTES * (NB_BYTES - 1) / 2 / 8 + NB_BYTES + 6] = {0};
+ char bits[(NB_BYTES - 1) + 8 + 1] = {0};
char *code;
- unsigned char *header = buffer;
+ byte_t *header = buffer;
int i, j, length, mode;
int nb = 0;
int size = 0;
VERBOSE (DEBUG, PRINTF ("start encoding header and code table\n"));
/* mode 1 or 2 */
- for (i = 0; i < NB_CHARS; i++) {
+ for (i = 0; i < NB_BYTES; i++) {
code = (char *)(codes + i);
- if (strlen (code) > 0) {
+ if (codlen (code) > 0) {
nb++;
- size += strlen (code) * occ[i];
+ size += codlen (code) * occ[i];
}
}
- mode = (NB_CHARS < 2 * nb + 1) ? 1 : 2;
+ mode = (NB_BYTES < 2 * nb + 1) ? 1 : 2;
VERBOSE (DEBUG, PRINTF ("nb chars: %d\n", nb));
VERBOSE (DEBUG, PRINTF ("mode: %d\n", mode));
VERBOSE (DEBUG, PRINTF ("size: %d\n", size));
VERBOSE (DEBUG, PRINTF ("rem: %d\n", size % 256));
/* header */
- strcpy ((char *)header, (mode == 1) ? "MZ1 " : "MZ2 ");
+ codcpy ((char *)header, sizeof (buffer), (mode == 1) ? "MZ1 " : "MZ2 ");
header += 6;
/* size */
switch (mode) {
case 1:
- for (i = 0; i < NB_CHARS; i++) {
+ for (i = 0; i < NB_BYTES; i++) {
code = (char *)(codes + i);
- *(header++) = (unsigned char) strlen (code);
+ *(header++) = (byte_t) codlen (code);
}
break;
case 2:
- *(header++) = (unsigned char)(nb - 1);
- for (i = 0; i < NB_CHARS; i++) {
+ *(header++) = (byte_t)(nb - 1);
+ for (i = 0; i < NB_BYTES; i++) {
code = (char *)(codes + i);
- if (strlen (code) > 0) {
- *(header++) = (unsigned char)i;
- *(header++) = (unsigned char) strlen (code);
+ if (codlen (code) > 0) {
+ *(header++) = (byte_t) i;
+ *(header++) = (byte_t) codlen (code);
}
}
break;
}
/* bits */
- for (i = 0; i < NB_CHARS; i++) {
+ for (i = 0; i < NB_BYTES; i++) {
code = (char *)(codes + i);
- if (strlen (code) > 0) {
- strcat (bits, code);
- while (strlen (bits) > (8 - 1)) {
+ if (codlen (code) > 0) {
+ codcat (bits, sizeof (code_t), code);
+ while (codlen (bits) > (8 - 1)) {
for (j = 0; j < 8; j++) {
*header <<= 1;
if (bits[j] == '1') {
(*header)++;
}
}
- strcpy (bits, bits + 8);
+ codcpy (bits, sizeof (code_t), bits + 8);
header++;
}
}
}
- if (strlen (bits) > 0) {
- for (j = 0; j < (int)strlen (bits); j++) {
+ if (codlen (bits) > 0) {
+ for (j = 0; j < (int)codlen (bits); j++) {
*header <<= 1;
if (bits[j] == '1') {
(*header)++;
}
}
- for (j = (int)strlen (bits); j < 8; j++) {
+ for (j = (int)codlen (bits); j < 8; j++) {
*header <<= 1;
}
header++;
/* length */
length = (int)(header - buffer - 6);
VERBOSE (DEBUG, PRINTF ("lengh: %d %02x %02x\n", length, length >> 8, length & 0xff));
- buffer[3] = (unsigned char)(length >> 8);
- buffer[4] = (unsigned char)(length & 0xff);
- buffer[5] = (unsigned char)(size % 256);
+ buffer[3] = (byte_t)(length >> 8);
+ buffer[4] = (byte_t)(length & 0xff);
+ buffer[5] = (byte_t)(size % 256);
/* allocation */
- header = (unsigned char *) calloc (length + 6, 1);
+ header = (byte_t *) calloc (length + 6, 1);
memcpy (header, buffer, length + 6);
VERBOSE (DEBUG, PRINTF ("end encoding header and code table\n"));
- return (char *)header;
+ return header;
}
/* print header */
-void print_header (char *header)
+void print_header (byte_t *header)
{
int length, i;
- length = ((unsigned char)(header[3]) << 8) + (unsigned char)(header[4]);
+ length = (header[3] << 8) + header[4];
VERBOSE (DEBUG, PRINTF ("lengh: %d\n", length));
for (i = 0; i < length + 6; i++) {
- printf ("%02x", (unsigned char)header[i]);
+ printf ("%02x", header[i]);
}
printf ("\n");
}
/* write crompressed file */
-int write_compress (char *output, char *input, code_t *codes, char *header)
+int write_compress (char *output, char *input, code_t *codes, byte_t *header)
{
- char bufin[BUFFER_SIZE] = {0};
- char bufout[BUFFER_SIZE] = {0};
- char bits[(NB_CHARS - 1) + 8 + 1] = {0};
+ byte_t bufin[BUFFER_SIZE] = {0};
+ byte_t bufout[BUFFER_SIZE] = {0};
+ char bits[(NB_BYTES - 1) + 8 + 1] = {0};
FILE *fin, *fout;
int length = 0;
int i, j, nbread;
- char *pt;
+ byte_t *pt;
VERBOSE (DEBUG, PRINTF ("start writting compressed file\n"));
VERBOSE (INFO, printf ("file '%s' opened\n", output));
/* write header */
- length = ((unsigned char)(header[3]) << 8) + (unsigned char)(header[4]);
+ length = (header[3] << 8) + header[4];
VERBOSE (DEBUG, PRINTF ("lengh: %d\n", length));
fwrite (header, 1, length + 6, fout);
nbread = fread (bufin, 1, BUFFER_SIZE, fin);
VERBOSE (DEBUG, PRINTF ("nbread: %d\n", nbread));
for (i = 0; i < nbread; i++) {
- strcat (bits, (char *)(codes + bufin[i]));
- while (strlen (bits) > (8 - 1)) {
+ codcat (bits, sizeof (code_t), (char *)(codes + bufin[i]));
+ while (codlen (bits) > (8 - 1)) {
for (j = 0; j < 8; j++) {
*pt <<= 1;
if (bits[j] == '1') {
(*pt)++;
}
}
- strcpy (bits, bits + 8);
+ codcpy (bits, sizeof (code_t), bits + 8);
if (pt - bufout == BUFFER_SIZE - 1) {
fwrite (bufout, 1, BUFFER_SIZE, fout);
pt = bufout;
}
}
}
- VERBOSE (DEBUG, PRINTF ("lastest bits : %d\n", strlen (bits)));
- if (strlen (bits) > 0) {
- for (j = 0; j < (int)strlen (bits); j++) {
+ VERBOSE (DEBUG, PRINTF ("lastest bits : %d\n", codlen (bits)));
+ if (codlen (bits) > 0) {
+ for (j = 0; j < (int)codlen (bits); j++) {
*pt <<= 1;
if (bits[j] == '1') {
(*pt)++;
}
}
- for (j = (int)strlen (bits); j < 8; j++) {
+ for (j = (int)codlen (bits); j < 8; j++) {
*pt <<= 1;
}
pt++;
/* read header */
code_t *read_header (char *filename) {
- unsigned char buffer[NB_CHARS * (NB_CHARS - 1) / 2 / 8 + NB_CHARS + 6] = {0};
+ byte_t buffer[NB_BYTES * (NB_BYTES - 1) / 2 / 8 + NB_BYTES + 6] = {0};
code_t *table = NULL;
- unsigned char *codes = NULL;
- unsigned char cur;
- int lengths[NB_CHARS] = {0};
+ byte_t *codes = NULL;
+ byte_t cur;
+ int lengths[NB_BYTES] = {0};
FILE *fid = NULL;
int mode = 0;
size_t i, j, l, nb, size;
VERBOSE (DEBUG, PRINTF ("nb, buffer: %d 0x%02x 0x%02x\n", nb, buffer[0], buffer[1]));
if ((nb == 6) && (buffer[0] == 'M') && (buffer[1] == 'Z')) {
mode = (buffer[2] == '1') ? 1 : (buffer[2] == '2') ? 2 : 0;
- size = ((unsigned char)(buffer[3]) << 8) + (unsigned char)(buffer[4]);
+ size = (buffer[3] << 8) + buffer[4];
VERBOSE (DEBUG, PRINTF ("mode, size: %d %d\n", mode, size));
- if (size > NB_CHARS * (NB_CHARS - 1) / 2 / 8 + NB_CHARS) {
+ if (size > NB_BYTES * (NB_BYTES - 1) / 2 / 8 + NB_BYTES) {
mode = 0;
} else {
nb = fread (buffer, 1, size, fid);
}
/* analyse header */
- codes = (unsigned char *)buffer;
+ codes = buffer;
switch (mode) {
case 1:
- for (i = 0; i < NB_CHARS; i++) {
+ for (i = 0; i < NB_BYTES; i++) {
lengths[i] = *(codes++);
}
break;
}
break;
}
- VERBOSE (DEBUG, for (i = 0; i < NB_CHARS; i++) if (lengths[i]) PRINTF ("%d: %d\n", i, lengths[i]));
+ VERBOSE (DEBUG, for (i = 0; i < NB_BYTES; i++) if (lengths[i]) PRINTF ("%d: %d\n", i, lengths[i]));
/* check lengths */
- for (i = 0, l = 0; i < NB_CHARS; i++) {
+ for (i = 0, l = 0; i < NB_BYTES; i++) {
l += lengths[i];
}
if (((mode == 1) && (size - 256 != (l + 7) / 8)) ||
}
/* allocate table */
- table = (code_t *) calloc (NB_CHARS, sizeof (code_t));
+ table = (code_t *) calloc (NB_BYTES, sizeof (code_t));
if (table == NULL) {
VERBOSE (ERROR, printf ("can't allocate memory\n"));
return NULL;
/* decode code */
cur = *(codes++);
l = 8;
- for (i = 0; i < NB_CHARS; i++) {
+ for (i = 0; i < NB_BYTES; i++) {
if (lengths[i] == 0) {
continue;
}
while (lengths[i]--) {
- strcat ((char *)(table + i), ((cur & 0x80) == 0) ? "0" : "1");
+ codcat ((char *)(table + i), sizeof (code_t), ((cur & 0x80) == 0) ? "0" : "1");
l--;
cur <<= 1;
if (l == 0) {
int write_decompress (char *output, char *input, code_t *codes)
{
- char bufin[BUFFER_SIZE] = {0};
- char bufout[BUFFER_SIZE] = {0};
- unsigned char buffer[MAX(NB_CHARS * (NB_CHARS - 1) / 2 / 8 + NB_CHARS + 6, BUFFER_SIZE)] = {0};
- char bits[(NB_CHARS - 1) + 1] = {0};
+ byte_t bufin[BUFFER_SIZE] = {0};
+ byte_t bufout[BUFFER_SIZE] = {0};
+ byte_t bufhea[MAX(NB_BYTES * (NB_BYTES - 1) / 2 / 8 + NB_BYTES + 6, BUFFER_SIZE)] = {0};
+ char bits[(NB_BYTES - 1) + 1] = {0};
FILE *fin, *fout;
int i, j, k, nb, size, rem;
int is_found;
int l = 0;
- char *pt;
+ byte_t *pt;
VERBOSE (DEBUG, PRINTF ("start writing decompressed file\n"));
VERBOSE (INFO, printf ("file '%s' opened\n", input));
/* read magic number */
- nb = fread (buffer, 1, 6, fin);
+ nb = fread (bufhea, 1, 6, fin);
if (nb != 6) {
VERBOSE (ERROR, printf ("can't read file\n"));
fclose (fin);
return 1;
}
- size = ((unsigned char)(buffer[3]) << 8) + (unsigned char)(buffer[4]);
+ size = (bufhea[3] << 8) + bufhea[4];
VERBOSE (DEBUG, printf ("table size: %d\n", size));
- rem = buffer[5];
+ rem = bufhea[5];
VERBOSE (DEBUG, printf ("remainder: %d\n", rem));
- nb = fread (buffer, 1, size, fin);
+ nb = fread (bufhea, 1, size, fin);
if (nb != size) {
VERBOSE (ERROR, printf ("can't read file\n"));
fclose (fin);
VERBOSE (DEBUG, PRINTF ("nbread: %d\n", nb));
for (i = 0; i < nb; i++) {
for (j = 0; j < 8; j++) {
- strcat (bits, ((bufin[i] & 0x80) == 0) ? "0" : "1");
+ codcat (bits, sizeof (bits), ((bufin[i] & 0x80) == 0) ? "0" : "1");
bufin[i] <<= 1;
l++;
- VERBOSE (DEBUG, PRINTF ("bits: %d - %s\n", strlen (bits), bits));
+ VERBOSE (DEBUG, PRINTF ("bits: %d - %s\n", codlen (bits), bits));
/* look for correct code */
is_found = 0;
- for (k = 0; (k < NB_CHARS) && (!is_found); k++) {
- if (strcmp ((char *)(codes + k), bits) == 0) {
+ for (k = 0; (k < NB_BYTES) && (!is_found); k++) {
+ if (codcmp ((char *)(codes + k), bits) == 0) {
is_found = 1;
VERBOSE (DEBUG, PRINTF ("found: %d\n", k));
*pt= k;
leaf_t **leafs = NULL;
leaf_t *root = NULL;
code_t *codes = NULL;
- char *header = NULL;
+ byte_t *header = NULL;
int mode = COMPRESS;
int rc = 1;
}
/* clean everything */
+ fflush (stdout);
if (header) free (header);
if (codes) free (codes);
if (root) free_tree (root);