1 //
2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9 
10 #ifndef BOOST_BEAST_DETAIL_STATIC_OSTREAM_HPP
11 #define BOOST_BEAST_DETAIL_STATIC_OSTREAM_HPP
12 
13 #include <locale>
14 #include <ostream>
15 #include <streambuf>
16 
frame_cmp(gconstpointer a,gconstpointer b,gpointer user_data _U_)17 namespace boost {
18 namespace beast {
19 namespace detail {
20 
21 // http://www.mr-edd.co.uk/blog/beginners_guide_streambuf
22 
23 class static_ostream_buffer
24     : public std::basic_streambuf<char>
25 {
26     using CharT = char;
27     using Traits = std::char_traits<CharT>;
28     using int_type = typename
29         std::basic_streambuf<CharT, Traits>::int_type;
30     using traits_type = typename
31         std::basic_streambuf<CharT, Traits>::traits_type;
32 
33     char* data_;
34     std::size_t size_;
35     std::size_t len_ = 0;
36     std::string s_;
37 
38 public:
39     static_ostream_buffer(static_ostream_buffer&&) = delete;
40     static_ostream_buffer(static_ostream_buffer const&) = delete;
41 
42     static_ostream_buffer(char* data, std::size_t size)
43         : data_(data)
44         , size_(size)
45     {
46         this->setp(data_, data_ + size - 1);
47     }
48 
49     ~static_ostream_buffer() noexcept
50     {
51     }
52 
53     string_view
54     str() const
55     {
56         if(! s_.empty())
57             return {s_.data(), len_};
58         return {data_, len_};
59     }
60 
61     int_type
62     overflow(int_type ch) override
63     {
64         if(! Traits::eq_int_type(ch, Traits::eof()))
65         {
66             Traits::assign(*this->pptr(),
67                 static_cast<CharT>(ch));
68             flush(1);
69             prepare();
70             return ch;
71         }
72         flush();
73         return traits_type::eof();
74     }
75 
76     int
77     sync() override
78     {
79         flush();
80         prepare();
81         return 0;
82     }
83 
84 private:
85     void
86     prepare()
87     {
88         static auto const growth_factor = 1.5;
89 
90         if(len_ < size_ - 1)
91         {
92             this->setp(
93                 data_ + len_, data_ + size_ - 2);
94             return;
95         }
96         if(s_.empty())
97         {
98             s_.resize(static_cast<std::size_t>(
99                 growth_factor * len_));
100             Traits::copy(&s_[0], data_, len_);
101         }
102         else
103         {
104             s_.resize(static_cast<std::size_t>(
105                 growth_factor * len_));
106         }
107         this->setp(&s_[len_], &s_[len_] +
108             s_.size() - len_ - 1);
109     }
110 
111     void
112     flush(int extra = 0)
113     {
114         len_ += static_cast<std::size_t>(
115             this->pptr() - this->pbase() + extra);
116     }
117 };
118 
119 class static_ostream : public std::basic_ostream<char>
120 {
121     static_ostream_buffer osb_;
122 
123 public:
124     static_ostream(char* data, std::size_t size)
125         : std::basic_ostream<char>(&this->osb_)
126         , osb_(data, size)
127     {
128         imbue(std::locale::classic());
129     }
130 
131     string_view
132     str() const
133     {
134         return osb_.str();
135     }
136 };
137 
138 } // detail
139 } // beast
140 } // boost
141 
142 #endif
143