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