Line | Branch | Exec | Source |
---|---|---|---|
1 | // | ||
2 | // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) | ||
3 | // | ||
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
6 | // | ||
7 | // Official repository: https://github.com/cppalliance/http_proto | ||
8 | // | ||
9 | |||
10 | #ifndef BOOST_HTTP_PROTO_SERVICE_IMPL_ZLIB_SERVICE_IPP | ||
11 | #define BOOST_HTTP_PROTO_SERVICE_IMPL_ZLIB_SERVICE_IPP | ||
12 | |||
13 | #include <boost/http_proto/service/zlib_service.hpp> | ||
14 | #include <boost/system/result.hpp> | ||
15 | #include "zlib.h" | ||
16 | |||
17 | namespace boost { | ||
18 | namespace http_proto { | ||
19 | namespace zlib { | ||
20 | namespace detail { | ||
21 | |||
22 | /* | ||
23 | DEFLATE Compressed Data Format Specification version 1.3 | ||
24 | https://www.rfc-editor.org/rfc/rfc1951 | ||
25 | */ | ||
26 | |||
27 | //------------------------------------------------ | ||
28 | |||
29 | enum class error | ||
30 | { | ||
31 | ok = 0, | ||
32 | stream_end = 1, | ||
33 | need_dict = 2, | ||
34 | errno_ = -1, | ||
35 | stream_err = -2, | ||
36 | data_err = -3, | ||
37 | mem_err = -4, | ||
38 | buf_err = -5, | ||
39 | version_err = -6 | ||
40 | }; | ||
41 | |||
42 | //------------------------------------------------ | ||
43 | } // detail | ||
44 | } // zlib | ||
45 | } // http_proto | ||
46 | namespace system { | ||
47 | template<> | ||
48 | struct is_error_code_enum< | ||
49 | ::boost::http_proto::zlib::detail::error> | ||
50 | { | ||
51 | static bool const value = true; | ||
52 | }; | ||
53 | } // system | ||
54 | namespace http_proto { | ||
55 | namespace zlib { | ||
56 | namespace detail { | ||
57 | //------------------------------------------------ | ||
58 | |||
59 | struct error_cat_type | ||
60 | : system::error_category | ||
61 | { | ||
62 | BOOST_SYSTEM_CONSTEXPR | ||
63 | 2 | error_cat_type() noexcept | |
64 | 2 | : error_category( | |
65 | 2 | 0xe6c6d0215d1d6e22) | |
66 | { | ||
67 | 2 | } | |
68 | |||
69 | const char* | ||
70 | ✗ | name() const noexcept override | |
71 | { | ||
72 | ✗ | return "boost.http.proto.zlib"; | |
73 | } | ||
74 | |||
75 | std::string | ||
76 | ✗ | message( int ev ) const override | |
77 | { | ||
78 | ✗ | return message( ev, nullptr, 0 ); | |
79 | } | ||
80 | |||
81 | char const* | ||
82 | ✗ | message( | |
83 | int ev, | ||
84 | char*, | ||
85 | std::size_t) const noexcept override | ||
86 | { | ||
87 | ✗ | switch(static_cast<error>(ev)) | |
88 | { | ||
89 | ✗ | case error::ok: return "Z_OK"; | |
90 | ✗ | case error::stream_end: return "Z_STREAM_END"; | |
91 | ✗ | case error::need_dict: return "Z_NEED_DICT"; | |
92 | ✗ | case error::errno_: return "Z_ERRNO"; | |
93 | ✗ | case error::stream_err: return "Z_STREAM_ERROR"; | |
94 | ✗ | case error::data_err: return "Z_DATA_ERROR"; | |
95 | ✗ | case error::mem_err: return "Z_MEM_ERROR"; | |
96 | ✗ | case error::buf_err: return "Z_BUF_ERROR"; | |
97 | ✗ | case error::version_err: return "Z_VERSION_ERROR"; | |
98 | ✗ | default: | |
99 | ✗ | return "unknown"; | |
100 | } | ||
101 | } | ||
102 | }; | ||
103 | |||
104 | system::error_code | ||
105 | 8 | make_error_code( | |
106 | error ev) noexcept | ||
107 | { | ||
108 | static BOOST_SYSTEM_CONSTEXPR | ||
109 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
8 | error_cat_type cat{}; |
110 | return system::error_code{static_cast< | ||
111 | std::underlying_type< | ||
112 | 8 | error>::type>(ev), cat}; | |
113 | } | ||
114 | |||
115 | //------------------------------------------------ | ||
116 | |||
117 | // probes memory usage for a config | ||
118 | class probe | ||
119 | { | ||
120 | public: | ||
121 | explicit | ||
122 | 2 | probe() noexcept | |
123 | 2 | { | |
124 | 2 | zs_.zalloc = &zalloc; | |
125 | 2 | zs_.zfree = &zfree; | |
126 | 2 | zs_.opaque = this; | |
127 | 2 | } | |
128 | |||
129 | system::result<std::size_t> | ||
130 | 2 | deflate_init( | |
131 | int level) | ||
132 | { | ||
133 | 2 | n_ = 0; | |
134 | 2 | system::error_code ec; | |
135 | ec = static_cast<error>( | ||
136 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | deflateInit(&zs_, level)); |
137 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if(ec.failed()) |
138 | ✗ | return ec; | |
139 | 2 | Bytef tmp[24]{}; | |
140 | 2 | zs_.next_in = &tmp[0]; | |
141 | 2 | zs_.avail_in = 1; | |
142 | 2 | zs_.next_out = &tmp[1]; | |
143 | 2 | zs_.avail_out = 23; | |
144 | ec = static_cast<error>( | ||
145 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | deflate(&zs_, |
146 | 2 | Z_FINISH)); | |
147 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
4 | if( ec.failed() && |
148 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
4 | ec != error::stream_end) |
149 | ✗ | return ec; | |
150 | ec = static_cast<error>( | ||
151 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | deflateEnd(&zs_)); |
152 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if(ec.failed()) |
153 | ✗ | return ec; | |
154 | 2 | return n_; | |
155 | } | ||
156 | |||
157 | system::result<std::size_t> | ||
158 | deflate_init2( | ||
159 | int level, | ||
160 | int method, | ||
161 | int windowBits, | ||
162 | int memLevel, | ||
163 | int strategy) | ||
164 | { | ||
165 | n_ = 0; | ||
166 | system::error_code ec; | ||
167 | ec = static_cast<error>( | ||
168 | deflateInit2(&zs_, | ||
169 | level, | ||
170 | method, | ||
171 | windowBits, | ||
172 | memLevel, | ||
173 | strategy)); | ||
174 | if(ec.failed()) | ||
175 | return ec; | ||
176 | Bytef tmp[2]; | ||
177 | zs_.next_in = &tmp[0]; | ||
178 | zs_.avail_in = 0; | ||
179 | zs_.next_out = &tmp[1]; | ||
180 | zs_.avail_out = 0; | ||
181 | ec = static_cast<error>( | ||
182 | deflate(&zs_, | ||
183 | Z_FULL_FLUSH)); | ||
184 | if(ec.failed()) | ||
185 | return ec; | ||
186 | ec = static_cast<error>( | ||
187 | deflateEnd(&zs_)); | ||
188 | if(ec.failed()) | ||
189 | return ec; | ||
190 | return n_; | ||
191 | } | ||
192 | |||
193 | private: | ||
194 | 10 | static void* zalloc(void* opaque, | |
195 | uInt num, uInt size) | ||
196 | { | ||
197 | 10 | auto& self = | |
198 | *reinterpret_cast< | ||
199 | probe*>(opaque); | ||
200 | 10 | self.n_ += num * size; | |
201 | 10 | return new char[num * size]; | |
202 | } | ||
203 | |||
204 | 10 | static void zfree( | |
205 | void*, void* address) | ||
206 | { | ||
207 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | delete[] reinterpret_cast< |
208 | 10 | char*>(address); | |
209 | 10 | } | |
210 | |||
211 | z_stream_s zs_{}; | ||
212 | std::size_t n_ = 0; | ||
213 | }; | ||
214 | |||
215 | //------------------------------------------------ | ||
216 | |||
217 | struct | ||
218 | deflate_decoder_service_impl | ||
219 | : deflate_decoder_service | ||
220 | { | ||
221 | using key_type = | ||
222 | deflate_decoder_service; | ||
223 | |||
224 | explicit | ||
225 | 2 | deflate_decoder_service_impl( | |
226 | context& ctx, | ||
227 | config const& cfg) | ||
228 | 2 | : cfg_(cfg) | |
229 | { | ||
230 | (void)ctx; | ||
231 | 2 | probe p; | |
232 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | auto n0 = p.deflate_init( |
233 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | Z_DEFAULT_COMPRESSION).value(); |
234 | (void)n0; | ||
235 | 2 | } | |
236 | |||
237 | private: | ||
238 | config cfg_; | ||
239 | |||
240 | config const& | ||
241 | ✗ | get_config() const noexcept override | |
242 | { | ||
243 | ✗ | return cfg_; | |
244 | } | ||
245 | |||
246 | std::size_t | ||
247 | 1 | space_needed() const noexcept override | |
248 | { | ||
249 | 1 | return 0; | |
250 | } | ||
251 | |||
252 | filter& | ||
253 | ✗ | make_filter(http_proto::detail::workspace& ws) const override | |
254 | { | ||
255 | filter* p; | ||
256 | (void)ws; | ||
257 | ✗ | p = nullptr; | |
258 | ✗ | return *p; | |
259 | } | ||
260 | }; | ||
261 | |||
262 | } // detail | ||
263 | |||
264 | void | ||
265 | 2 | deflate_decoder_service:: | |
266 | config:: | ||
267 | install(context& ctx) | ||
268 | { | ||
269 | ctx.make_service< | ||
270 | 2 | detail::deflate_decoder_service_impl>(*this); | |
271 | 2 | } | |
272 | |||
273 | } // zlib | ||
274 | } // http_proto | ||
275 | } // boost | ||
276 | |||
277 | #endif | ||
278 |