39 #include "FSBAllocator/FSBAllocator.hh"
47 const CodeType dms {std::numeric_limits<CodeType>::max()};
56 void compress(std::istream &is, std::ostream &os)
58 using KeyType = std::pair<CodeType, char>;
59 using PairType = std::pair<const KeyType, CodeType>;
64 const auto reset_dictionary = [&dictionary] {
67 const long int minc = std::numeric_limits<char>::min();
68 const long int maxc = std::numeric_limits<char>::max();
70 for (
long int c = minc; c <= maxc; ++c)
74 const CodeType dictionary_size = dictionary.size();
76 dictionary[{globals::dms,
static_cast<char> (c)}] = dictionary_size;
88 if (dictionary.size() == globals::dms)
91 if (dictionary.count({i, c}) == 0)
95 const CodeType dictionary_size = dictionary.size();
97 dictionary[{i, c}] = dictionary_size;
98 os.write(reinterpret_cast<const char *> (&i),
sizeof (
CodeType));
99 i = dictionary.at({globals::dms, c});
102 i = dictionary.at({i, c});
105 if (i != globals::dms)
106 os.write(reinterpret_cast<const char *> (&i),
sizeof (
CodeType));
116 std::vector<std::pair<CodeType, char>> dictionary;
119 const auto reset_dictionary = [&dictionary] {
121 dictionary.reserve(globals::dms);
123 const long int minc = std::numeric_limits<char>::min();
124 const long int maxc = std::numeric_limits<char>::max();
126 for (
long int c = minc; c <= maxc; ++c)
127 dictionary.push_back({globals::dms, static_cast<char> (c)});
130 const auto rebuild_string = [&dictionary](
CodeType k) ->
const std::vector<char> * {
131 static std::vector<char> s;
136 s.reserve(globals::dms);
138 while (k != globals::dms)
140 s.push_back(dictionary[k].second);
141 k = dictionary[k].first;
144 std::reverse(s.begin(), s.end());
153 while (is.read(reinterpret_cast<char *> (&k), sizeof (
CodeType)))
156 if (dictionary.size() == globals::dms)
159 if (k > dictionary.size())
160 throw std::runtime_error(
"invalid compressed code");
162 const std::vector<char> *s;
164 if (k == dictionary.size())
166 dictionary.push_back({i, rebuild_string(i)->front()});
167 s = rebuild_string(k);
171 s = rebuild_string(k);
173 if (i != globals::dms)
174 dictionary.push_back({i, s->front()});
177 os.write(&s->front(), s->size());
181 if (!is.eof() || is.gcount() != 0)
182 throw std::runtime_error(
"corrupted compressed file");
193 std::cerr <<
"\nERROR: " << s <<
'\n';
197 std::cerr <<
"\nUsage:\n";
198 std::cerr <<
"\tprogram -flag input_file output_file\n\n";
199 std::cerr <<
"Where `flag' is either `c' for compressing, or `d' for decompressing, and\n";
200 std::cerr <<
"`input_file' and `output_file' are distinct files.\n\n";
201 std::cerr <<
"Examples:\n";
202 std::cerr <<
"\tlzw_v4.exe -c license.txt license.lzw\n";
203 std::cerr <<
"\tlzw_v4.exe -d license.lzw new_license.txt\n";
206 std::cerr << std::endl;
216 int main(
int argc,
char *argv[])
231 if (std::string(argv[1]) ==
"-c")
234 if (std::string(argv[1]) ==
"-d")
235 m = Mode::Decompress;
238 print_usage(std::string(
"flag `") + argv[1] +
"' is not recognized.");
242 const std::size_t buffer_size {1024 * 1024};
245 const std::unique_ptr<char[]> input_buffer(
new char[buffer_size]);
246 const std::unique_ptr<char[]> output_buffer(
new char[buffer_size]);
248 std::ifstream input_file;
249 std::ofstream output_file;
251 input_file.rdbuf()->pubsetbuf(input_buffer.get(), buffer_size);
252 input_file.open(argv[2], std::ios_base::binary);
254 if (!input_file.is_open())
256 print_usage(std::string(
"input_file `") + argv[2] +
"' could not be opened.");
260 output_file.rdbuf()->pubsetbuf(output_buffer.get(), buffer_size);
261 output_file.open(argv[3], std::ios_base::binary);
263 if (!output_file.is_open())
265 print_usage(std::string(
"output_file `") + argv[3] +
"' could not be opened.");
271 input_file.exceptions(std::ios_base::badbit);
272 output_file.exceptions(std::ios_base::badbit | std::ios_base::failbit);
274 if (m == Mode::Compress)
277 if (m == Mode::Decompress)
280 catch (
const std::ios_base::failure &f)
282 print_usage(std::string(
"File input/output failure: ") + f.what() +
'.',
false);
285 catch (
const std::exception &e)
287 print_usage(std::string(
"Caught exception: ") + e.what() +
'.',
false);