Line | Branch | Exec | Source |
---|---|---|---|
1 | // | ||
2 | // Copyright (c) 2019 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_DETAIL_IMPL_ZLIB_CODEC_IPP | ||
11 | #define BOOST_HTTP_PROTO_DETAIL_IMPL_ZLIB_CODEC_IPP | ||
12 | |||
13 | #ifdef BOOST_HTTP_PROTO_HAS_ZLIB | ||
14 | |||
15 | #include <boost/http_proto/parser.hpp> | ||
16 | #include <boost/http_proto/serializer.hpp> | ||
17 | #include <boost/http_proto/detail/codec.hpp> | ||
18 | #include <boost/core/ignore_unused.hpp> | ||
19 | #include <boost/throw_exception.hpp> | ||
20 | #include "zlib.h" | ||
21 | |||
22 | namespace boost { | ||
23 | namespace http_proto { | ||
24 | namespace detail { | ||
25 | |||
26 | enum class zlib_error | ||
27 | { | ||
28 | ok = 0, | ||
29 | stream_end = 1, | ||
30 | need_dict = 2, | ||
31 | errno_ = -1, | ||
32 | stream_err = -2, | ||
33 | data_err = -3, | ||
34 | mem_err = -4, | ||
35 | buf_err = -5, | ||
36 | version_err = -6 | ||
37 | }; | ||
38 | |||
39 | //------------------------------------------------ | ||
40 | } // detail | ||
41 | } // http_proto | ||
42 | namespace system { | ||
43 | template<> | ||
44 | struct is_error_code_enum< | ||
45 | ::boost::http_proto::detail::zlib_error> | ||
46 | { | ||
47 | static bool const value = true; | ||
48 | }; | ||
49 | } // system | ||
50 | namespace http_proto { | ||
51 | namespace detail { | ||
52 | //------------------------------------------------ | ||
53 | |||
54 | error_code | ||
55 | ✗ | make_error_code( | |
56 | zlib_error ev) noexcept | ||
57 | { | ||
58 | struct cat_t : error_category | ||
59 | { | ||
60 | ✗ | cat_t() noexcept | |
61 | ✗ | : error_category( | |
62 | ✗ | 0xe6c6d0215d1d6e22) | |
63 | { | ||
64 | } | ||
65 | |||
66 | const char* | ||
67 | ✗ | name() const noexcept override | |
68 | { | ||
69 | ✗ | return "boost.http.proto.zlib_error"; | |
70 | } | ||
71 | |||
72 | std::string | ||
73 | ✗ | message(int ev) const override | |
74 | { | ||
75 | ✗ | switch(static_cast<zlib_error>(ev)) | |
76 | { | ||
77 | ✗ | case zlib_error::ok: return "Z_OK"; | |
78 | ✗ | case zlib_error::stream_end: return "Z_STREAM_END"; | |
79 | ✗ | case zlib_error::need_dict: return "Z_NEED_DICT"; | |
80 | ✗ | case zlib_error::errno_: return "Z_ERRNO"; | |
81 | ✗ | case zlib_error::stream_err: return "Z_STREAM_ERROR"; | |
82 | ✗ | case zlib_error::data_err: return "Z_DATA_ERROR"; | |
83 | ✗ | case zlib_error::mem_err: return "Z_MEM_ERROR"; | |
84 | ✗ | case zlib_error::buf_err: return "Z_BUF_ERROR"; | |
85 | ✗ | case zlib_error::version_err: return "Z_VERSION_ERROR"; | |
86 | ✗ | default: | |
87 | ✗ | return "unknown"; | |
88 | } | ||
89 | } | ||
90 | }; | ||
91 | ✗ | static cat_t const cat{}; | |
92 | return error_code{static_cast< | ||
93 | std::underlying_type< | ||
94 | ✗ | error>::type>(ev), cat}; | |
95 | } | ||
96 | |||
97 | //------------------------------------------------ | ||
98 | |||
99 | class gzip_decoder : public codec | ||
100 | { | ||
101 | void* zs_ = nullptr; | ||
102 | |||
103 | public: | ||
104 | ~gzip_decoder() override; | ||
105 | gzip_decoder(); | ||
106 | |||
107 | gzip_decoder( | ||
108 | gzip_decoder&&) noexcept; | ||
109 | gzip_decoder& operator=( | ||
110 | gzip_decoder&&) = delete; | ||
111 | |||
112 | results | ||
113 | exchange( | ||
114 | void* output, | ||
115 | std::size_t output_size, | ||
116 | void const* input, | ||
117 | std::size_t input_size) override; | ||
118 | }; | ||
119 | |||
120 | 8 | gzip_decoder:: | |
121 | 4 | ~gzip_decoder() | |
122 | { | ||
123 | 4 | auto zs = reinterpret_cast< | |
124 | ::z_stream*>(zs_); | ||
125 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | if(zs) |
126 | { | ||
127 | 4 | ::inflateEnd(zs); | |
128 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | delete zs; |
129 | } | ||
130 | 8 | } | |
131 | |||
132 | 2 | gzip_decoder:: | |
133 | 2 | gzip_decoder() | |
134 | { | ||
135 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | ::z_stream* zs = new ::z_stream; |
136 | 2 | zs->zalloc = nullptr; | |
137 | 2 | zs->zfree = nullptr; | |
138 | 2 | zs->opaque = nullptr; | |
139 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | int const ec = ::inflateInit(zs); |
140 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if(ec == Z_OK) |
141 | { | ||
142 | 2 | zs_ = zs; | |
143 | 2 | return; | |
144 | } | ||
145 | ✗ | delete zs; | |
146 | ✗ | throw_exception( | |
147 | ✗ | system_error(error_code( | |
148 | static_cast<zlib_error>(ec))), | ||
149 | ✗ | BOOST_CURRENT_LOCATION); | |
150 | } | ||
151 | |||
152 | ✗ | gzip_decoder:: | |
153 | gzip_decoder( | ||
154 | ✗ | gzip_decoder&& other) noexcept | |
155 | ✗ | : zs_(other.zs_) | |
156 | { | ||
157 | ✗ | other.zs_ = nullptr; | |
158 | } | ||
159 | |||
160 | auto | ||
161 | ✗ | gzip_decoder:: | |
162 | exchange( | ||
163 | void* output, | ||
164 | std::size_t output_size, | ||
165 | void const* input, | ||
166 | std::size_t input_size) -> | ||
167 | results | ||
168 | { | ||
169 | ✗ | auto zs = reinterpret_cast< | |
170 | ::z_stream*>(zs_); | ||
171 | // VFALCO zlib seems to need const_cast | ||
172 | ✗ | zs->next_in = | |
173 | const_cast<Bytef z_const*>( | ||
174 | reinterpret_cast< | ||
175 | Bytef const*>(input)); | ||
176 | ✗ | zs->avail_in = static_cast<uInt>(input_size); | |
177 | ✗ | zs->next_out = reinterpret_cast< | |
178 | Bytef*>(output); | ||
179 | ✗ | zs->avail_out = static_cast<uInt>(output_size); | |
180 | ✗ | results rv; | |
181 | rv.ec = static_cast<zlib_error>( | ||
182 | ✗ | ::inflate(zs, Z_NO_FLUSH)); | |
183 | ✗ | rv.input_used = | |
184 | ✗ | input_size - zs->avail_in; | |
185 | ✗ | rv.output_used = | |
186 | ✗ | output_size - zs->avail_out; | |
187 | ✗ | return rv; | |
188 | } | ||
189 | |||
190 | //------------------------------------------------ | ||
191 | |||
192 | class gzip_encoder : public codec | ||
193 | { | ||
194 | void* zs_ = nullptr; | ||
195 | |||
196 | public: | ||
197 | ~gzip_encoder() override; | ||
198 | gzip_encoder(); | ||
199 | |||
200 | gzip_encoder( | ||
201 | gzip_encoder&&) noexcept; | ||
202 | gzip_encoder& operator=( | ||
203 | gzip_encoder&&) = delete; | ||
204 | |||
205 | results | ||
206 | exchange( | ||
207 | void* output, | ||
208 | std::size_t output_size, | ||
209 | void const* input, | ||
210 | std::size_t input_size) override; | ||
211 | }; | ||
212 | |||
213 | ✗ | gzip_encoder:: | |
214 | ✗ | ~gzip_encoder() | |
215 | { | ||
216 | ✗ | auto zs = reinterpret_cast< | |
217 | ::z_stream*>(zs_); | ||
218 | ✗ | if(zs) | |
219 | { | ||
220 | ✗ | ::deflateEnd(zs); | |
221 | ✗ | delete zs; | |
222 | } | ||
223 | } | ||
224 | |||
225 | ✗ | gzip_encoder:: | |
226 | ✗ | gzip_encoder() | |
227 | { | ||
228 | ✗ | ::z_stream* zs = new ::z_stream; | |
229 | ✗ | zs->zalloc = nullptr; | |
230 | ✗ | zs->zfree = nullptr; | |
231 | ✗ | zs->opaque = nullptr; | |
232 | ✗ | int const ec = ::deflateInit(zs, | |
233 | Z_DEFAULT_COMPRESSION); | ||
234 | ✗ | if(ec == Z_OK) | |
235 | { | ||
236 | ✗ | zs_ = zs; | |
237 | ✗ | return; | |
238 | } | ||
239 | ✗ | delete zs; | |
240 | ✗ | throw_exception( | |
241 | ✗ | system_error(error_code( | |
242 | static_cast<zlib_error>(ec))), | ||
243 | ✗ | BOOST_CURRENT_LOCATION); | |
244 | } | ||
245 | |||
246 | ✗ | gzip_encoder:: | |
247 | gzip_encoder( | ||
248 | ✗ | gzip_encoder&& other) noexcept | |
249 | ✗ | : zs_(other.zs_) | |
250 | { | ||
251 | ✗ | other.zs_ = nullptr; | |
252 | } | ||
253 | |||
254 | auto | ||
255 | ✗ | gzip_encoder:: | |
256 | exchange( | ||
257 | void* output, | ||
258 | std::size_t output_size, | ||
259 | void const* input, | ||
260 | std::size_t input_size) -> | ||
261 | results | ||
262 | { | ||
263 | ✗ | auto zs = reinterpret_cast< | |
264 | ::z_stream*>(zs_); | ||
265 | // VFALCO zlib seems to need const_cast | ||
266 | ✗ | zs->next_in = | |
267 | const_cast<Bytef z_const*>( | ||
268 | reinterpret_cast< | ||
269 | Bytef const*>(input)); | ||
270 | ✗ | zs->avail_in = static_cast<uInt>(input_size); | |
271 | ✗ | zs->next_out = reinterpret_cast< | |
272 | Bytef*>(output); | ||
273 | ✗ | zs->avail_out = static_cast<uInt>(output_size); | |
274 | ✗ | results rv; | |
275 | rv.ec = static_cast<zlib_error>( | ||
276 | ✗ | ::deflate(zs, Z_NO_FLUSH)); | |
277 | ✗ | rv.input_used = | |
278 | ✗ | input_size - zs->avail_in; | |
279 | ✗ | rv.output_used = | |
280 | ✗ | output_size - zs->avail_out; | |
281 | ✗ | return rv; | |
282 | } | ||
283 | |||
284 | //------------------------------------------------ | ||
285 | |||
286 | class deflate_decoder : public codec | ||
287 | { | ||
288 | void* zs_ = nullptr; | ||
289 | |||
290 | public: | ||
291 | ~deflate_decoder() override; | ||
292 | deflate_decoder(); | ||
293 | |||
294 | deflate_decoder( | ||
295 | deflate_decoder&&) noexcept; | ||
296 | deflate_decoder& operator=( | ||
297 | deflate_decoder&&) = delete; | ||
298 | |||
299 | results | ||
300 | exchange( | ||
301 | void* output, | ||
302 | std::size_t output_size, | ||
303 | void const* input, | ||
304 | std::size_t input_size) override; | ||
305 | }; | ||
306 | |||
307 | ✗ | deflate_decoder:: | |
308 | ✗ | ~deflate_decoder() | |
309 | { | ||
310 | ✗ | auto zs = reinterpret_cast< | |
311 | ::z_stream*>(zs_); | ||
312 | ✗ | if(zs) | |
313 | { | ||
314 | ✗ | ::inflateEnd(zs); | |
315 | ✗ | delete zs; | |
316 | } | ||
317 | } | ||
318 | |||
319 | ✗ | deflate_decoder:: | |
320 | ✗ | deflate_decoder() | |
321 | { | ||
322 | ✗ | ::z_stream* zs = new ::z_stream; | |
323 | ✗ | zs->zalloc = nullptr; | |
324 | ✗ | zs->zfree = nullptr; | |
325 | ✗ | zs->opaque = nullptr; | |
326 | ✗ | int const ec = ::inflateInit(zs); | |
327 | ✗ | if(ec == Z_OK) | |
328 | { | ||
329 | ✗ | zs_ = zs; | |
330 | ✗ | return; | |
331 | } | ||
332 | ✗ | delete zs; | |
333 | ✗ | throw_exception( | |
334 | ✗ | system_error(error_code( | |
335 | static_cast<zlib_error>(ec))), | ||
336 | ✗ | BOOST_CURRENT_LOCATION); | |
337 | } | ||
338 | |||
339 | ✗ | deflate_decoder:: | |
340 | deflate_decoder( | ||
341 | ✗ | deflate_decoder&& other) noexcept | |
342 | ✗ | : zs_(other.zs_) | |
343 | { | ||
344 | ✗ | other.zs_ = nullptr; | |
345 | } | ||
346 | |||
347 | auto | ||
348 | ✗ | deflate_decoder:: | |
349 | exchange( | ||
350 | void* output, | ||
351 | std::size_t output_size, | ||
352 | void const* input, | ||
353 | std::size_t input_size) -> | ||
354 | results | ||
355 | { | ||
356 | ✗ | auto zs = reinterpret_cast< | |
357 | ::z_stream*>(zs_); | ||
358 | // VFALCO zlib seems to need const_cast | ||
359 | ✗ | zs->next_in = | |
360 | const_cast<Bytef z_const*>( | ||
361 | reinterpret_cast< | ||
362 | Bytef const*>(input)); | ||
363 | ✗ | zs->avail_in = static_cast<uInt>(input_size); | |
364 | ✗ | zs->next_out = reinterpret_cast< | |
365 | Bytef*>(output); | ||
366 | ✗ | zs->avail_out = static_cast<uInt>(output_size); | |
367 | ✗ | results rv; | |
368 | rv.ec = static_cast<zlib_error>( | ||
369 | ✗ | ::inflate(zs, Z_NO_FLUSH)); | |
370 | ✗ | rv.input_used = | |
371 | ✗ | input_size - zs->avail_in; | |
372 | ✗ | rv.output_used = | |
373 | ✗ | output_size - zs->avail_out; | |
374 | ✗ | return rv; | |
375 | } | ||
376 | |||
377 | //------------------------------------------------ | ||
378 | |||
379 | class deflate_encoder : public codec | ||
380 | { | ||
381 | void* zs_ = nullptr; | ||
382 | |||
383 | public: | ||
384 | ~deflate_encoder() override; | ||
385 | deflate_encoder(); | ||
386 | |||
387 | deflate_encoder( | ||
388 | deflate_encoder&&) noexcept; | ||
389 | deflate_encoder& operator=( | ||
390 | deflate_encoder&&) = delete; | ||
391 | |||
392 | results | ||
393 | exchange( | ||
394 | void* output, | ||
395 | std::size_t output_size, | ||
396 | void const* input, | ||
397 | std::size_t input_size) override; | ||
398 | }; | ||
399 | |||
400 | ✗ | deflate_encoder:: | |
401 | ✗ | ~deflate_encoder() | |
402 | { | ||
403 | ✗ | auto zs = reinterpret_cast< | |
404 | ::z_stream*>(zs_); | ||
405 | ✗ | if(zs) | |
406 | { | ||
407 | ✗ | ::deflateEnd(zs); | |
408 | ✗ | delete zs; | |
409 | } | ||
410 | } | ||
411 | |||
412 | ✗ | deflate_encoder:: | |
413 | ✗ | deflate_encoder() | |
414 | { | ||
415 | ✗ | ::z_stream* zs = new ::z_stream; | |
416 | ✗ | zs->zalloc = nullptr; | |
417 | ✗ | zs->zfree = nullptr; | |
418 | ✗ | zs->opaque = nullptr; | |
419 | ✗ | int const ec = ::deflateInit(zs, | |
420 | Z_DEFAULT_COMPRESSION); | ||
421 | ✗ | if(ec == Z_OK) | |
422 | { | ||
423 | ✗ | zs_ = zs; | |
424 | ✗ | return; | |
425 | } | ||
426 | ✗ | delete zs; | |
427 | ✗ | throw_exception( | |
428 | ✗ | system_error(error_code( | |
429 | static_cast<zlib_error>(ec))), | ||
430 | ✗ | BOOST_CURRENT_LOCATION); | |
431 | } | ||
432 | |||
433 | ✗ | deflate_encoder:: | |
434 | deflate_encoder( | ||
435 | ✗ | deflate_encoder&& other) noexcept | |
436 | ✗ | : zs_(other.zs_) | |
437 | { | ||
438 | ✗ | other.zs_ = nullptr; | |
439 | } | ||
440 | |||
441 | auto | ||
442 | ✗ | deflate_encoder:: | |
443 | exchange( | ||
444 | void* output, | ||
445 | std::size_t output_size, | ||
446 | void const* input, | ||
447 | std::size_t input_size) -> | ||
448 | results | ||
449 | { | ||
450 | ✗ | auto zs = reinterpret_cast< | |
451 | ::z_stream*>(zs_); | ||
452 | // VFALCO zlib seems to need const_cast | ||
453 | ✗ | zs->next_in = | |
454 | const_cast<Bytef z_const*>( | ||
455 | reinterpret_cast< | ||
456 | Bytef const*>(input)); | ||
457 | ✗ | zs->avail_in = static_cast<uInt>(input_size); | |
458 | ✗ | zs->next_out = reinterpret_cast< | |
459 | Bytef*>(output); | ||
460 | ✗ | zs->avail_out = static_cast<uInt>(output_size); | |
461 | ✗ | results rv; | |
462 | rv.ec = static_cast<zlib_error>( | ||
463 | ✗ | ::deflate(zs, Z_NO_FLUSH)); | |
464 | ✗ | rv.input_used = | |
465 | ✗ | input_size - zs->avail_in; | |
466 | ✗ | rv.output_used = | |
467 | ✗ | output_size - zs->avail_out; | |
468 | ✗ | return rv; | |
469 | } | ||
470 | |||
471 | } // detail | ||
472 | |||
473 | //------------------------------------------------ | ||
474 | |||
475 | void | ||
476 | ✗ | parser:: | |
477 | apply_param( | ||
478 | deflate_decoder_t const&) | ||
479 | { | ||
480 | ✗ | dec_[deflate_codec].reset( | |
481 | ✗ | new detail::deflate_decoder); | |
482 | } | ||
483 | |||
484 | void | ||
485 | 2 | parser:: | |
486 | apply_param( | ||
487 | gzip_decoder_t const&) | ||
488 | { | ||
489 | 2 | dec_[gzip_codec].reset( | |
490 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | new detail::gzip_decoder); |
491 | 2 | } | |
492 | |||
493 | //------------------------------------------------ | ||
494 | |||
495 | void | ||
496 | ✗ | serializer:: | |
497 | apply_param( | ||
498 | deflate_decoder_t const&) | ||
499 | { | ||
500 | ✗ | dec_[deflate_codec].reset( | |
501 | ✗ | new detail::deflate_decoder); | |
502 | } | ||
503 | |||
504 | void | ||
505 | ✗ | serializer:: | |
506 | apply_param( | ||
507 | deflate_encoder_t const&) | ||
508 | { | ||
509 | ✗ | enc_[deflate_codec].reset( | |
510 | ✗ | new detail::deflate_encoder); | |
511 | } | ||
512 | |||
513 | void | ||
514 | ✗ | serializer:: | |
515 | apply_param( | ||
516 | gzip_decoder_t const&) | ||
517 | { | ||
518 | ✗ | dec_[gzip_codec].reset( | |
519 | ✗ | new detail::gzip_decoder); | |
520 | } | ||
521 | |||
522 | void | ||
523 | ✗ | serializer:: | |
524 | apply_param( | ||
525 | gzip_encoder_t const&) | ||
526 | { | ||
527 | ✗ | enc_[gzip_codec].reset( | |
528 | ✗ | new detail::gzip_encoder); | |
529 | } | ||
530 | |||
531 | } // http_proto | ||
532 | } // boost | ||
533 | |||
534 | #endif | ||
535 | #endif | ||
536 |