1//
2// Copyright (c) 2016-2019 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
17namespace boost {
18namespace beast {
19namespace detail {
20
21// http://www.mr-edd.co.uk/blog/beginners_guide_streambuf
22
23class 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
38public:
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(pbeg: data_, pend: 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(c1: ch, c2: Traits::eof()))
65 {
66 Traits::assign(c1&: *this->pptr(),
67 c2: static_cast<CharT>(ch));
68 flush(extra: 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
84private:
85 void
86 prepare()
87 {
88 static auto const growth_factor = 1.5;
89
90 if(len_ < size_ - 1)
91 {
92 this->setp(
93 pbeg: data_ + len_, pend: data_ + size_ - 2);
94 return;
95 }
96 if(s_.empty())
97 {
98 s_.resize(n: static_cast<std::size_t>(
99 growth_factor * len_));
100 Traits::copy(s1: &s_[0], s2: data_, n: len_);
101 }
102 else
103 {
104 s_.resize(n: static_cast<std::size_t>(
105 growth_factor * len_));
106 }
107 this->setp(pbeg: &s_[len_], pend: &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
119class static_ostream : public std::basic_ostream<char>
120{
121 static_ostream_buffer osb_;
122
123public:
124 static_ostream(char* data, std::size_t size)
125 : std::basic_ostream<char>(&this->osb_)
126 , osb_(data, size)
127 {
128 imbue(loc: 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

source code of boost/libs/beast/include/boost/beast/core/detail/static_ostream.hpp