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 "zlib.h"
5#include <stdexcept>
6#include <vector>
7#include "Reader.hpp"
8
15namespace byteme {
16
22class ZlibBufferReader : public Reader {
23private:
27 struct ZStream {
28 ZStream(int mode) {
29 /* allocate inflate state */
30 strm.zalloc = Z_NULL;
31 strm.zfree = Z_NULL;
32 strm.opaque = Z_NULL;
33 strm.avail_in = 0;
34 strm.next_in = Z_NULL;
35
36 /* See:
37 * https://stackoverflow.com/questions/1838699/how-can-i-decompress-a-gzip-stream-with-zlib
38 * https://stackoverflow.com/questions/29003909/why-is-a-different-zlib-window-bits-value-required-for-extraction-compared-with
39 */
40 int ret = 0;
41 if (mode == 0) { // DEFLATE
42 ret = inflateInit2(&strm, -MAX_WBITS);
43 } else if (mode == 1) { // Zlib
44 ret = inflateInit2(&strm, MAX_WBITS);
45 } else if (mode == 2) { // Gzip
46 ret = inflateInit2(&strm, 16 + MAX_WBITS);
47 } else if (mode == 3) { // Gzip/Zlib auto-detected
48 ret = inflateInit2(&strm, 32 + MAX_WBITS);
49 } else {
50 throw std::runtime_error("mode must be 0 (DEFLATE), 1 (Zlib), 2 (Gzip) or 3 (automatic)");
51 }
52
53 if (ret != Z_OK) {
54 throw 1;
55 }
56 }
57
58 ~ZStream() {
59 inflateEnd(&strm);
60 return;
61 }
62
63 public:
64 // Delete the remaining constructors.
65 ZStream(const ZStream&) = delete;
66 ZStream(ZStream&&) = delete;
67 ZStream& operator=(const ZStream&) = delete;
68 ZStream& operator=(ZStream&&) = delete;
69
70 public:
71 z_stream strm;
72 };
77public:
85 ZlibBufferReader(const unsigned char* buffer, size_t length, int mode = 3, size_t buffer_size = 65536) : my_zstr(mode), my_buffer(buffer_size) {
86 my_zstr.strm.avail_in = length;
87 my_zstr.strm.next_in = const_cast<unsigned char*>(buffer); // cast is purely for C compatibility.
88 }
89
90public:
91 bool load() {
92 /* This function is stolen from the loop in 'inf()' at
93 * http://www.zlib.net/zpipe.c, with some shuffling of code to make it
94 * a bit more C++-like.
95 */
96
97 if (!my_okay) {
98 return false;
99 }
100
101 // Not entirely sure why we need to check for this, but
102 // https://zlib.net/zpipe.c does it, and so will we; because not doing
103 // so seems to occasionally result in infinite loops.
104 if (my_zstr.strm.avail_in == 0) {
105 return false;
106 }
107
108 my_zstr.strm.avail_out = my_buffer.size();
109 my_zstr.strm.next_out = my_buffer.data();
110 int ret = inflate(&(my_zstr.strm), Z_NO_FLUSH);
111
112 switch (ret) {
113 case Z_STREAM_ERROR:
114 case Z_NEED_DICT:
115 case Z_DATA_ERROR:
116 case Z_MEM_ERROR:
117 throw std::runtime_error("zlib error");
118 case Z_STREAM_END:
119 my_okay = false;
120 break;
121 }
122
123 my_read = my_buffer.size() - my_zstr.strm.avail_out;
124 return true;
125 }
126
127 const unsigned char* buffer() const {
128 return my_buffer.data();
129 }
130
131 size_t available() const {
132 return my_read;
133 }
134
135private:
136 ZStream my_zstr;
137 std::vector<unsigned char> my_buffer;
138 size_t my_read = 0;
139 bool my_okay = true;
140};
141
142}
143
144#endif
Read an input source.
Virtual class for reading bytes from a source.
Definition Reader.hpp:15
Read and decompress bytes from a Zlib-compressed buffer.
Definition ZlibBufferReader.hpp:22
size_t available() const
Definition ZlibBufferReader.hpp:131
ZlibBufferReader(const unsigned char *buffer, size_t length, int mode=3, size_t buffer_size=65536)
Definition ZlibBufferReader.hpp:85
bool load()
Definition ZlibBufferReader.hpp:91
const unsigned char * buffer() const
Definition ZlibBufferReader.hpp:127
Simple byte readers and writers.