LCOV - code coverage report
Current view: top level - libs/http_proto/src_zlib/service/zlib_service.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 62.9 % 70 44
Test Date: 2024-09-20 16:11:51 Functions: 66.7 % 15 10

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
       3              : // Copyright (c) 2024 Mohammad Nejati
       4              : //
       5              : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       6              : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       7              : //
       8              : // Official repository: https://github.com/cppalliance/http_proto
       9              : //
      10              : 
      11              : #include <boost/http_proto/service/zlib_service.hpp>
      12              : 
      13              : #include <boost/assert/source_location.hpp>
      14              : #include <boost/config.hpp>
      15              : #include <boost/system/result.hpp>
      16              : #include <boost/throw_exception.hpp>
      17              : 
      18              : #include <zlib.h>
      19              : 
      20              : namespace boost {
      21              : namespace http_proto {
      22              : namespace zlib {
      23              : 
      24              : namespace {
      25              : 
      26              : BOOST_NOINLINE BOOST_NORETURN
      27              : void
      28            0 : throw_zlib_error(
      29              :     int e,
      30              :     source_location const& loc = BOOST_CURRENT_LOCATION)
      31              : {
      32            0 :     throw_exception(
      33            0 :         system::system_error(static_cast<error>(e)), loc);
      34              : }
      35              : 
      36              : // probes memory usage for a config
      37              : class probe
      38              : {
      39              : public:
      40              :     explicit
      41              :     probe() noexcept
      42              :     {
      43              :         zs_.zalloc = &zalloc;
      44              :         zs_.zfree = &zfree;
      45              :         zs_.opaque = this;
      46              :     }
      47              : 
      48              :     system::result<std::size_t>
      49              :     deflate_init(
      50              :         int level)
      51              :     {
      52              :         n_ = 0;
      53              :         system::error_code ec;
      54              :         ec = static_cast<error>(
      55              :             deflateInit(&zs_, level));
      56              :         if(ec.failed())
      57              :             return ec;
      58              :         Bytef tmp[24]{};
      59              :         zs_.next_in = &tmp[0];
      60              :         zs_.avail_in = 1;
      61              :         zs_.next_out = &tmp[1];
      62              :         zs_.avail_out = 23;
      63              :         ec = static_cast<error>(
      64              :             deflate(&zs_,
      65              :                 Z_FINISH));
      66              :         if( ec.failed() &&
      67              :             ec != error::stream_end)
      68              :             return ec;
      69              :         ec = static_cast<error>(
      70              :             deflateEnd(&zs_));
      71              :         if(ec.failed())
      72              :             return ec;
      73              :         return n_;
      74              :     }
      75              : 
      76              :     system::result<std::size_t>
      77              :     deflate_init2(
      78              :         int level,
      79              :         int method,
      80              :         int windowBits,
      81              :         int memLevel,
      82              :         int strategy)
      83              :     {
      84              :         n_ = 0;
      85              :         system::error_code ec;
      86              :         ec = static_cast<error>(
      87              :             deflateInit2(&zs_,
      88              :                 level,
      89              :                 method,
      90              :                 windowBits,
      91              :                 memLevel,
      92              :                 strategy));
      93              :         if(ec.failed())
      94              :             return ec;
      95              :         Bytef tmp[2];
      96              :         zs_.next_in = &tmp[0];
      97              :         zs_.avail_in = 0;
      98              :         zs_.next_out = &tmp[1];
      99              :         zs_.avail_out = 0;
     100              :         ec = static_cast<error>(
     101              :             deflate(&zs_,
     102              :                 Z_FULL_FLUSH));
     103              :         if(ec.failed())
     104              :             return ec;
     105              :         ec = static_cast<error>(
     106              :             deflateEnd(&zs_));
     107              :         if(ec.failed())
     108              :             return ec;
     109              :         return n_;
     110              :     }
     111              : 
     112              : private:
     113              :     static void* zalloc(void* opaque,
     114              :         uInt num, uInt size)
     115              :     {
     116              :         auto& self =
     117              :             *reinterpret_cast<
     118              :                 probe*>(opaque);
     119              :         self.n_ += num * size;
     120              :         return new char[num * size];
     121              :     }
     122              : 
     123              :     static void zfree(
     124              :         void*, void* address)
     125              :     {
     126              :         delete[] reinterpret_cast<
     127              :             char*>(address);
     128              :     }
     129              : 
     130              :     z_stream_s zs_{};
     131              :     std::size_t n_ = 0;
     132              : };
     133              : 
     134          240 : void* zalloc(
     135              :     void* opaque,
     136              :     unsigned items,
     137              :     unsigned size)
     138              : {
     139              :     try
     140              :     {
     141          240 :         auto n = items * size;
     142          240 :         auto* ws =
     143              :             reinterpret_cast<
     144              :                 http_proto::detail::workspace*>(opaque);
     145              : 
     146          240 :         return ws->reserve_front(n);
     147              :     }
     148            0 :     catch(std::length_error const&) // represents OOM
     149              :     {
     150            0 :         return Z_NULL;
     151            0 :     }
     152              : }
     153              : 
     154            0 : void zfree(void* /* opaque */, void* /* addr */)
     155              : {
     156              :     // we call ws_.clear() before the serializer is reused
     157              :     // so all the allocations are passively freed
     158            0 : }
     159              : 
     160              : static ::uInt
     161       144928 : clamp(std::size_t x) noexcept
     162              : {
     163       144928 :     if(x >= (std::numeric_limits<::uInt>::max)())
     164            0 :         return (std::numeric_limits<::uInt>::max)();
     165       144928 :     return static_cast<::uInt>(x);
     166              : }
     167              : 
     168              : void
     169        36232 : sync(z_stream* zs, params const& p) noexcept
     170              : {
     171        36232 :     zs->next_in   = reinterpret_cast<::Bytef*>(
     172        36232 :         const_cast<void*>(p.next_in));
     173        36232 :     zs->avail_in  = clamp(p.avail_in);
     174        36232 :     zs->next_out  = reinterpret_cast<::Bytef*>(p.next_out);
     175        36232 :     zs->avail_out = clamp(p.avail_out);
     176        36232 : }
     177              : 
     178              : void
     179        36232 : sync(z_stream const& zs, params* p) noexcept
     180              : {
     181        36232 :     p->next_in    = zs.next_in;
     182        36232 :     p->avail_in  -= clamp(p->avail_in) - zs.avail_in;
     183        36232 :     p->next_out   = zs.next_out;
     184        36232 :     p->avail_out -= clamp(p->avail_out) - zs.avail_out;
     185        36232 : }
     186              : 
     187              : class deflator
     188              :     : public stream
     189              : {
     190              :     z_stream zs_;
     191              : 
     192              : public:
     193           48 :     deflator(
     194              :         http_proto::detail::workspace& ws,
     195              :         int level,
     196              :         int window_bits,
     197              :         int mem_level)
     198           48 :     {
     199           48 :         zs_.zalloc = &zalloc;
     200           48 :         zs_.zfree  = &zfree;
     201           48 :         zs_.opaque = &ws;
     202              : 
     203           48 :         auto ret = deflateInit2(&zs_, level, Z_DEFLATED,
     204              :             window_bits, mem_level, Z_DEFAULT_STRATEGY);
     205           48 :         if(ret != Z_OK)
     206            0 :             throw_zlib_error(ret);
     207           48 :     }
     208              : 
     209              :     system::error_code
     210        36232 :     write(params& p, flush f) noexcept override
     211              :     {
     212        36232 :         sync(&zs_, p);
     213        36232 :         auto ret = deflate(&zs_, static_cast<int>(f));
     214        36232 :         sync(zs_, &p);
     215        36232 :         return static_cast<error>(ret);
     216              :     }
     217              : };
     218              : 
     219              : class inflator
     220              :     : public stream
     221              : {
     222              :     z_stream zs_;
     223              : 
     224              : public:
     225            0 :     inflator(
     226              :         http_proto::detail::workspace& ws,
     227              :         int window_bits)
     228            0 :     {
     229            0 :         zs_.zalloc = &zalloc;
     230            0 :         zs_.zfree  = &zfree;
     231            0 :         zs_.opaque = &ws;
     232              : 
     233            0 :         auto ret = inflateInit2(&zs_, window_bits);
     234            0 :         if(ret != Z_OK)
     235            0 :             throw_zlib_error(ret);
     236            0 :     }
     237              : 
     238              :     system::error_code
     239            0 :     write(params& p, flush f) noexcept override
     240              :     {
     241            0 :         sync(&zs_, p);
     242            0 :         auto ret = inflate(&zs_, static_cast<int>(f));
     243            0 :         sync(zs_, &p);
     244            0 :         return static_cast<error>(ret);
     245              :     }
     246              : };
     247              : 
     248              : struct service_impl
     249              :     : public service
     250              : {
     251              :     using key_type = service;
     252              : 
     253              :     explicit
     254           26 :     service_impl(context&) noexcept
     255           26 :     {
     256           26 :     }
     257              : 
     258              :     std::size_t
     259            1 :     space_needed() const noexcept override
     260              :     {
     261            1 :         return 0; // TODO
     262              :     }
     263              : 
     264              :     stream&
     265           48 :     make_deflator(
     266              :         http_proto::detail::workspace& ws,
     267              :         int level,
     268              :         int window_bits,
     269              :         int mem_level) const override
     270              :     {
     271           48 :         return ws.emplace<deflator>(
     272           48 :             ws, level, window_bits, mem_level);
     273              :     }
     274              : 
     275              :     stream&
     276            0 :     make_inflator(
     277              :         http_proto::detail::workspace& ws,
     278              :         int window_bits) const override
     279              :     {
     280            0 :         return ws.emplace<inflator>(ws, window_bits);
     281              :     }
     282              : };
     283              : 
     284              : } // namespace
     285              : 
     286              : void
     287           26 : install_service(context& ctx)
     288              : {
     289           26 :     ctx.make_service<service_impl>();
     290           26 : }
     291              : 
     292              : } // zlib
     293              : } // http_proto
     294              : } // boost
        

Generated by: LCOV version 2.1