source: testjes/testcompressie.cpp

Last change on this file was 10, checked in by willem, 11 years ago

willem

File size: 3.8 KB
Line 
1#include <string>
2#include <stdexcept>
3#include <iostream>
4#include <iomanip>
5#include <sstream>
6
7#include <string.h>
8
9#include <zlib.h>
10
11/** Compress a STL string using zlib with given compression level and return
12  * the binary data. */
13std::string compress_string(const std::string& str,
14                            int compressionlevel = Z_BEST_COMPRESSION)
15{
16    z_stream zs;                        // z_stream is zlib's control structure
17    memset(&zs, 0, sizeof(zs));
18
19    if (deflateInit(&zs, compressionlevel) != Z_OK)
20        throw(std::runtime_error("deflateInit failed while compressing."));
21
22    zs.next_in = (Bytef*)str.data();
23    zs.avail_in = str.size();           // set the z_stream's input
24
25    int ret;
26    char outbuffer[32768];
27    std::string outstring;
28
29    // retrieve the compressed bytes blockwise
30    do {
31        zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
32        zs.avail_out = sizeof(outbuffer);
33
34        ret = deflate(&zs, Z_FINISH);
35
36        if (outstring.size() < zs.total_out) {
37            // append the block to the output string
38            outstring.append(outbuffer,
39                             zs.total_out - outstring.size());
40        }
41    } while (ret == Z_OK);
42
43    deflateEnd(&zs);
44
45    if (ret != Z_STREAM_END) {          // an error occurred that was not EOF
46        std::ostringstream oss;
47        oss << "Exception during zlib compression: (" << ret << ") " << zs.msg;
48        throw(std::runtime_error(oss.str()));
49    }
50
51    return outstring;
52}
53
54/** Decompress an STL string using zlib and return the original data. */
55std::string decompress_string(const std::string& str)
56{
57    z_stream zs;                        // z_stream is zlib's control structure
58    memset(&zs, 0, sizeof(zs));
59
60    if (inflateInit(&zs) != Z_OK)
61        throw(std::runtime_error("inflateInit failed while decompressing."));
62
63    zs.next_in = (Bytef*)str.data();
64    zs.avail_in = str.size();
65
66    int ret;
67    char outbuffer[32768];
68    std::string outstring;
69
70    // get the decompressed bytes blockwise using repeated calls to inflate
71    do {
72        zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
73        zs.avail_out = sizeof(outbuffer);
74
75        ret = inflate(&zs, 0);
76
77        if (outstring.size() < zs.total_out) {
78            outstring.append(outbuffer,
79                             zs.total_out - outstring.size());
80        }
81
82    } while (ret == Z_OK);
83
84    inflateEnd(&zs);
85
86    if (ret != Z_STREAM_END) {          // an error occurred that was not EOF
87        std::ostringstream oss;
88        oss << "Exception during zlib decompression: (" << ret << ") "
89            << zs.msg;
90        throw(std::runtime_error(oss.str()));
91    }
92
93    return outstring;
94}
95
96/** Small dumb tool (de)compressing cin to cout. It holds all input in memory,
97  * so don't use it for huge files. */
98int main(int argc, char* argv[])
99{
100    std::string allinput;
101
102    while (std::cin.good())     // read all input from cin
103    {
104        char inbuffer[32768];
105        std::cin.read(inbuffer, sizeof(inbuffer));
106        allinput.append(inbuffer, std::cin.gcount());
107    }
108
109    if (argc >= 2 && strcmp(argv[1], "-d") == 0)
110    {
111        std::string cstr = decompress_string( allinput );
112
113        std::cerr << "Inflated data: "
114                  << allinput.size() << " -> " << cstr.size()
115                  << " (" << std::setprecision(1) << std::fixed
116                  << ( ((float)cstr.size() / (float)allinput.size() - 1.0) * 100.0 )
117                  << "% increase).\n";
118
119        std::cout << cstr;
120    }
121    else
122    {
123        std::string cstr = compress_string( allinput );
124
125        std::cerr << "Deflated data: "
126                  << allinput.size() << " -> " << cstr.size()
127                  << " (" << std::setprecision(1) << std::fixed
128                  << ( (1.0 - (float)cstr.size() / (float)allinput.size()) * 100.0)
129                  << "% saved).\n";
130
131        std::cout << cstr;
132    }
133}
Note: See TracBrowser for help on using the repository browser.