46 const CodeType dms {std::numeric_limits<CodeType>::max()};
82 const long int minc = std::numeric_limits<char>::min();
83 const long int maxc = std::numeric_limits<char>::max();
86 for (
long int c = minc; c <= maxc; ++c)
87 initials[static_cast<unsigned char> (c)] = k++;
89 vn.reserve(globals::dms);
101 const long int minc = std::numeric_limits<char>::min();
102 const long int maxc = std::numeric_limits<char>::max();
104 for (
long int c = minc; c <= maxc; ++c)
118 if (
vn.size() == globals::dms)
121 if (i == globals::dms)
127 if (ci != globals::dms)
132 if (
vn[ci].left == globals::dms)
134 vn[ci].left = vn_size;
143 if (
vn[ci].right == globals::dms)
145 vn[ci].right = vn_size;
155 vn[i].first = vn_size;
168 return initials[
static_cast<unsigned char> (c)];
174 std::vector<Node>
vn;
197 os.write(reinterpret_cast<const char *> (&temp),
sizeof (
CodeType));
202 if (i != globals::dms)
203 os.write(reinterpret_cast<const char *> (&i),
sizeof (
CodeType));
213 std::vector<std::pair<CodeType, char>> dictionary;
216 const auto reset_dictionary = [&dictionary] {
218 dictionary.reserve(globals::dms);
220 const long int minc = std::numeric_limits<char>::min();
221 const long int maxc = std::numeric_limits<char>::max();
223 for (
long int c = minc; c <= maxc; ++c)
224 dictionary.push_back({globals::dms, static_cast<char> (c)});
227 const auto rebuild_string = [&dictionary](
CodeType k) ->
const std::vector<char> * {
228 static std::vector<char> s;
233 s.reserve(globals::dms);
235 while (k != globals::dms)
237 s.push_back(dictionary[k].second);
238 k = dictionary[k].first;
241 std::reverse(s.begin(), s.end());
250 while (is.read(reinterpret_cast<char *> (&k), sizeof (
CodeType)))
253 if (dictionary.size() == globals::dms)
256 if (k > dictionary.size())
257 throw std::runtime_error(
"invalid compressed code");
259 const std::vector<char> *s;
261 if (k == dictionary.size())
263 dictionary.push_back({i, rebuild_string(i)->front()});
264 s = rebuild_string(k);
268 s = rebuild_string(k);
270 if (i != globals::dms)
271 dictionary.push_back({i, s->front()});
274 os.write(&s->front(), s->size());
278 if (!is.eof() || is.gcount() != 0)
279 throw std::runtime_error(
"corrupted compressed file");
290 std::cerr <<
"\nERROR: " << s <<
'\n';
294 std::cerr <<
"\nUsage:\n";
295 std::cerr <<
"\tprogram -flag input_file output_file\n\n";
296 std::cerr <<
"Where `flag' is either `c' for compressing, or `d' for decompressing, and\n";
297 std::cerr <<
"`input_file' and `output_file' are distinct files.\n\n";
298 std::cerr <<
"Examples:\n";
299 std::cerr <<
"\tlzw_v5.exe -c license.txt license.lzw\n";
300 std::cerr <<
"\tlzw_v5.exe -d license.lzw new_license.txt\n";
303 std::cerr << std::endl;
313 int main(
int argc,
char *argv[])
328 if (std::string(argv[1]) ==
"-c")
331 if (std::string(argv[1]) ==
"-d")
332 m = Mode::Decompress;
335 print_usage(std::string(
"flag `") + argv[1] +
"' is not recognized.");
339 const std::size_t buffer_size {1024 * 1024};
342 const std::unique_ptr<char[]> input_buffer(
new char[buffer_size]);
343 const std::unique_ptr<char[]> output_buffer(
new char[buffer_size]);
345 std::ifstream input_file;
346 std::ofstream output_file;
348 input_file.rdbuf()->pubsetbuf(input_buffer.get(), buffer_size);
349 input_file.open(argv[2], std::ios_base::binary);
351 if (!input_file.is_open())
353 print_usage(std::string(
"input_file `") + argv[2] +
"' could not be opened.");
357 output_file.rdbuf()->pubsetbuf(output_buffer.get(), buffer_size);
358 output_file.open(argv[3], std::ios_base::binary);
360 if (!output_file.is_open())
362 print_usage(std::string(
"output_file `") + argv[3] +
"' could not be opened.");
368 input_file.exceptions(std::ios_base::badbit);
369 output_file.exceptions(std::ios_base::badbit | std::ios_base::failbit);
371 if (m == Mode::Compress)
374 if (m == Mode::Decompress)
377 catch (
const std::ios_base::failure &f)
379 print_usage(std::string(
"File input/output failure: ") + f.what() +
'.',
false);
382 catch (
const std::exception &e)
384 print_usage(std::string(
"Caught exception: ") + e.what() +
'.',
false);