Photon 1.0.0
Loading...
Searching...
No Matches
compress.hpp
Go to the documentation of this file.
1#include <gzip/config.hpp>
2
3// zlib
4#include <zlib.h>
5
6// std
7#include <limits>
8#include <stdexcept>
9#include <string>
10
11namespace gzip
12{
13
15 {
16 std::size_t max_;
17 int level_;
18
19 public:
20 Compressor(int level = Z_DEFAULT_COMPRESSION,
21 std::size_t max_bytes = 2000000000) // by default refuse operation if uncompressed data is > 2GB
22 : max_(max_bytes), level_(level)
23 {
24 }
25
26 template <typename InputType> void compress(InputType& output, const char* data, std::size_t size) const
27 {
28
29#ifdef DEBUG
30 // Verify if size input will fit into unsigned int, type used for zlib's avail_in
31 if (size > std::numeric_limits<unsigned int>::max())
32 {
33 throw std::runtime_error("size arg is too large to fit into unsigned int type");
34 }
35#endif
36 if (size > max_)
37 {
38 throw std::runtime_error("size may use more memory than intended when decompressing");
39 }
40
41 z_stream deflate_s;
42 deflate_s.zalloc = Z_NULL;
43 deflate_s.zfree = Z_NULL;
44 deflate_s.opaque = Z_NULL;
45 deflate_s.avail_in = 0;
46 deflate_s.next_in = Z_NULL;
47
48 // The windowBits parameter is the base two logarithm of the window size (the size of the history buffer).
49 // It should be in the range 8..15 for this version of the library.
50 // Larger values of this parameter result in better compression at the expense of memory usage.
51 // This range of values also changes the decoding type:
52 // -8 to -15 for raw deflate
53 // 8 to 15 for zlib
54 // (8 to 15) + 16 for gzip
55 // (8 to 15) + 32 to automatically detect gzip/zlib header (decompression/inflate only)
56 constexpr int window_bits = 15 + 16; // gzip with windowbits of 15
57
58 constexpr int mem_level = 8;
59 // The memory requirements for deflate are (in bytes):
60 // (1 << (window_bits+2)) + (1 << (mem_level+9))
61 // with a default value of 8 for mem_level and our window_bits of 15
62 // this is 128Kb
63
64#pragma GCC diagnostic push
65#pragma GCC diagnostic ignored "-Wold-style-cast"
66 if (deflateInit2(&deflate_s, level_, Z_DEFLATED, window_bits, mem_level, Z_DEFAULT_STRATEGY) != Z_OK)
67 {
68 throw std::runtime_error("deflate init failed");
69 }
70#pragma GCC diagnostic pop
71
72 deflate_s.next_in = reinterpret_cast<z_const Bytef*>(data);
73 deflate_s.avail_in = static_cast<unsigned int>(size);
74
75 std::size_t size_compressed = 0;
76 do
77 {
78 size_t increase = size / 2 + 1024;
79 if (output.size() < (size_compressed + increase))
80 {
81 output.resize(size_compressed + increase);
82 }
83 // There is no way we see that "increase" would not fit in an unsigned int,
84 // hence we use static cast here to avoid -Wshorten-64-to-32 error
85 deflate_s.avail_out = static_cast<unsigned int>(increase);
86 deflate_s.next_out = reinterpret_cast<Bytef*>((&output[0] + size_compressed));
87 // From http://www.zlib.net/zlib_how.html
88 // "deflate() has a return value that can indicate errors, yet we do not check it here.
89 // Why not? Well, it turns out that deflate() can do no wrong here."
90 // Basically only possible error is from deflateInit not working properly
91 deflate(&deflate_s, Z_FINISH);
92 size_compressed += (increase - deflate_s.avail_out);
93 } while (deflate_s.avail_out == 0);
94
95 deflateEnd(&deflate_s);
96 output.resize(size_compressed);
97 }
98 };
99
100 inline std::string compress(const char* data, std::size_t size, int level = Z_DEFAULT_COMPRESSION)
101 {
102 Compressor comp(level);
103 std::string output;
104 comp.compress(output, data, size);
105 return output;
106 }
107
108} // namespace gzip
Definition compress.hpp:15
void compress(InputType &output, const char *data, std::size_t size) const
Definition compress.hpp:26
Compressor(int level=Z_DEFAULT_COMPRESSION, std::size_t max_bytes=2000000000)
Definition compress.hpp:20
std::size_t max_
Definition compress.hpp:16
int level_
Definition compress.hpp:17
Definition compress.hpp:12
std::string compress(const char *data, std::size_t size, int level=Z_DEFAULT_COMPRESSION)
Definition compress.hpp:100
Definition format.h:1901
annotation output
Definition tag_strings.h:122