123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- /*
- * Copyright (c) 2017-2023 zhllxt
- *
- * author : zhllxt
- * email : 37792738@qq.com
- *
- * Distributed under the Boost Software License, Version 1.0. (See accompanying
- * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- *
- * https://github.com/r-lyeh-archived/bundle
- *
- */
- #ifndef __ASIO2_ZLIB_HPP__
- #define __ASIO2_ZLIB_HPP__
- #if defined(_MSC_VER) && (_MSC_VER >= 1200)
- #pragma once
- #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
- #include <string>
- #include <string_view>
- #include <algorithm>
- #include <asio2/external/asio.hpp>
- #include <asio2/external/beast.hpp>
- #include <asio2/base/error.hpp>
- #ifdef ASIO2_HEADER_ONLY
- namespace bho::beast::zlib
- #else
- namespace boost::beast::zlib
- #endif
- {
- /**
- * impl : use the beast::zlib for compress and uncompress
- * Problem: compress data with beast::zlib and uncompress data with zlib(www.zlib.net) will fail
- */
- class impl
- {
- public:
- impl(
- beast::zlib::Flush compress_flush = beast::zlib::Flush::sync,
- beast::zlib::Flush uncompress_flush = beast::zlib::Flush::sync
- )
- : deflate_flush_( compress_flush)
- , inflate_flush_(uncompress_flush)
- {
- }
- ~impl() = default;
- impl(impl&&) = delete;
- impl(const impl&) = delete;
- impl& operator=(impl&&) = delete;
- impl& operator=(const impl&) = delete;
- inline std::string compress(std::string_view data)
- {
- return work(deflate_stream_, deflate_flush_, data, asio2::get_last_error());
- }
- inline std::string uncompress(std::string_view data)
- {
- return work(inflate_stream_, inflate_flush_, data, asio2::get_last_error());
- }
- inline static std::size_t compress_bound(std::size_t size)
- {
- return beast::zlib::deflate_upper_bound(size);
- }
- inline static std::size_t uncompress_bound(std::size_t size)
- {
- std::size_t bound = size;
- std::size_t deflate_bound = beast::zlib::deflate_upper_bound(bound) + 5 + 6 + 1;
- while (deflate_bound < size)
- {
- bound += (size - deflate_bound) * 2;
- deflate_bound = beast::zlib::deflate_upper_bound(bound) + 5 + 6 + 1;
- }
- return (std::max)(bound, deflate_bound);
- }
- inline beast::zlib::deflate_stream& compressor() { return deflate_stream_; }
- inline beast::zlib::inflate_stream& uncompressor() { return inflate_stream_; }
- protected:
- template<class CompressOrUncompress>
- inline std::size_t calc_bound(CompressOrUncompress&, beast::zlib::Flush, std::size_t size)
- {
- using optype = std::remove_cv_t<std::remove_reference_t<CompressOrUncompress>>;
- if constexpr /**/ (std::is_same_v<beast::zlib::deflate_stream, optype>)
- {
- return compress_bound(size);
- }
- else if constexpr (std::is_same_v<beast::zlib::inflate_stream, optype>)
- {
- return uncompress_bound(size);
- }
- else
- {
- // http://www.purecpp.cn/detail?id=2293
- static_assert(!sizeof(CompressOrUncompress));
- }
- }
- template<class CompressOrUncompress>
- inline std::string work(CompressOrUncompress& op, beast::zlib::Flush flush, std::string_view data, asio::error_code& ec)
- {
- ec.clear();
- std::string result{};
- result.resize(calc_bound(op, flush, data.size()));
- beast::zlib::z_params zs{};
- zs.next_in = decltype(zs.next_in)(data.data());
- zs.avail_in = data.size();
- zs.next_out = decltype(zs.next_out)(result.data());
- zs.avail_out = result.size();
- while (true)
- {
- op.write(zs, flush, ec);
- if (ec)
- break;
- if (zs.avail_in == std::size_t(0))
- break;
- result.resize(result.size() + calc_bound(op, flush, zs.avail_in));
- zs.next_out = decltype(zs.next_out)(result.data() + zs.total_out);
- zs.avail_out = result.size() - zs.total_out;
- }
- if (!ec)
- result.resize(zs.total_out);
- else
- result.resize(0);
- return result;
- }
- protected:
- beast::zlib::deflate_stream deflate_stream_{};
- beast::zlib::inflate_stream inflate_stream_{};
- beast::zlib::Flush deflate_flush_{ beast::zlib::Flush::sync };
- beast::zlib::Flush inflate_flush_{ beast::zlib::Flush::sync };
- };
- }
- #endif // !__ASIO2_ZLIB_HPP__
|