-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.cpp
189 lines (163 loc) · 4.34 KB
/
main.cpp
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <hash_map>
#include "dictionary.h"
using namespace std;
void displayHelp(void);
void decodeFile(const string& inFile, const string& outFile);
void encodeFile(const string& inFile, string& outFile);
int findStr(const string& value, hash_map<string, int>& dictionary);
void writeKey(int key, size_t dictionary_size, size_t& starting_bit, vector<bool>& output);
void writeToFile(string& outputFile, const vector<bool>& output, const size_t ending_bit);
void showData(vector<bool>& output, size_t end_idx);
int main(int nArgs, const char** cmdLine)
{
string args[4];
for (int i = 0; i < 4; i++)
args[i] = cmdLine[i];
if (args[1] == "-e" || args[1] == "/e")
{
if (args[3] != "")
encodeFile(args[2], args[3]);
else
cout << "Error: you must specify an output file name!\n" << endl;
}
else if (args[1] == "-d" || args[1] == "/d")
decodeFile(args[2], args[3]);
else
displayHelp();
return 0;
}
void displayHelp(void)
{
cout << "This program sucks!" << endl;
}
void decodeFile(const string& inFile, const string& outFile)
{
}
void encodeFile(const string& inputFile, string& outputFile)
{
// Populate data with file contents
ifstream file(inputFile, ios::in | ios::binary);
if (file.is_open())
{
vector<char> data;
char c;
while(file.good())
{
file.read(&c, 1);
data.push_back(c);
}
file.close();
Dictionary dictionary;
int dict_idx = 0;
for (unsigned char c = 0; dict_idx < 256; c++, dict_idx++)
{
string key;
key = c;
dictionary[key] = c;
}
// Create an empty output bool vector with size = 16 * data.size
// eg 8 bit data encoded at up to 16 bits per code
vector<bool> output(data.size()*16, false);
// Populate output using lzw encoding scheme!
string sub_str = "";
string str_next = "";
int old_key, new_key;
size_t starting_bit = 0;
// Black Magic Below!!!
// Tommy wrote this shit on 10/27 @ 10:55 pm
// Modified slightly by Stew on 11/3 @ 1:45 pm
for (vector<char>::iterator i = data.begin(); i+1 != data.end();)
{
sub_str = *i;
str_next = sub_str + *(++i);
old_key = findStr(sub_str, dictionary);
while((new_key = findStr(str_next, dictionary)) >= 0 && i+1 != data.end())
{
old_key = new_key;
sub_str = str_next;
str_next = sub_str + *(++i);
}
// Don't swap these two
writeKey(old_key, dictionary.size(), starting_bit, output);
dictionary[str_next] = dictionary.size();
}
cout << "Dictionary size: " << dictionary.size();
writeToFile(outputFile, output, starting_bit); // starting_bit is actually being used as ending_bit
}
else
{
cout << "Error, could not open file: " << inputFile << endl;
return;
}
}
int findStr(const string& value, hash_map<string, int>& dictionary)
{
auto it = dictionary.find(value);
if (it == dictionary.end())
return -1;
else
return it->second;
}
void writeKey(int key, size_t dictionary_size, size_t& starting_bit, vector<bool>& output)
{
unsigned int u_key = (unsigned int) key;
// Hacky log base 2 TROLOLO
// input 31 gives 5, 32 gives 6
unsigned int key_bit_length = 1;
while (dictionary_size >>= 1)
key_bit_length++;
// Write key to output!
for (unsigned int i = 0; i < key_bit_length; i++)
{
if ((u_key >> (key_bit_length - i - 1)) & 1)
{
output[starting_bit + i].flip();
}
}
starting_bit += key_bit_length;
}
void writeToFile(string& outputFile, const vector<bool>& output, const size_t ending_bit)
{
// Add file extension
outputFile += ".lzw";
// Open file in binary mode
ofstream file(outputFile, ios::out | ios::binary);
if (file.is_open())
{
// Convert chunks of the output vector into chars, and then write those to file
for (size_t i = 0; i < ending_bit; i += 8)
{
unsigned char outByte = 0;
for (size_t j = 0; j < 8; j++)
{
if (i + j < ending_bit) // output[i+j] could "theoretically" fail
{
unsigned char temp = output[i+j];
temp <<= 7-j; // 8-j-1
outByte |= temp;
}
}
file.write((char*)&outByte,1);
}
// Be a good boy and close the file
file.close();
}
else
cout << "Could not write compressed data to file: " << outputFile << endl;
return;
}
void showData(vector<bool>& output, size_t end_idx)
{
for (vector<bool>::iterator i = output.begin(); i < end_idx+output.begin(); i++)
{
if (*i)
cout << 1;
else
cout << 0;
}
cout << endl;
}