byteme
C++ wrappers for buffered inputs
Loading...
Searching...
No Matches
ZlibBufferReader.hpp
Go to the documentation of this file.
1#ifndef BYTEME_ZLIB_BUFFER_READER_HPP
2#define BYTEME_ZLIB_BUFFER_READER_HPP
3
4#include <stdexcept>
5#include <vector>
6#include <cstddef>
7
8#include "zlib.h"
9
10#include "Reader.hpp"
11#include "check_buffer_size.hpp"
12
19namespace byteme {
20
29 int mode = 3;
30
35 std::size_t buffer_size = 65536;
36};
37
43class ZlibBufferReader final : public Reader {
44private:
48 struct ZStream {
49 ZStream(int mode) {
50 /* allocate inflate state */
51 strm.zalloc = Z_NULL;
52 strm.zfree = Z_NULL;
53 strm.opaque = Z_NULL;
54 strm.avail_in = 0;
55 strm.next_in = Z_NULL;
56
57 /* See:
58 * https://stackoverflow.com/questions/1838699/how-can-i-decompress-a-gzip-stream-with-zlib
59 * https://stackoverflow.com/questions/29003909/why-is-a-different-zlib-window-bits-value-required-for-extraction-compared-with
60 */
61 int ret = 0;
62 if (mode == 0) { // DEFLATE
63 ret = inflateInit2(&strm, -MAX_WBITS);
64 } else if (mode == 1) { // Zlib
65 ret = inflateInit2(&strm, MAX_WBITS);
66 } else if (mode == 2) { // Gzip
67 ret = inflateInit2(&strm, 16 + MAX_WBITS);
68 } else if (mode == 3) { // Gzip/Zlib auto-detected
69 ret = inflateInit2(&strm, 32 + MAX_WBITS);
70 } else {
71 throw std::runtime_error("mode must be 0 (DEFLATE), 1 (Zlib), 2 (Gzip) or 3 (automatic)");
72 }
73
74 if (ret != Z_OK) {
75 throw 1;
76 }
77 }
78
79 ~ZStream() {
80 inflateEnd(&strm);
81 return;
82 }
83
84 public:
85 // Delete the remaining constructors.
86 ZStream(const ZStream&) = delete;
87 ZStream(ZStream&&) = delete;
88 ZStream& operator=(const ZStream&) = delete;
89 ZStream& operator=(ZStream&&) = delete;
90
91 public:
92 z_stream strm;
93 };
98public:
104 ZlibBufferReader(const unsigned char* buffer, std::size_t length, const ZlibBufferReaderOptions& options) :
105 my_zstr(options.mode),
106 my_buffer(
107 check_buffer_size<decltype(decltype(ZStream::strm)::avail_out)>(
108 check_buffer_size(options.buffer_size)
109 )
110 )
111 {
112 my_zstr.strm.avail_in = length;
113 my_zstr.strm.next_in = const_cast<unsigned char*>(buffer); // cast is purely for C compatibility.
114 }
115
116public:
117 bool load() {
118 /* This function is stolen from the loop in 'inf()' at
119 * http://www.zlib.net/zpipe.c, with some shuffling of code to make it
120 * a bit more C++-like.
121 */
122
123 if (!my_okay) {
124 return false;
125 }
126
127 // Not entirely sure why we need to check for this, but
128 // https://zlib.net/zpipe.c does it, and so will we; because not doing
129 // so seems to occasionally result in infinite loops.
130 if (my_zstr.strm.avail_in == 0) {
131 return false;
132 }
133
134 my_zstr.strm.avail_out = my_buffer.size();
135 my_zstr.strm.next_out = my_buffer.data();
136 int ret = inflate(&(my_zstr.strm), Z_NO_FLUSH);
137
138 switch (ret) {
139 case Z_STREAM_ERROR:
140 case Z_NEED_DICT:
141 case Z_DATA_ERROR:
142 case Z_MEM_ERROR:
143 throw std::runtime_error("zlib error");
144 case Z_STREAM_END:
145 my_okay = false;
146 break;
147 }
148
149 my_read = my_buffer.size() - my_zstr.strm.avail_out;
150 return true;
151 }
152
153 const unsigned char* buffer() const {
154 return my_buffer.data();
155 }
156
157 std::size_t available() const {
158 return my_read;
159 }
160
161private:
162 ZStream my_zstr;
163 std::vector<unsigned char> my_buffer;
164 std::size_t my_read = 0;
165 bool my_okay = true;
166};
167
168}
169
170#endif
Read an input source.
Virtual class for reading bytes from a source.
Definition Reader.hpp:17
Read and decompress bytes from a Zlib-compressed buffer.
Definition ZlibBufferReader.hpp:43
ZlibBufferReader(const unsigned char *buffer, std::size_t length, const ZlibBufferReaderOptions &options)
Definition ZlibBufferReader.hpp:104
std::size_t available() const
Definition ZlibBufferReader.hpp:157
bool load()
Definition ZlibBufferReader.hpp:117
const unsigned char * buffer() const
Definition ZlibBufferReader.hpp:153
Simple byte readers and writers.
Options for the ZlibBufferReader constructor.
Definition ZlibBufferReader.hpp:24
int mode
Definition ZlibBufferReader.hpp:29
std::size_t buffer_size
Definition ZlibBufferReader.hpp:35