95 const long int minc = std::numeric_limits<char>::min();
96 const long int maxc = std::numeric_limits<char>::max();
99 for (
long int c = minc; c <= maxc; ++c)
100 initials[static_cast<unsigned char> (c)] = k++;
102 vn.reserve(globals::dms);
114 const long int minc = std::numeric_limits<char>::min();
115 const long int maxc = std::numeric_limits<char>::max();
117 for (
long int c = minc; c <= maxc; ++c)
121 vn.push_back(
Node(
'\x00'));
133 if (i == globals::dms)
139 if (ci != globals::dms)
144 if (
vn[ci].left == globals::dms)
146 vn[ci].left = vn_size;
155 if (
vn[ci].right == globals::dms)
157 vn[ci].right = vn_size;
167 vn[i].first = vn_size;
180 return initials[
static_cast<unsigned char> (c)];
186 std::vector<Node>::size_type
size()
const
194 std::vector<Node>
vn;
236 write(static_cast<CodeType> (MetaCode::Eof));
240 os.put(static_cast<char> (
lo.
data));
268 if (
bits == SIZE_MAX)
269 throw std::overflow_error(
"CodeWriter::increase_bits()");
283 std::size_t remaining_bits {
bits};
288 os.put(static_cast<char> (
lo.
data));
290 remaining_bits -= CHAR_BIT -
lo.
used;
295 while (remaining_bits != 0)
296 if (remaining_bits >= CHAR_BIT)
298 os.put(static_cast<char> (k));
300 remaining_bits -= CHAR_BIT;
358 if (
bits == SIZE_MAX)
359 throw std::overflow_error(
"CodeReader::increase_bits()");
374 static const std::array<unsigned long int, 9> masks {
375 {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}
378 std::size_t remaining_bits {
bits};
379 std::size_t offset {
lo.
used};
383 remaining_bits -=
lo.
used;
387 while (remaining_bits != 0 &&
is.get(reinterpret_cast<char &> (temp)))
388 if (remaining_bits >= CHAR_BIT)
390 k |=
static_cast<CodeType> (temp) << offset;
392 remaining_bits -= CHAR_BIT;
396 k |=
static_cast<CodeType> (temp & masks[remaining_bits]) << offset;
397 lo.
used = CHAR_BIT - remaining_bits;
398 lo.
data = temp >> remaining_bits;
402 if (k == static_cast<CodeType> (MetaCode::Eof))
438 while ((n >>= 1) != 0)
460 if (ed.
size() == globals::dms)
484 if (i != globals::dms)
495 std::vector<std::pair<CodeType, char>> dictionary;
498 const auto reset_dictionary = [&dictionary] {
500 dictionary.reserve(globals::dms);
502 const long int minc = std::numeric_limits<char>::min();
503 const long int maxc = std::numeric_limits<char>::max();
505 for (
long int c = minc; c <= maxc; ++c)
506 dictionary.push_back({globals::dms, static_cast<char> (c)});
509 dictionary.push_back({0,
'\x00'});
512 const auto rebuild_string = [&dictionary](
CodeType k) ->
const std::vector<char> * {
513 static std::vector<char> s;
518 s.reserve(globals::dms);
520 while (k != globals::dms)
522 s.push_back(dictionary[k].second);
523 k = dictionary[k].first;
526 std::reverse(s.begin(), s.end());
539 if (dictionary.size() == globals::dms)
551 if (k > dictionary.size())
552 throw std::runtime_error(
"invalid compressed code");
554 const std::vector<char> *s;
556 if (k == dictionary.size())
558 dictionary.push_back({i, rebuild_string(i)->front()});
559 s = rebuild_string(k);
563 s = rebuild_string(k);
565 if (i != globals::dms)
566 dictionary.push_back({i, s->front()});
569 os.write(&s->front(), s->size());
574 throw std::runtime_error(
"corrupted compressed file");
585 std::cerr <<
"\nERROR: " << s <<
'\n';
589 std::cerr <<
"\nUsage:\n";
590 std::cerr <<
"\tprogram -flag input_file output_file\n\n";
591 std::cerr <<
"Where `flag' is either `c' for compressing, or `d' for decompressing, and\n";
592 std::cerr <<
"`input_file' and `output_file' are distinct files.\n\n";
593 std::cerr <<
"Examples:\n";
594 std::cerr <<
"\tlzw_v6.exe -c license.txt license.lzw\n";
595 std::cerr <<
"\tlzw_v6.exe -d license.lzw new_license.txt\n";
598 std::cerr << std::endl;
608 int main(
int argc,
char *argv[])
623 if (std::string(argv[1]) ==
"-c")
626 if (std::string(argv[1]) ==
"-d")
627 m = Mode::Decompress;
630 print_usage(std::string(
"flag `") + argv[1] +
"' is not recognized.");
634 const std::size_t buffer_size {1024 * 1024};
637 const std::unique_ptr<char[]> input_buffer(
new char[buffer_size]);
638 const std::unique_ptr<char[]> output_buffer(
new char[buffer_size]);
640 std::ifstream input_file;
641 std::ofstream output_file;
643 input_file.rdbuf()->pubsetbuf(input_buffer.get(), buffer_size);
644 input_file.open(argv[2], std::ios_base::binary);
646 if (!input_file.is_open())
648 print_usage(std::string(
"input_file `") + argv[2] +
"' could not be opened.");
652 output_file.rdbuf()->pubsetbuf(output_buffer.get(), buffer_size);
653 output_file.open(argv[3], std::ios_base::binary);
655 if (!output_file.is_open())
657 print_usage(std::string(
"output_file `") + argv[3] +
"' could not be opened.");
663 input_file.exceptions(std::ios_base::badbit);
664 output_file.exceptions(std::ios_base::badbit | std::ios_base::failbit);
666 if (m == Mode::Compress)
669 if (m == Mode::Decompress)
672 catch (
const std::ios_base::failure &f)
674 print_usage(std::string(
"File input/output failure: ") + f.what() +
'.',
false);
677 catch (
const std::exception &e)
679 print_usage(std::string(
"Caught exception: ") + e.what() +
'.',
false);