123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- //
- // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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)
- //
- // Official repository: https://github.com/boostorg/beast
- //
- #ifndef BOOST_BEAST_DETAIL_OSTREAM_HPP
- #define BOOST_BEAST_DETAIL_OSTREAM_HPP
- #include <boost/beast/core/buffers_prefix.hpp>
- #include <boost/beast/core/buffers_range.hpp>
- #include <boost/throw_exception.hpp>
- #include <boost/asio/buffer.hpp>
- #include <memory>
- #include <ostream>
- #include <streambuf>
- #include <type_traits>
- #include <utility>
- namespace boost {
- namespace beast {
- namespace detail {
- struct basic_streambuf_movable_helper :
- std::basic_streambuf<char, std::char_traits<char>>
- {
- basic_streambuf_movable_helper(
- basic_streambuf_movable_helper&&) = default;
- };
- using basic_streambuf_movable =
- std::is_move_constructible<basic_streambuf_movable_helper>;
- template<class DynamicBuffer,
- class CharT, class Traits, bool isMovable>
- class ostream_buffer;
- //------------------------------------------------------------------------------
- template<class DynamicBuffer, class CharT, class Traits>
- class ostream_buffer
- <DynamicBuffer, CharT, Traits, true> final
- : public std::basic_streambuf<CharT, Traits>
- {
- using int_type = typename
- std::basic_streambuf<CharT, Traits>::int_type;
- using traits_type = typename
- std::basic_streambuf<CharT, Traits>::traits_type;
- DynamicBuffer& b_;
- public:
- ostream_buffer(ostream_buffer&&) = default;
- ostream_buffer(ostream_buffer const&) = delete;
- ~ostream_buffer() noexcept
- {
- sync();
- }
- explicit
- ostream_buffer(DynamicBuffer& b)
- : b_(b)
- {
- b_.prepare(0);
- }
- int_type
- overflow(int_type ch) override
- {
- BOOST_ASSERT(! Traits::eq_int_type(
- ch, Traits::eof()));
- sync();
- static std::size_t constexpr max_size = 65536;
- auto const max_prepare = std::min<std::size_t>(
- std::max<std::size_t>(
- 512, b_.capacity() - b_.size()),
- std::min<std::size_t>(
- max_size, b_.max_size() - b_.size()));
- if(max_prepare == 0)
- return Traits::eof();
- auto const bs = b_.prepare(max_prepare);
- auto const b = buffers_front(bs);
- auto const p = static_cast<CharT*>(b.data());
- this->setp(p, p + b.size() / sizeof(CharT));
- BOOST_ASSERT(b_.capacity() > b_.size());
- return this->sputc(
- Traits::to_char_type(ch));
- }
- int
- sync() override
- {
- b_.commit(
- (this->pptr() - this->pbase()) *
- sizeof(CharT));
- this->setp(nullptr, nullptr);
- return 0;
- }
- };
- //------------------------------------------------------------------------------
- // This nonsense is all to work around a glitch in libstdc++
- // where std::basic_streambuf copy constructor is private:
- // https://github.com/gcc-mirror/gcc/blob/gcc-4_8-branch/libstdc%2B%2B-v3/include/std/streambuf#L799
- template<class DynamicBuffer, class CharT, class Traits>
- class ostream_buffer
- <DynamicBuffer, CharT, Traits, false>
- : public std::basic_streambuf<CharT, Traits>
- {
- using int_type = typename
- std::basic_streambuf<CharT, Traits>::int_type;
- using traits_type = typename
- std::basic_streambuf<CharT, Traits>::traits_type;
- DynamicBuffer& b_;
- public:
- ostream_buffer(ostream_buffer&&) = delete;
- ostream_buffer(ostream_buffer const&) = delete;
- ~ostream_buffer() noexcept
- {
- sync();
- }
- explicit
- ostream_buffer(DynamicBuffer& b)
- : b_(b)
- {
- }
- int_type
- overflow(int_type ch) override
- {
- BOOST_ASSERT(! Traits::eq_int_type(
- ch, Traits::eof()));
- sync();
- static std::size_t constexpr max_size = 65536;
- auto const max_prepare = std::min<std::size_t>(
- std::max<std::size_t>(
- 512, b_.capacity() - b_.size()),
- std::min<std::size_t>(
- max_size, b_.max_size() - b_.size()));
- if(max_prepare == 0)
- return Traits::eof();
- auto const bs = b_.prepare(max_prepare);
- auto const b = buffers_front(bs);
- auto const p = static_cast<CharT*>(b.data());
- this->setp(p, p + b.size() / sizeof(CharT));
- BOOST_ASSERT(b_.capacity() > b_.size());
- return this->sputc(
- Traits::to_char_type(ch));
- }
- int
- sync() override
- {
- b_.commit(
- (this->pptr() - this->pbase()) *
- sizeof(CharT));
- this->setp(nullptr, nullptr);
- return 0;
- }
- };
- //------------------------------------------------------------------------------
- template<class DynamicBuffer,
- class CharT, class Traits, bool isMovable>
- class ostream_helper;
- template<class DynamicBuffer, class CharT, class Traits>
- class ostream_helper<
- DynamicBuffer, CharT, Traits, true>
- : public std::basic_ostream<CharT, Traits>
- {
- ostream_buffer<
- DynamicBuffer, CharT, Traits, true> osb_;
- public:
- explicit
- ostream_helper(DynamicBuffer& b);
- ostream_helper(ostream_helper&& other);
- };
- template<class DynamicBuffer, class CharT, class Traits>
- ostream_helper<DynamicBuffer, CharT, Traits, true>::
- ostream_helper(DynamicBuffer& b)
- : std::basic_ostream<CharT, Traits>(&this->osb_)
- , osb_(b)
- {
- }
- template<class DynamicBuffer, class CharT, class Traits>
- ostream_helper<DynamicBuffer, CharT, Traits, true>::
- ostream_helper(ostream_helper&& other)
- : std::basic_ostream<CharT, Traits>(&osb_)
- , osb_(std::move(other.osb_))
- {
- }
- // This work-around is for libstdc++ versions that
- // don't have a movable std::basic_streambuf
- template<class T>
- class ostream_helper_base
- {
- protected:
- std::unique_ptr<T> member;
- ostream_helper_base(
- ostream_helper_base&&) = default;
- explicit
- ostream_helper_base(T* t)
- : member(t)
- {
- }
- };
- template<class DynamicBuffer, class CharT, class Traits>
- class ostream_helper<
- DynamicBuffer, CharT, Traits, false>
- : private ostream_helper_base<ostream_buffer<
- DynamicBuffer, CharT, Traits, false>>
- , public std::basic_ostream<CharT, Traits>
- {
- public:
- explicit
- ostream_helper(DynamicBuffer& b)
- : ostream_helper_base<ostream_buffer<
- DynamicBuffer, CharT, Traits, false>>(
- new ostream_buffer<DynamicBuffer,
- CharT, Traits, false>(b))
- , std::basic_ostream<CharT, Traits>(
- this->member.get())
- {
- }
- ostream_helper(ostream_helper&& other)
- : ostream_helper_base<ostream_buffer<
- DynamicBuffer, CharT, Traits, false>>(
- std::move(other))
- , std::basic_ostream<CharT, Traits>(
- this->member.get())
- {
- }
- };
- } // detail
- } // beast
- } // boost
- #endif
|