Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:24

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_DETAIL_OSTREAM_HPP
0011 #define BOOST_BEAST_DETAIL_OSTREAM_HPP
0012 
0013 #include <boost/beast/core/buffers_prefix.hpp>
0014 #include <boost/beast/core/buffers_range.hpp>
0015 #include <boost/throw_exception.hpp>
0016 #include <boost/asio/buffer.hpp>
0017 #include <memory>
0018 #include <ostream>
0019 #include <streambuf>
0020 #include <type_traits>
0021 #include <utility>
0022 
0023 namespace boost {
0024 namespace beast {
0025 namespace detail {
0026 
0027 struct basic_streambuf_movable_helper :
0028     std::basic_streambuf<char, std::char_traits<char>>
0029 {
0030     basic_streambuf_movable_helper(
0031         basic_streambuf_movable_helper&&) = default;
0032 };
0033 
0034 using basic_streambuf_movable =
0035     std::is_move_constructible<basic_streambuf_movable_helper>;
0036 
0037 template<class DynamicBuffer,
0038     class CharT, class Traits, bool isMovable>
0039 class ostream_buffer;
0040 
0041 //------------------------------------------------------------------------------
0042 
0043 template<class DynamicBuffer, class CharT, class Traits>
0044 class ostream_buffer
0045         <DynamicBuffer, CharT, Traits, true> final
0046     : public std::basic_streambuf<CharT, Traits>
0047 {
0048     using int_type = typename
0049         std::basic_streambuf<CharT, Traits>::int_type;
0050 
0051     using traits_type = typename
0052         std::basic_streambuf<CharT, Traits>::traits_type;
0053 
0054     DynamicBuffer& b_;
0055 
0056 public:
0057     ostream_buffer(ostream_buffer&&) = default;
0058     ostream_buffer(ostream_buffer const&) = delete;
0059 
0060     ~ostream_buffer() noexcept
0061     {
0062         sync();
0063     }
0064 
0065     explicit
0066     ostream_buffer(DynamicBuffer& b)
0067         : b_(b)
0068     {
0069         b_.prepare(0);
0070     }
0071 
0072     int_type
0073     overflow(int_type ch) override
0074     {
0075         BOOST_ASSERT(! Traits::eq_int_type(
0076             ch, Traits::eof()));
0077         sync();
0078 
0079         static std::size_t constexpr max_size = 65536;
0080         auto const max_prepare = std::min<std::size_t>(
0081             std::max<std::size_t>(
0082                 512, b_.capacity() - b_.size()),
0083             std::min<std::size_t>(
0084                 max_size, b_.max_size() - b_.size()));
0085         if(max_prepare == 0)
0086             return Traits::eof();
0087         auto const bs = b_.prepare(max_prepare);
0088         auto const b = buffers_front(bs);
0089         auto const p = static_cast<CharT*>(b.data());
0090         this->setp(p, p + b.size() / sizeof(CharT));
0091 
0092         BOOST_ASSERT(b_.capacity() > b_.size());
0093         return this->sputc(
0094             Traits::to_char_type(ch));
0095     }
0096 
0097     int
0098     sync() override
0099     {
0100         b_.commit(
0101             (this->pptr() - this->pbase()) *
0102             sizeof(CharT));
0103         this->setp(nullptr, nullptr);
0104         return 0;
0105     }
0106 };
0107 
0108 //------------------------------------------------------------------------------
0109 
0110 // This nonsense is all to work around a glitch in libstdc++
0111 // where std::basic_streambuf copy constructor is private:
0112 // https://github.com/gcc-mirror/gcc/blob/gcc-4_8-branch/libstdc%2B%2B-v3/include/std/streambuf#L799
0113 
0114 template<class DynamicBuffer, class CharT, class Traits>
0115 class ostream_buffer
0116         <DynamicBuffer, CharT, Traits, false>
0117     : public std::basic_streambuf<CharT, Traits>
0118 {
0119     using int_type = typename
0120         std::basic_streambuf<CharT, Traits>::int_type;
0121 
0122     using traits_type = typename
0123         std::basic_streambuf<CharT, Traits>::traits_type;
0124 
0125     DynamicBuffer& b_;
0126 
0127 public:
0128     ostream_buffer(ostream_buffer&&) = delete;
0129     ostream_buffer(ostream_buffer const&) = delete;
0130 
0131     ~ostream_buffer() noexcept
0132     {
0133         sync();
0134     }
0135 
0136     explicit
0137     ostream_buffer(DynamicBuffer& b)
0138         : b_(b)
0139     {
0140     }
0141 
0142     int_type
0143     overflow(int_type ch) override
0144     {
0145         BOOST_ASSERT(! Traits::eq_int_type(
0146             ch, Traits::eof()));
0147         sync();
0148 
0149         static std::size_t constexpr max_size = 65536;
0150         auto const max_prepare = std::min<std::size_t>(
0151             std::max<std::size_t>(
0152                 512, b_.capacity() - b_.size()),
0153             std::min<std::size_t>(
0154                 max_size, b_.max_size() - b_.size()));
0155         if(max_prepare == 0)
0156             return Traits::eof();
0157         auto const bs = b_.prepare(max_prepare);
0158         auto const b = buffers_front(bs);
0159         auto const p = static_cast<CharT*>(b.data());
0160         this->setp(p, p + b.size() / sizeof(CharT));
0161 
0162         BOOST_ASSERT(b_.capacity() > b_.size());
0163         return this->sputc(
0164             Traits::to_char_type(ch));
0165     }
0166 
0167     int
0168     sync() override
0169     {
0170         b_.commit(
0171             (this->pptr() - this->pbase()) *
0172             sizeof(CharT));
0173         this->setp(nullptr, nullptr);
0174         return 0;
0175     }
0176 };
0177 
0178 //------------------------------------------------------------------------------
0179 
0180 template<class DynamicBuffer,
0181     class CharT, class Traits, bool isMovable>
0182 class ostream_helper;
0183 
0184 template<class DynamicBuffer, class CharT, class Traits>
0185 class ostream_helper<
0186         DynamicBuffer, CharT, Traits, true>
0187     : public std::basic_ostream<CharT, Traits>
0188 {
0189     ostream_buffer<
0190         DynamicBuffer, CharT, Traits, true> osb_;
0191 
0192 public:
0193     explicit
0194     ostream_helper(DynamicBuffer& b);
0195 
0196     ostream_helper(ostream_helper&& other);
0197 };
0198 
0199 template<class DynamicBuffer, class CharT, class Traits>
0200 ostream_helper<DynamicBuffer, CharT, Traits, true>::
0201 ostream_helper(DynamicBuffer& b)
0202     : std::basic_ostream<CharT, Traits>(&this->osb_)
0203     , osb_(b)
0204 {
0205 }
0206 
0207 template<class DynamicBuffer, class CharT, class Traits>
0208 ostream_helper<DynamicBuffer, CharT, Traits, true>::
0209 ostream_helper(ostream_helper&& other)
0210     : std::basic_ostream<CharT, Traits>(&osb_)
0211     , osb_(std::move(other.osb_))
0212 {
0213 }
0214 
0215 // This work-around is for libstdc++ versions that
0216 // don't have a movable std::basic_streambuf
0217 
0218 template<class T>
0219 class ostream_helper_base
0220 {
0221 protected:
0222     std::unique_ptr<T> member;
0223 
0224     ostream_helper_base(
0225         ostream_helper_base&&) = default;
0226 
0227     explicit
0228     ostream_helper_base(T* t)
0229         : member(t)
0230     {
0231     }
0232 };
0233 
0234 template<class DynamicBuffer, class CharT, class Traits>
0235 class ostream_helper<
0236         DynamicBuffer, CharT, Traits, false>
0237     : private ostream_helper_base<ostream_buffer<
0238         DynamicBuffer, CharT, Traits, false>>
0239     , public std::basic_ostream<CharT, Traits>
0240 {
0241 public:
0242     explicit
0243     ostream_helper(DynamicBuffer& b)
0244         : ostream_helper_base<ostream_buffer<
0245             DynamicBuffer, CharT, Traits, false>>(
0246                 new ostream_buffer<DynamicBuffer,
0247                     CharT, Traits, false>(b))
0248         , std::basic_ostream<CharT, Traits>(
0249             this->member.get())
0250     {
0251     }
0252 
0253     ostream_helper(ostream_helper&& other)
0254         : ostream_helper_base<ostream_buffer<
0255             DynamicBuffer, CharT, Traits, false>>(
0256                 std::move(other))
0257         , std::basic_ostream<CharT, Traits>(
0258             this->member.get())
0259     {
0260     }
0261 };
0262 
0263 } // detail
0264 } // beast
0265 } // boost
0266 
0267 #endif