LZW file compressor.
More...
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <exception>
#include <fstream>
#include <ios>
#include <iostream>
#include <istream>
#include <limits>
#include <map>
#include <memory>
#include <ostream>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
Go to the source code of this file.
|
using | CodeType = std::uint16_t |
| Type used to store and retrieve codes.
|
|
|
void | compress (std::istream &is, std::ostream &os) |
| Compresses the contents of is and writes the result to os . More...
|
|
void | decompress (std::istream &is, std::ostream &os) |
| Decompresses the contents of is and writes the result to os . More...
|
|
void | print_usage (const std::string &s="", bool su=true) |
| Prints usage information and a custom error message. More...
|
|
int | main (int argc, char *argv[]) |
| Actual program entry point. More...
|
|
|
const CodeType | globals::dms {std::numeric_limits<CodeType>::max()} |
| Dictionary Maximum Size (when reached, the dictionary will be reset)
|
|
LZW file compressor.
- Author
- Julius Pettersson
- Copyright
- MIT/Expat License.
- Version
- 3
This is the C++11 implementation of a Lempel-Ziv-Welch single-file command-line compressor. It uses the simpler fixed-width code compression method. It was written with Doxygen comments.
- See Also
- http://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Welch
-
http://marknelson.us/2011/11/08/lzw-revisited/
-
http://www.cs.duke.edu/csed/curious/compression/lzw.html
-
http://warp.povusers.org/EfficientLZW/index.html
-
http://en.cppreference.com/
-
http://www.doxygen.org/
Definition in file lzw_v3.cpp.
void compress |
( |
std::istream & |
is, |
|
|
std::ostream & |
os |
|
) |
| |
Compresses the contents of is
and writes the result to os
.
- Parameters
-
[in] | is | input stream |
[out] | os | output stream |
Definition at line 53 of file lzw_v3.cpp.
Referenced by main().
55 std::map<std::pair<CodeType, char>,
CodeType> dictionary;
58 const auto reset_dictionary = [&dictionary] {
61 const long int minc = std::numeric_limits<char>::min();
62 const long int maxc = std::numeric_limits<char>::max();
64 for (
long int c = minc; c <= maxc; ++c)
68 const CodeType dictionary_size = dictionary.size();
70 dictionary[{globals::dms,
static_cast<char> (c)}] = dictionary_size;
82 if (dictionary.size() == globals::dms)
85 if (dictionary.count({i, c}) == 0)
89 const CodeType dictionary_size = dictionary.size();
91 dictionary[{i, c}] = dictionary_size;
92 os.write(reinterpret_cast<const char *> (&i),
sizeof (
CodeType));
93 i = dictionary.at({globals::dms, c});
96 i = dictionary.at({i, c});
99 if (i != globals::dms)
100 os.write(reinterpret_cast<const char *> (&i),
sizeof (
CodeType));
void decompress |
( |
std::istream & |
is, |
|
|
std::ostream & |
os |
|
) |
| |
Decompresses the contents of is
and writes the result to os
.
- Parameters
-
[in] | is | input stream |
[out] | os | output stream |
Definition at line 108 of file lzw_v3.cpp.
Referenced by main().
110 std::vector<std::pair<CodeType, char>> dictionary;
113 const auto reset_dictionary = [&dictionary] {
115 dictionary.reserve(globals::dms);
117 const long int minc = std::numeric_limits<char>::min();
118 const long int maxc = std::numeric_limits<char>::max();
120 for (
long int c = minc; c <= maxc; ++c)
121 dictionary.push_back({globals::dms, static_cast<char> (c)});
124 const auto rebuild_string = [&dictionary](
CodeType k) -> std::vector<char> {
127 while (k != globals::dms)
129 s.push_back(dictionary.at(k).second);
130 k = dictionary.at(k).first;
133 std::reverse(s.begin(), s.end());
142 while (is.read(reinterpret_cast<char *> (&k), sizeof (
CodeType)))
145 if (dictionary.size() == globals::dms)
148 if (k > dictionary.size())
149 throw std::runtime_error(
"invalid compressed code");
153 if (k == dictionary.size())
155 dictionary.push_back({i, rebuild_string(i).front()});
156 s = rebuild_string(k);
160 s = rebuild_string(k);
162 if (i != globals::dms)
163 dictionary.push_back({i, s.front()});
166 os.write(&s.front(), s.size());
170 if (!is.eof() || is.gcount() != 0)
171 throw std::runtime_error(
"corrupted compressed file");
int main |
( |
int |
argc, |
|
|
char * |
argv[] |
|
) |
| |
Actual program entry point.
- Parameters
-
| argc | number of command line arguments |
[in] | argv | array of command line arguments |
- Return values
-
EXIT_FAILURE | for failed operation |
EXIT_SUCCESS | for successful operation |
Definition at line 205 of file lzw_v3.cpp.
References compress(), decompress(), and print_usage().
220 if (std::string(argv[1]) ==
"-c")
223 if (std::string(argv[1]) ==
"-d")
224 m = Mode::Decompress;
227 print_usage(std::string(
"flag `") + argv[1] +
"' is not recognized.");
231 const std::size_t buffer_size {1024 * 1024};
234 const std::unique_ptr<char[]> input_buffer(
new char[buffer_size]);
235 const std::unique_ptr<char[]> output_buffer(
new char[buffer_size]);
237 std::ifstream input_file;
238 std::ofstream output_file;
240 input_file.rdbuf()->pubsetbuf(input_buffer.get(), buffer_size);
241 input_file.open(argv[2], std::ios_base::binary);
243 if (!input_file.is_open())
245 print_usage(std::string(
"input_file `") + argv[2] +
"' could not be opened.");
249 output_file.rdbuf()->pubsetbuf(output_buffer.get(), buffer_size);
250 output_file.open(argv[3], std::ios_base::binary);
252 if (!output_file.is_open())
254 print_usage(std::string(
"output_file `") + argv[3] +
"' could not be opened.");
260 input_file.exceptions(std::ios_base::badbit);
261 output_file.exceptions(std::ios_base::badbit | std::ios_base::failbit);
263 if (m == Mode::Compress)
266 if (m == Mode::Decompress)
269 catch (
const std::ios_base::failure &f)
271 print_usage(std::string(
"File input/output failure: ") + f.what() +
'.',
false);
274 catch (
const std::exception &e)
276 print_usage(std::string(
"Caught exception: ") + e.what() +
'.',
false);
void print_usage |
( |
const std::string & |
s = "" , |
|
|
bool |
su = true |
|
) |
| |
Prints usage information and a custom error message.
- Parameters
-
s | custom error message to be printed |
su | Show Usage information |
Definition at line 179 of file lzw_v3.cpp.
Referenced by main().
182 std::cerr <<
"\nERROR: " << s <<
'\n';
186 std::cerr <<
"\nUsage:\n";
187 std::cerr <<
"\tprogram -flag input_file output_file\n\n";
188 std::cerr <<
"Where `flag' is either `c' for compressing, or `d' for decompressing, and\n";
189 std::cerr <<
"`input_file' and `output_file' are distinct files.\n\n";
190 std::cerr <<
"Examples:\n";
191 std::cerr <<
"\tlzw_v3.exe -c license.txt license.lzw\n";
192 std::cerr <<
"\tlzw_v3.exe -d license.lzw new_license.txt\n";
195 std::cerr << std::endl;