diff --git a/include/boost/http_proto/service/zlib_service.hpp b/include/boost/http_proto/service/zlib_service.hpp index 6e4f5eb5..c4f37241 100644 --- a/include/boost/http_proto/service/zlib_service.hpp +++ b/include/boost/http_proto/service/zlib_service.hpp @@ -21,35 +21,6 @@ namespace boost { namespace http_proto { namespace zlib { -struct decoder_config -{ - unsigned max_window_bits = 15; - unsigned mem_level = 8; -}; - -constexpr -inline -std::size_t -encoding_size_hint(decoder_config cfg = {}) noexcept -{ - // from: https://www.zlib.net/zlib_tech.html - // - // Memory Footprint - // - // zlib's memory footprint can also be specified fairly - // precisely. It is larger for compression than for - // decompression, and the exact requirements depend on - // how the library was compiled. - // - // The memory requirements for compression depend on two - // parameters, windowBits and memLevel: - // deflate memory usage (bytes) = (1 << (windowBits+2)) + (1 << (memLevel+9)) + 6 KB - return - (1 << (cfg.max_window_bits + 2)) + - (1 << (cfg.mem_level + 9)) + - (6 * 1024); -} - /** Error codes returned from compression/decompression functions. Negative values are errors, positive values are used @@ -124,9 +95,30 @@ struct BOOST_HTTP_PROTO_DECL service : http_proto::service { + /** The memory requirements for deflator. + + @param window_bits The window size. + + @param mem_level The memory level. + + @return The memory requirements in bytes. + */ + virtual + std::size_t + deflator_space_needed( + int window_bits, + int mem_level) const noexcept = 0; + + /** The memory requirements for inflator. + + @param window_bits The window size. + + @return The memory requirements in bytes. + */ virtual std::size_t - space_needed() const noexcept = 0; + inflator_space_needed( + int window_bits) const noexcept = 0; /** Create a deflator stream by calling zlib `deflateInit2()`. diff --git a/src/parser.cpp b/src/parser.cpp index 58844444..cf690708 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -428,9 +428,8 @@ parser_service( { if(cfg.apply_deflate_decoder) { - zlib_svc = &ctx.get_service< - zlib::service>(); - auto const n = zlib_svc->space_needed(); + auto const n = ctx.get_service< + zlib::service>().inflator_space_needed(15); if( max_codec < n) max_codec = n; } diff --git a/src_zlib/service/zlib_service.cpp b/src_zlib/service/zlib_service.cpp index 61a09494..4fa46ff1 100644 --- a/src_zlib/service/zlib_service.cpp +++ b/src_zlib/service/zlib_service.cpp @@ -256,9 +256,35 @@ struct service_impl } std::size_t - space_needed() const noexcept override + deflator_space_needed( + int window_bits, + int mem_level) const noexcept override + { + // TODO: Account for the number of allocations and + // their overhead in the workspace. + + // https://www.zlib.net/zlib_tech.html + return + (1 << (window_bits + 2)) + + (1 << (mem_level + 9)) + + (6 * 1024) + + http_proto::detail:: + workspace::space_needed(); + } + + std::size_t + inflator_space_needed( + int window_bits) const noexcept override { - return 0; // TODO + // TODO: Account for the number of allocations and + // their overhead in the workspace. + + // https://www.zlib.net/zlib_tech.html + return + (1 << window_bits) + + (7 * 1024) + + http_proto::detail:: + workspace::space_needed(); } stream& diff --git a/test/unit/zlib.cpp b/test/unit/zlib.cpp index a6dc187c..113215bb 100644 --- a/test/unit/zlib.cpp +++ b/test/unit/zlib.cpp @@ -325,7 +325,8 @@ struct zlib_test zlib::install_service(ctx); serializer sr( ctx, - zlib::encoding_size_hint() + (2 * 1024)); + ctx.get_service< + zlib::service>().deflator_space_needed(15, 8) + (2 * 1024)); // prove we can reuse the serializer successfully for( int i = 0; i < 2; ++i )