1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
/* A struct for writing to files as
streams of individual bits */
typedef struct __bit_writer
{
FILE *file;
uint8_t byte;
int mod;
} bit_writer;
bit_writer *bit_writer_init(FILE *file)
{
bit_writer *bw = malloc(sizeof(bit_writer));
assert(bw);
bw->file = file;
bw->byte = 0;
bw->mod = 0;
return bw;
}
void bit_writer_free(bit_writer *bw)
{
free(bw);
}
void bit_writer_write_bit(bit_writer *bw, bool bit)
{
bw->byte |= (bit > 0) << (bw->mod++);
if (bw->mod == 8)
{
fwrite(&bw->byte, 1, 1, bw->file);
bw->byte = 0;
bw->mod = 0;
}
}
void bit_writer_flush(bit_writer *bw)
{
while (bw->mod != 0) bit_writer_write_bit(bw, 0);
}
void write_byte(bit_writer *bw, uint8_t byte)
{
if (byte <= 143) /* 8 bit encoding */
{
uint32_t to_encode = 0x30 + (uint32_t) byte;
for (int b = 8 - 1; b >= 0; b--)
bit_writer_write_bit(bw, to_encode & (1 << b));
} else /* 9 bit encoding */
{
uint32_t to_encode = 0x100 + (uint32_t) byte;
for (int b = 9 - 1; b >= 0; b--)
{
// bool to_write = () != 0;
// printf("Writing %d\n", to_write);
bit_writer_write_bit(bw, to_encode & (1 << b));
}
}
}
int main(int argc, char *argv[])
{
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);
bit_writer *bw = bit_writer_init(output_file);
bit_writer_write_bit(bw, 1); /* BFINAL */
bit_writer_write_bit(bw, 1); /* BTYPE */
bit_writer_write_bit(bw, 0);
// write_byte(bw, 144);
char c;
while (fread(&c, 1, 1, input_file))
{
// printf("Writing %d\n", (int) c);
write_byte(bw, c);
}
for (int i = 0; i < 7; i++)
bit_writer_write_bit(bw, 0);
bit_writer_flush(bw);
bit_writer_free(bw);
fclose(output_file);
fclose(input_file);
return 0;
}