Skip to main content
Code Review

Return to Question

Grammar!
Source Link

Here is a simple decompressor in Cdecompression implementation. I'd very much appreciate any advice or comments about the structure/logic of the program, style of the code, or reusability of the features. I'm a real novice and really eager to learn from people here, so fire away!

Here is a simple decompressor in C. I'd very much appreciate any advice or comments about the structure/logic of the program, style of the code, or reusability of the features. I'm a real novice and really eager to learn from people here, so fire away!

Here is a simple decompression implementation. I'd very much appreciate any advice or comments about the structure/logic of the program, style of the code, or reusability of the features. I'm a real novice and really eager to learn from people here, so fire away!

Edits as per moderator rolfl's advice
Source Link

LZW decompressor in C Decompression implementation

lzw.h:

/**
 * lzw.h
 * Function declarations for lzwlempel ziv-welch decompression algorithm.
 */
#ifndef LZW_H
#define LZW_H
#include <stdio.h>
#include <stdlib.h>
/**
 * Frees all blocks between 'from' and 'to' (inclusive) in the dict.
 */
void free_dict (unsigned char* dict[], int from, int to);
/**
 * Enters the first 256 ASCII values into dict.
 */
void load_dict_defaults (unsigned char* dict[]);
/**
 * Reads 12 bits from source and returns them as an int.
 */
int fread_twelve(FILE* source);
/**
 * LZW decompression of source to dest.
 * Returns 0 if successful, a positive integer otherwise.
 */
int decompress (FILE* source, FILE* dest);
#endif // LZW_H

decompress.c:


/**
 * decompress.c
 * Implementation of LZWlempel ziv-welch decompression algorithm using 12-bit fixed-width compression format.
 *
 * Usage: decompress
 */
#include "lzw.h"
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char* argv[])
{ 
 // check for correct number of args
 if (argc != 3)
 {
 printf("Usage: decompress source destination\n");
 return 1;
 }
 
 // open compressed file
 FILE* source = fopen(argv[1], "r");
 if (source == NULL)
 {
 printf("Error: cannot open %s\n", argv[1]);
 return 1;
 }
 
 // open destination file
 FILE* dest = fopen(argv[2], "w");
 if (dest == NULL)
 {
 printf("Error: cannot open %s\n", argv[2]);
 return 1;
 }
 
 // decompress
 if (decompress(source, dest) == 1)
 {
 printf("Decompression failed\n");
 fclose(source);
 fclose(dest);
 return 1;
 }
 else
 {
 fclose(source);
 fclose(dest);
 return 0;
 }
}

lzw.c:


/**
 * lzw.c
 * Implementation of LZWlempel ziv-welch decompression algorithm using 12-bit fixed-width compression format.
 *
 */
#include "lzw.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
unsigned char* dictionary[4096];
/**
 * Enters the first 256 ASCII values into dict.
 */
void load_dict_defaults (unsigned char* dict[])
{
 unsigned char* temp;
 unsigned char c = 0;
 for (int i = 0; i < 256; i++)
 {
 temp = calloc(2, sizeof(unsigned char));
 temp[0] = c++;
 dict[i] = temp;
 }
}
/**
 * Frees all blocks between 'from' and 'to' (inclusive) in the dict.
 */
void free_dict (unsigned char* dict[], int from, int to)
{
 for (int i = from; i <= to; i++)
 {
 free(dict[i]);
 }
}
/**
 * Reads 12 bits from source and returns them as an int.
 * Returns 0 on an error or EOF.
 */
int fread_twelve(FILE* source)
{
 int value;
 static bool left = true;
 
 unsigned char buf[2];
 
 if (left)
 {
 // if left, read two bytes and calculate int
 if (fread(buf, 1, 2, source) != 2) {return 0;}
 if (feof(source)) // we're at a 16-bit end! 
 {
 value = (buf[0] << 8) | buf[1];
 }
 else
 {
 value = (buf[0] << 4) | (buf[1] >> 4);
 }
 left = false;
 }
 else
 {
 // if right, rewind source by one byte, read two bytes and calculate int
 fseek(source, -1, SEEK_CUR);
 if (fread(buf, 1, 2, source) != 2) {return 0;}
 value = ((buf[0] & 0x0F) << 8) | buf[1];
 left = true;
 }
 return value;
}
/**
 * LZW decompression of source to dest.
 * Returns 0 if successful, a positive integer otherwise.
 */
int decompress (FILE* source, FILE* dest)
{
 load_dict_defaults(dictionary);
 
 int dictPos = 256;
 
 int prevCode, currCode;
 unsigned char* prevString, *currString;
 
 // read in the first character
 currCode = fread_twelve(source);
 if (dictionary[currCode] == NULL)
 {
 return 1;
 }
 size_t size;
 size = strlen((char*)dictionary[currCode]);
 currString = calloc(size + 2, sizeof(char)); //+2 for upcoming char and null
 if (currString == NULL)
 {
 return 1;
 }
 memcpy(currString, dictionary[currCode], size+1);
 fprintf(dest, "%s", currString);
 prevCode = currCode;
 prevString = currString;
 
 // read in the rest of the characters
 while ( (currCode = fread_twelve(source)) && currCode )
 { 
 if (dictionary[currCode] == NULL)
 {
 return 1;
 }
 size = strlen((char*)dictionary[currCode]);
 currString = calloc(size + 2, sizeof(char)); //+2 for upcoming char and null
 if (currString == NULL)
 {
 return 1;
 }
 memcpy(currString, dictionary[currCode], size+1);
 fprintf(dest, "%s", currString);
 
 if (currCode > dictPos)
 {
 dictionary[dictPos++] = (unsigned char*) strncat((char*)prevString, (char*)prevString, 1);
 }
 else
 {
 dictionary[dictPos++] = (unsigned char*) strncat((char*)prevString, (char*)currString, 1);
 }
 
 // restart dict if full.
 if (dictPos >= 4096)
 {
 free_dict(dictionary, 256, 4096);
 dictPos = 256;
 }
 
 prevCode = currCode;
 prevString = currString;
 }
 
 free_dict(dictionary, 0, dictPos-1);
 
 return 0;
}

Link to the followup question: LZW decompressor in C (II)Decompression implementation II

LZW decompressor in C

lzw.h:

/**
 * lzw.h
 * Function declarations for lzw decompression algorithm.
 */
#ifndef LZW_H
#define LZW_H
#include <stdio.h>
#include <stdlib.h>
/**
 * Frees all blocks between 'from' and 'to' (inclusive) in the dict.
 */
void free_dict (unsigned char* dict[], int from, int to);
/**
 * Enters the first 256 ASCII values into dict.
 */
void load_dict_defaults (unsigned char* dict[]);
/**
 * Reads 12 bits from source and returns them as an int.
 */
int fread_twelve(FILE* source);
/**
 * LZW decompression of source to dest.
 * Returns 0 if successful, a positive integer otherwise.
 */
int decompress (FILE* source, FILE* dest);
#endif // LZW_H

decompress.c:

/**
 * decompress.c
 * Implementation of LZW decompression algorithm using 12-bit fixed-width compression format.
 *
 * Usage: decompress
 */
#include "lzw.h"
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char* argv[])
{ 
 // check for correct number of args
 if (argc != 3)
 {
 printf("Usage: decompress source destination\n");
 return 1;
 }
 
 // open compressed file
 FILE* source = fopen(argv[1], "r");
 if (source == NULL)
 {
 printf("Error: cannot open %s\n", argv[1]);
 return 1;
 }
 
 // open destination file
 FILE* dest = fopen(argv[2], "w");
 if (dest == NULL)
 {
 printf("Error: cannot open %s\n", argv[2]);
 return 1;
 }
 
 // decompress
 if (decompress(source, dest) == 1)
 {
 printf("Decompression failed\n");
 fclose(source);
 fclose(dest);
 return 1;
 }
 else
 {
 fclose(source);
 fclose(dest);
 return 0;
 }
}

lzw.c:

/**
 * lzw.c
 * Implementation of LZW decompression algorithm using 12-bit fixed-width compression format.
 *
 */
#include "lzw.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
unsigned char* dictionary[4096];
/**
 * Enters the first 256 ASCII values into dict.
 */
void load_dict_defaults (unsigned char* dict[])
{
 unsigned char* temp;
 unsigned char c = 0;
 for (int i = 0; i < 256; i++)
 {
 temp = calloc(2, sizeof(unsigned char));
 temp[0] = c++;
 dict[i] = temp;
 }
}
/**
 * Frees all blocks between 'from' and 'to' (inclusive) in the dict.
 */
void free_dict (unsigned char* dict[], int from, int to)
{
 for (int i = from; i <= to; i++)
 {
 free(dict[i]);
 }
}
/**
 * Reads 12 bits from source and returns them as an int.
 * Returns 0 on an error or EOF.
 */
int fread_twelve(FILE* source)
{
 int value;
 static bool left = true;
 
 unsigned char buf[2];
 
 if (left)
 {
 // if left, read two bytes and calculate int
 if (fread(buf, 1, 2, source) != 2) {return 0;}
 if (feof(source)) // we're at a 16-bit end! 
 {
 value = (buf[0] << 8) | buf[1];
 }
 else
 {
 value = (buf[0] << 4) | (buf[1] >> 4);
 }
 left = false;
 }
 else
 {
 // if right, rewind source by one byte, read two bytes and calculate int
 fseek(source, -1, SEEK_CUR);
 if (fread(buf, 1, 2, source) != 2) {return 0;}
 value = ((buf[0] & 0x0F) << 8) | buf[1];
 left = true;
 }
 return value;
}
/**
 * LZW decompression of source to dest.
 * Returns 0 if successful, a positive integer otherwise.
 */
int decompress (FILE* source, FILE* dest)
{
 load_dict_defaults(dictionary);
 
 int dictPos = 256;
 
 int prevCode, currCode;
 unsigned char* prevString, *currString;
 
 // read in the first character
 currCode = fread_twelve(source);
 if (dictionary[currCode] == NULL)
 {
 return 1;
 }
 size_t size;
 size = strlen((char*)dictionary[currCode]);
 currString = calloc(size + 2, sizeof(char)); //+2 for upcoming char and null
 if (currString == NULL)
 {
 return 1;
 }
 memcpy(currString, dictionary[currCode], size+1);
 fprintf(dest, "%s", currString);
 prevCode = currCode;
 prevString = currString;
 
 // read in the rest of the characters
 while ( (currCode = fread_twelve(source)) && currCode )
 { 
 if (dictionary[currCode] == NULL)
 {
 return 1;
 }
 size = strlen((char*)dictionary[currCode]);
 currString = calloc(size + 2, sizeof(char)); //+2 for upcoming char and null
 if (currString == NULL)
 {
 return 1;
 }
 memcpy(currString, dictionary[currCode], size+1);
 fprintf(dest, "%s", currString);
 
 if (currCode > dictPos)
 {
 dictionary[dictPos++] = (unsigned char*) strncat((char*)prevString, (char*)prevString, 1);
 }
 else
 {
 dictionary[dictPos++] = (unsigned char*) strncat((char*)prevString, (char*)currString, 1);
 }
 
 // restart dict if full.
 if (dictPos >= 4096)
 {
 free_dict(dictionary, 256, 4096);
 dictPos = 256;
 }
 
 prevCode = currCode;
 prevString = currString;
 }
 
 free_dict(dictionary, 0, dictPos-1);
 
 return 0;
}

Link to the followup question: LZW decompressor in C (II)

Decompression implementation

:

/**
 * lzw.h
 * Function declarations for lempel ziv-welch decompression algorithm.
 */
#ifndef LZW_H
#define LZW_H
#include <stdio.h>
#include <stdlib.h>
/**
 * Frees all blocks between 'from' and 'to' (inclusive) in the dict.
 */
void free_dict (unsigned char* dict[], int from, int to);
/**
 * Enters the first 256 ASCII values into dict.
 */
void load_dict_defaults (unsigned char* dict[]);
/**
 * Reads 12 bits from source and returns them as an int.
 */
int fread_twelve(FILE* source);
/**
 * LZW decompression of source to dest.
 * Returns 0 if successful, a positive integer otherwise.
 */
int decompress (FILE* source, FILE* dest);
#endif // LZW_H

/**
 * decompress.c
 * Implementation of lempel ziv-welch decompression algorithm using 12-bit fixed-width compression format.
 *
 * Usage: decompress
 */
#include "lzw.h"
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char* argv[])
{ 
 // check for correct number of args
 if (argc != 3)
 {
 printf("Usage: decompress source destination\n");
 return 1;
 }
 
 // open compressed file
 FILE* source = fopen(argv[1], "r");
 if (source == NULL)
 {
 printf("Error: cannot open %s\n", argv[1]);
 return 1;
 }
 
 // open destination file
 FILE* dest = fopen(argv[2], "w");
 if (dest == NULL)
 {
 printf("Error: cannot open %s\n", argv[2]);
 return 1;
 }
 
 // decompress
 if (decompress(source, dest) == 1)
 {
 printf("Decompression failed\n");
 fclose(source);
 fclose(dest);
 return 1;
 }
 else
 {
 fclose(source);
 fclose(dest);
 return 0;
 }
}

/**
 * lzw.c
 * Implementation of lempel ziv-welch decompression algorithm using 12-bit fixed-width compression format.
 *
 */
#include "lzw.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
unsigned char* dictionary[4096];
/**
 * Enters the first 256 ASCII values into dict.
 */
void load_dict_defaults (unsigned char* dict[])
{
 unsigned char* temp;
 unsigned char c = 0;
 for (int i = 0; i < 256; i++)
 {
 temp = calloc(2, sizeof(unsigned char));
 temp[0] = c++;
 dict[i] = temp;
 }
}
/**
 * Frees all blocks between 'from' and 'to' (inclusive) in the dict.
 */
void free_dict (unsigned char* dict[], int from, int to)
{
 for (int i = from; i <= to; i++)
 {
 free(dict[i]);
 }
}
/**
 * Reads 12 bits from source and returns them as an int.
 * Returns 0 on an error or EOF.
 */
int fread_twelve(FILE* source)
{
 int value;
 static bool left = true;
 
 unsigned char buf[2];
 
 if (left)
 {
 // if left, read two bytes and calculate int
 if (fread(buf, 1, 2, source) != 2) {return 0;}
 if (feof(source)) // we're at a 16-bit end! 
 {
 value = (buf[0] << 8) | buf[1];
 }
 else
 {
 value = (buf[0] << 4) | (buf[1] >> 4);
 }
 left = false;
 }
 else
 {
 // if right, rewind source by one byte, read two bytes and calculate int
 fseek(source, -1, SEEK_CUR);
 if (fread(buf, 1, 2, source) != 2) {return 0;}
 value = ((buf[0] & 0x0F) << 8) | buf[1];
 left = true;
 }
 return value;
}
/**
 * LZW decompression of source to dest.
 * Returns 0 if successful, a positive integer otherwise.
 */
int decompress (FILE* source, FILE* dest)
{
 load_dict_defaults(dictionary);
 
 int dictPos = 256;
 
 int prevCode, currCode;
 unsigned char* prevString, *currString;
 
 // read in the first character
 currCode = fread_twelve(source);
 if (dictionary[currCode] == NULL)
 {
 return 1;
 }
 size_t size;
 size = strlen((char*)dictionary[currCode]);
 currString = calloc(size + 2, sizeof(char)); //+2 for upcoming char and null
 if (currString == NULL)
 {
 return 1;
 }
 memcpy(currString, dictionary[currCode], size+1);
 fprintf(dest, "%s", currString);
 prevCode = currCode;
 prevString = currString;
 
 // read in the rest of the characters
 while ( (currCode = fread_twelve(source)) && currCode )
 { 
 if (dictionary[currCode] == NULL)
 {
 return 1;
 }
 size = strlen((char*)dictionary[currCode]);
 currString = calloc(size + 2, sizeof(char)); //+2 for upcoming char and null
 if (currString == NULL)
 {
 return 1;
 }
 memcpy(currString, dictionary[currCode], size+1);
 fprintf(dest, "%s", currString);
 
 if (currCode > dictPos)
 {
 dictionary[dictPos++] = (unsigned char*) strncat((char*)prevString, (char*)prevString, 1);
 }
 else
 {
 dictionary[dictPos++] = (unsigned char*) strncat((char*)prevString, (char*)currString, 1);
 }
 
 // restart dict if full.
 if (dictPos >= 4096)
 {
 free_dict(dictionary, 256, 4096);
 dictPos = 256;
 }
 
 prevCode = currCode;
 prevString = currString;
 }
 
 free_dict(dictionary, 0, dictPos-1);
 
 return 0;
}

Link to the followup question: Decompression implementation II

Notice removed Content dispute by Community Bot
Post Unlocked by Community Bot
Post Locked by 200_success
Notice added Content dispute by 200_success
Rollback to Revision 6
Source Link
200_success
  • 145.6k
  • 22
  • 190
  • 479

Delete me please LZW decompressor in C

................................................. Here is a simple decompressor in C. I'd very much appreciate any advice or comments about the structure/logic of the program, style of the code, or reusability of the features. I'm a real novice and really eager to learn from people here, so fire away!

lzw.h:

/**
 * lzw.h
 * Function declarations for lzw decompression algorithm.
 */
#ifndef LZW_H
#define LZW_H
#include <stdio.h>
#include <stdlib.h>
/**
 * Frees all blocks between 'from' and 'to' (inclusive) in the dict.
 */
void free_dict (unsigned char* dict[], int from, int to);
/**
 * Enters the first 256 ASCII values into dict.
 */
void load_dict_defaults (unsigned char* dict[]);
/**
 * Reads 12 bits from source and returns them as an int.
 */
int fread_twelve(FILE* source);
/**
 * LZW decompression of source to dest.
 * Returns 0 if successful, a positive integer otherwise.
 */
int decompress (FILE* source, FILE* dest);
#endif // LZW_H

decompress.c:

/**
 * decompress.c
 * Implementation of LZW decompression algorithm using 12-bit fixed-width compression format.
 *
 * Usage: decompress
 */
#include "lzw.h"
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char* argv[])
{ 
 // check for correct number of args
 if (argc != 3)
 {
 printf("Usage: decompress source destination\n");
 return 1;
 }
 
 // open compressed file
 FILE* source = fopen(argv[1], "r");
 if (source == NULL)
 {
 printf("Error: cannot open %s\n", argv[1]);
 return 1;
 }
 
 // open destination file
 FILE* dest = fopen(argv[2], "w");
 if (dest == NULL)
 {
 printf("Error: cannot open %s\n", argv[2]);
 return 1;
 }
 
 // decompress
 if (decompress(source, dest) == 1)
 {
 printf("Decompression failed\n");
 fclose(source);
 fclose(dest);
 return 1;
 }
 else
 {
 fclose(source);
 fclose(dest);
 return 0;
 }
}

lzw.c:

/**
 * lzw.c
 * Implementation of LZW decompression algorithm using 12-bit fixed-width compression format.
 *
 */
#include "lzw.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
unsigned char* dictionary[4096];
/**
 * Enters the first 256 ASCII values into dict.
 */
void load_dict_defaults (unsigned char* dict[])
{
 unsigned char* temp;
 unsigned char c = 0;
 for (int i = 0; i < 256; i++)
 {
 temp = calloc(2, sizeof(unsigned char));
 temp[0] = c++;
 dict[i] = temp;
 }
}
/**
 * Frees all blocks between 'from' and 'to' (inclusive) in the dict.
 */
void free_dict (unsigned char* dict[], int from, int to)
{
 for (int i = from; i <= to; i++)
 {
 free(dict[i]);
 }
}
/**
 * Reads 12 bits from source and returns them as an int.
 * Returns 0 on an error or EOF.
 */
int fread_twelve(FILE* source)
{
 int value;
 static bool left = true;
 
 unsigned char buf[2];
 
 if (left)
 {
 // if left, read two bytes and calculate int
 if (fread(buf, 1, 2, source) != 2) {return 0;}
 if (feof(source)) // we're at a 16-bit end! 
 {
 value = (buf[0] << 8) | buf[1];
 }
 else
 {
 value = (buf[0] << 4) | (buf[1] >> 4);
 }
 left = false;
 }
 else
 {
 // if right, rewind source by one byte, read two bytes and calculate int
 fseek(source, -1, SEEK_CUR);
 if (fread(buf, 1, 2, source) != 2) {return 0;}
 value = ((buf[0] & 0x0F) << 8) | buf[1];
 left = true;
 }
 return value;
}
/**
 * LZW decompression of source to dest.
 * Returns 0 if successful, a positive integer otherwise.
 */
int decompress (FILE* source, FILE* dest)
{
 load_dict_defaults(dictionary);
 
 int dictPos = 256;
 
 int prevCode, currCode;
 unsigned char* prevString, *currString;
 
 // read in the first character
 currCode = fread_twelve(source);
 if (dictionary[currCode] == NULL)
 {
 return 1;
 }
 size_t size;
 size = strlen((char*)dictionary[currCode]);
 currString = calloc(size + 2, sizeof(char)); //+2 for upcoming char and null
 if (currString == NULL)
 {
 return 1;
 }
 memcpy(currString, dictionary[currCode], size+1);
 fprintf(dest, "%s", currString);
 prevCode = currCode;
 prevString = currString;
 
 // read in the rest of the characters
 while ( (currCode = fread_twelve(source)) && currCode )
 { 
 if (dictionary[currCode] == NULL)
 {
 return 1;
 }
 size = strlen((char*)dictionary[currCode]);
 currString = calloc(size + 2, sizeof(char)); //+2 for upcoming char and null
 if (currString == NULL)
 {
 return 1;
 }
 memcpy(currString, dictionary[currCode], size+1);
 fprintf(dest, "%s", currString);
 
 if (currCode > dictPos)
 {
 dictionary[dictPos++] = (unsigned char*) strncat((char*)prevString, (char*)prevString, 1);
 }
 else
 {
 dictionary[dictPos++] = (unsigned char*) strncat((char*)prevString, (char*)currString, 1);
 }
 
 // restart dict if full.
 if (dictPos >= 4096)
 {
 free_dict(dictionary, 256, 4096);
 dictPos = 256;
 }
 
 prevCode = currCode;
 prevString = currString;
 }
 
 free_dict(dictionary, 0, dictPos-1);
 
 return 0;
}

Link to the followup question: LZW decompressor in C (II)

Delete me please

...................................................

LZW decompressor in C

Here is a simple decompressor in C. I'd very much appreciate any advice or comments about the structure/logic of the program, style of the code, or reusability of the features. I'm a real novice and really eager to learn from people here, so fire away!

lzw.h:

/**
 * lzw.h
 * Function declarations for lzw decompression algorithm.
 */
#ifndef LZW_H
#define LZW_H
#include <stdio.h>
#include <stdlib.h>
/**
 * Frees all blocks between 'from' and 'to' (inclusive) in the dict.
 */
void free_dict (unsigned char* dict[], int from, int to);
/**
 * Enters the first 256 ASCII values into dict.
 */
void load_dict_defaults (unsigned char* dict[]);
/**
 * Reads 12 bits from source and returns them as an int.
 */
int fread_twelve(FILE* source);
/**
 * LZW decompression of source to dest.
 * Returns 0 if successful, a positive integer otherwise.
 */
int decompress (FILE* source, FILE* dest);
#endif // LZW_H

decompress.c:

/**
 * decompress.c
 * Implementation of LZW decompression algorithm using 12-bit fixed-width compression format.
 *
 * Usage: decompress
 */
#include "lzw.h"
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char* argv[])
{ 
 // check for correct number of args
 if (argc != 3)
 {
 printf("Usage: decompress source destination\n");
 return 1;
 }
 
 // open compressed file
 FILE* source = fopen(argv[1], "r");
 if (source == NULL)
 {
 printf("Error: cannot open %s\n", argv[1]);
 return 1;
 }
 
 // open destination file
 FILE* dest = fopen(argv[2], "w");
 if (dest == NULL)
 {
 printf("Error: cannot open %s\n", argv[2]);
 return 1;
 }
 
 // decompress
 if (decompress(source, dest) == 1)
 {
 printf("Decompression failed\n");
 fclose(source);
 fclose(dest);
 return 1;
 }
 else
 {
 fclose(source);
 fclose(dest);
 return 0;
 }
}

lzw.c:

/**
 * lzw.c
 * Implementation of LZW decompression algorithm using 12-bit fixed-width compression format.
 *
 */
#include "lzw.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
unsigned char* dictionary[4096];
/**
 * Enters the first 256 ASCII values into dict.
 */
void load_dict_defaults (unsigned char* dict[])
{
 unsigned char* temp;
 unsigned char c = 0;
 for (int i = 0; i < 256; i++)
 {
 temp = calloc(2, sizeof(unsigned char));
 temp[0] = c++;
 dict[i] = temp;
 }
}
/**
 * Frees all blocks between 'from' and 'to' (inclusive) in the dict.
 */
void free_dict (unsigned char* dict[], int from, int to)
{
 for (int i = from; i <= to; i++)
 {
 free(dict[i]);
 }
}
/**
 * Reads 12 bits from source and returns them as an int.
 * Returns 0 on an error or EOF.
 */
int fread_twelve(FILE* source)
{
 int value;
 static bool left = true;
 
 unsigned char buf[2];
 
 if (left)
 {
 // if left, read two bytes and calculate int
 if (fread(buf, 1, 2, source) != 2) {return 0;}
 if (feof(source)) // we're at a 16-bit end! 
 {
 value = (buf[0] << 8) | buf[1];
 }
 else
 {
 value = (buf[0] << 4) | (buf[1] >> 4);
 }
 left = false;
 }
 else
 {
 // if right, rewind source by one byte, read two bytes and calculate int
 fseek(source, -1, SEEK_CUR);
 if (fread(buf, 1, 2, source) != 2) {return 0;}
 value = ((buf[0] & 0x0F) << 8) | buf[1];
 left = true;
 }
 return value;
}
/**
 * LZW decompression of source to dest.
 * Returns 0 if successful, a positive integer otherwise.
 */
int decompress (FILE* source, FILE* dest)
{
 load_dict_defaults(dictionary);
 
 int dictPos = 256;
 
 int prevCode, currCode;
 unsigned char* prevString, *currString;
 
 // read in the first character
 currCode = fread_twelve(source);
 if (dictionary[currCode] == NULL)
 {
 return 1;
 }
 size_t size;
 size = strlen((char*)dictionary[currCode]);
 currString = calloc(size + 2, sizeof(char)); //+2 for upcoming char and null
 if (currString == NULL)
 {
 return 1;
 }
 memcpy(currString, dictionary[currCode], size+1);
 fprintf(dest, "%s", currString);
 prevCode = currCode;
 prevString = currString;
 
 // read in the rest of the characters
 while ( (currCode = fread_twelve(source)) && currCode )
 { 
 if (dictionary[currCode] == NULL)
 {
 return 1;
 }
 size = strlen((char*)dictionary[currCode]);
 currString = calloc(size + 2, sizeof(char)); //+2 for upcoming char and null
 if (currString == NULL)
 {
 return 1;
 }
 memcpy(currString, dictionary[currCode], size+1);
 fprintf(dest, "%s", currString);
 
 if (currCode > dictPos)
 {
 dictionary[dictPos++] = (unsigned char*) strncat((char*)prevString, (char*)prevString, 1);
 }
 else
 {
 dictionary[dictPos++] = (unsigned char*) strncat((char*)prevString, (char*)currString, 1);
 }
 
 // restart dict if full.
 if (dictPos >= 4096)
 {
 free_dict(dictionary, 256, 4096);
 dictPos = 256;
 }
 
 prevCode = currCode;
 prevString = currString;
 }
 
 free_dict(dictionary, 0, dictPos-1);
 
 return 0;
}

Link to the followup question: LZW decompressor in C (II)

deleted 6090 characters in body; edited tags; edited title
Source Link
Loading
replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Source Link
Loading
Added link to the follow-up question including the improvements suggested.
Source Link
glampert
  • 17.3k
  • 4
  • 31
  • 89
Loading
Tweeted twitter.com/#!/StackCodeReview/status/625899491980410880
edited tags
Link
glampert
  • 17.3k
  • 4
  • 31
  • 89
Loading
error in code
Source Link
Loading
deleted 26 characters in body; edited title
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238
Loading
Source Link
Loading
lang-c

AltStyle によって変換されたページ (->オリジナル) /