Commit 940bd3a2 authored by John M. (Jack) Maxfield's avatar John M. (Jack) Maxfield
Browse files

myzip

parent a2f22dc5
No related merge requests found
Showing with 242 additions and 4607 deletions
+242 -4607
......@@ -3,3 +3,5 @@
/inflate
/huffman
/myunzip
/myzip
/lz77
\ No newline at end of file
......@@ -19,5 +19,13 @@ test_inflate : src/inflate/inflate.c tests/inflate_test.cpp
g++ -I include src/inflate/inflate.c tests/inflate_test.cpp -o test_inflate -l gtest
./test_inflate
lz77 : include/bitwriter.h include/hashmap.h include/lz77.h src/lz77/bitwriter.c src/lz77/hashmap.c src/lz77/lz77.c src/lz77/main.c
cc -I include src/lz77/lz77.c src/lz77/hashmap.c src/lz77/bitwriter.c src/lz77/main.c -o lz77
myzip : include/bitwriter.h include/hashmap.h include/lz77.h src/lz77/bitwriter.c src/lz77/hashmap.c src/lz77/lz77.c src/myzip/myzip.c
cc -I include src/lz77/lz77.c src/lz77/hashmap.c src/lz77/bitwriter.c src/myzip/myzip.c -o myzip
clean :
rm myzip0 myunzip0 huffman inflate test_inflate myunzip
......@@ -23,6 +23,7 @@ void BitWriter_write_alpha(BitWriter *bw, uint32_t byte);
void BitWriter_write_length(BitWriter *bw, uint32_t length);
void BitWriter_write_distance(BitWriter *bw, uint32_t dist);
void BitWriter_write_bin(BitWriter *bw, uint32_t bits, int number_to_write);
size_t BitWriter_bytes_written(BitWriter *bw);
#endif
......
......@@ -8,10 +8,11 @@ struct Hashmap;
typedef struct Hashmap Hashmap;
Hashmap *Hashmap_init();
void Hashmap_free(Hashmap *hm);
void Hashmap_free(Hashmap *hm, void (*free_value)(void *));
void Hashmap_update(Hashmap *hm, uint32_t key, void *value);
bool Hashmap_contains(Hashmap *hm, uint32_t key);
void *Hashmap_get(Hashmap *hm, uint32_t key);
void Hashmap_delete(Hashmap *hm, uint32_t key);
#endif
\ No newline at end of file
#ifndef __LZ77_H__
#define __LZ77_H__
#include "hashmap.h"
#include "bitwriter.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
size_t write_lz77_stream(FILE *input_file, FILE *output_file);
#endif
\ No newline at end of file
This diff is collapsed.
......@@ -11,6 +11,7 @@ struct BitWriter
FILE *file;
uint8_t byte;
int mod;
size_t bytes_written;
};
BitWriter *BitWriter_init(FILE *file)
......@@ -20,6 +21,7 @@ BitWriter *BitWriter_init(FILE *file)
bw->file = file;
bw->byte = 0;
bw->mod = 0;
bw->bytes_written = 0;
return bw;
}
......@@ -37,6 +39,7 @@ void BitWriter_write_bit(BitWriter *bw, bool bit)
fwrite(&bw->byte, 1, 1, bw->file);
bw->byte = 0;
bw->mod = 0;
bw->bytes_written += 1;
}
}
......@@ -147,3 +150,8 @@ void BitWriter_write_distance(BitWriter *bw, uint32_t dist)
}
}
}
size_t BitWriter_bytes_written(BitWriter *bw)
{
return bw->bytes_written;
}
\ No newline at end of file
......@@ -51,11 +51,15 @@ void ListHashmap_init(ListHashmap *lh)
lh->head = NULL;
}
void ListHashmap_deinit(ListHashmap *lh)
void ListHashmap_deinit(ListHashmap *lh, void (*free_value)(void *))
{
LinkedListNode *pos = lh->head;
while (pos)
{
if (free_value)
{
free_value(pos->value);
}
LinkedListNode *next = pos->next;
LinkedListNode_free(pos);
pos = next;
......@@ -176,11 +180,11 @@ Hashmap *Hashmap_init()
return hm;
}
void Hashmap_free(Hashmap *hm)
void Hashmap_free(Hashmap *hm, void (*free_value)(void *))
{
for (size_t i = 0; i < BINS; i++)
{
ListHashmap_deinit(&hm->bins[i]);
ListHashmap_deinit(&hm->bins[i], free_value);
}
free(hm);
}
......
#include "hashmap.h"
#include "bitwriter.h"
#include "lz77.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -84,6 +85,7 @@ void IntQueue_pop(IntQueue *queue)
queue->head = queue->head->next;
if (!queue->head) queue->tail = NULL;
queue->size--;
free(oldHead);
}
bool IntQueue_empty(IntQueue *queue)
......@@ -91,35 +93,11 @@ bool IntQueue_empty(IntQueue *queue)
return queue->size == 0;
}
int main(int argc, char *argv[])
size_t write_lz77_stream(FILE *input_file, FILE *output_file)
{
/* this is bad */
if (argc != 2)
{
printf("Usage: %s <input file>\n", argv[0]);
exit(1);
}
char *input_file_name = argv[1];
char *output_file_name = malloc(sizeof(char) *
(strlen(input_file_name) + strlen(".deflate") + 1));
sprintf(output_file_name, "%s.deflate", input_file_name);
FILE *input_file = fopen(input_file_name, "r");
FILE *output_file = fopen(output_file_name, "w");
free(output_file_name);
BitWriter *bitWriter = BitWriter_init(output_file);
Hashmap *hashMap = Hashmap_init();
BitWriter_write_bit(bitWriter, 1); /* BFINAL */
BitWriter_write_bit(bitWriter, 1); /* BTYPE */
BitWriter_write_bit(bitWriter, 0);
IntQueue *seenTripleQueue = IntQueue_init();
/* read the input file to a buffer */
/* TODO: use mmap? */
fseek(input_file, 0, SEEK_END);
......@@ -129,8 +107,13 @@ int main(int argc, char *argv[])
assert(inp);
fread(inp, input_file_length, 1, input_file);
size_t cursor = 0;
/* write block headers */
BitWriter_write_bit(bitWriter, 1); /* BFINAL */
BitWriter_write_bit(bitWriter, 1); /* BTYPE */
BitWriter_write_bit(bitWriter, 0);
/* main lz77 loop */
size_t cursor = 0;
while (cursor < input_file_length)
{
size_t old_cursor = cursor;
......@@ -201,6 +184,8 @@ int main(int argc, char *argv[])
}
/* add new triple to hash map */
if (input_file_length - old_cursor > 3)
{
uint32_t new_triple = inp[old_cursor] + (inp[old_cursor + 1] << 8) + (inp[old_cursor + 2] << 16);
if (Hashmap_contains(hashMap, new_triple))
{
......@@ -216,14 +201,22 @@ int main(int argc, char *argv[])
}
}
}
}
/* end of block */
BitWriter_write_bin(bitWriter, 0, 7); /* EOB */
/* cleanup */
BitWriter_flush(bitWriter);
Hashmap_free(hashMap);
size_t compressed_size = BitWriter_bytes_written(bitWriter);
BitWriter_free(bitWriter);
fclose(input_file);
fclose(output_file);
Hashmap_free(hashMap, (void (*)(void *)) IntQueue_free);
free(inp);
return compressed_size;
}
#include "hashmap.h"
#include "bitwriter.h"
#include "lz77.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
/* this is bad */
if (argc != 2)
{
printf("Usage: %s <input file>\n", argv[0]);
exit(1);
}
char *input_file_name = argv[1];
char *output_file_name = malloc(sizeof(char) *
(strlen(input_file_name) + strlen(".deflate") + 1));
sprintf(output_file_name, "%s.deflate", input_file_name);
FILE *input_file = fopen(input_file_name, "r");
FILE *output_file = fopen(output_file_name, "w");
free(output_file_name);
size_t compressed_size = write_lz77_stream(input_file, output_file);
fclose(input_file);
fclose(output_file);
}
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "lz77.h"
const uint32_t BUFFER_SIZE = 1024;
int write_u8(FILE *file, const uint8_t v)
{
return fwrite(&v, sizeof(uint8_t), 1, file);
}
int write_u16(FILE *file, const uint16_t v)
{
return fwrite(&v, sizeof(uint16_t), 1, file);
}
int write_u32(FILE *file, const uint32_t v)
{
return fwrite(&v, sizeof(uint32_t), 1, file);
}
int copy_file_to_file(FILE *input, FILE *output, uint32_t bytes)
{
uint8_t buffer[BUFFER_SIZE];
uint32_t bytes_written = 0;
for (uint32_t start = 0; start < bytes; start += BUFFER_SIZE)
{
uint32_t remaining_bytes = bytes - start;
uint32_t copy_this_iter = (remaining_bytes < BUFFER_SIZE) ?
remaining_bytes : BUFFER_SIZE;
fread(buffer, 1, copy_this_iter, input);
bytes_written += fwrite(buffer, 1, copy_this_iter, output);
}
return bytes_written;
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
fprintf(stderr, "Usage: %s <output zip filename> <input file filename>\n", argv[0]);
return 1;
}
const char *output_file_name = argv[1];
const char *input_file_name = argv[2];
FILE *input_file = fopen(input_file_name, "r");
FILE *output_file = fopen(output_file_name, "w");
if (input_file == NULL)
{
fprintf(stderr, "Could not open \"%s\"\n", input_file_name);
return 1;
}
if (output_file == NULL)
{
fprintf(stderr, "Could not open \"%s\"\n", output_file_name);
return 2;
}
fseek(input_file, 0, SEEK_END);
uint32_t input_file_size = ftell(input_file);
fseek(input_file, 0, SEEK_SET);
/* (1) LOCAL FILE RECORD */
write_u32(output_file, 0x04034b50); /* local file signature */
write_u16(output_file, 20); /* extract version */
write_u16(output_file, 0); /* general purpose flag */
write_u16(output_file, 0); /* compression method */
write_u16(output_file, 0); /* last mod file time */
write_u16(output_file, 0); /* last mod file date */
write_u32(output_file, 0xDEADBEEF); /* crc */
size_t compressed_size_loc = ftell(input_file);
write_u32(output_file, 0); /* compressed file size */
write_u32(output_file, input_file_size); /* uncompressed file size */
write_u16(output_file, strlen(input_file_name)); /* file name len */
write_u16(output_file, 0); /* extra field length */
fputs(input_file_name, output_file); /* file name */
/* extra field */
/* copy input file to output */
uint32_t compressed_size = write_lz77_stream(input_file, output_file);
size_t central_directory_start = ftell(input_file); /* save location */
fseek(input_file, compressed_size_loc, SEEK_SET); /* move back */
write_u32(output_file, compressed_size); /* write compressed size */
fseek(input_file, central_directory_start, SEEK_SET); /* return to writing */
/* (2) CENTRAL DIRECTORY RECORD */
write_u32(output_file, 0x02014b50); /* central directory signature */
write_u8 (output_file, 30); /* specification version */
write_u8 (output_file, 65); /* made by */
write_u16(output_file, 20); /* extract version */
write_u16(output_file, 0); /* general purpose bit flag */
write_u16(output_file, 0); /* compression method */
write_u16(output_file, 0); /* last mod file time */
write_u16(output_file, 0); /* last mod file date */
write_u32(output_file, 0xdeadbeef); /* crc */
write_u32(output_file, compressed_size); /* compressed file size */
write_u32(output_file, input_file_size); /* uncompressed file size */
write_u16(output_file, strlen(input_file_name)); /* file name length */
write_u16(output_file, 0); /* extra field length */
write_u16(output_file, 0); /* file comment length */
write_u16(output_file, 0); /* disk number start */
write_u16(output_file, 1); /* internal file attributes */
write_u32(output_file, 1); /* external file attributes */
write_u32(output_file, 0); /* offset of local header */
fputs(input_file_name, output_file); /* file name */
/* extra field */
/* file comment */
uint32_t end_record_start = ftell(output_file);
/* (3) END OF CENTRAL DIRECTORY RECORD */
write_u32(output_file, 0x06054b50); /* end of central dir signature */
write_u16(output_file, 0); /* number of this disk */
write_u16(output_file, 0); /* number of the start disk */
write_u16(output_file, 1); /* total number of entries on this disk */
write_u16(output_file, 1); /* total number of entries */
write_u32(output_file, end_record_start - central_directory_start); /* size of central directory record */
write_u32(output_file, central_directory_start); /* offset of start of central directory */
write_u16(output_file, 0); /* .zip file comment length */
/* .zip file comment */
fclose(input_file);
fclose(output_file);
return 0;
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment