boost/beast/core/detail/static_ostream.hpp
//
// Copyright (c) 2016-2017 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_STATIC_OSTREAM_HPP
#define BOOST_BEAST_DETAIL_STATIC_OSTREAM_HPP
#include <locale>
#include <ostream>
#include <streambuf>
namespace boost {
namespace beast {
namespace detail {
// http://www.mr-edd.co.uk/blog/beginners_guide_streambuf
class static_ostream_buffer
: public std::basic_streambuf<char>
{
using CharT = char;
using Traits = std::char_traits<CharT>;
using int_type = typename
std::basic_streambuf<CharT, Traits>::int_type;
using traits_type = typename
std::basic_streambuf<CharT, Traits>::traits_type;
char* data_;
std::size_t size_;
std::size_t len_ = 0;
std::string s_;
public:
static_ostream_buffer(static_ostream_buffer&&) = delete;
static_ostream_buffer(static_ostream_buffer const&) = delete;
static_ostream_buffer(char* data, std::size_t size)
: data_(data)
, size_(size)
{
this->setp(data_, data_ + size - 1);
}
~static_ostream_buffer() noexcept
{
}
string_view
str() const
{
if(! s_.empty())
return {s_.data(), len_};
return {data_, len_};
}
int_type
overflow(int_type ch) override
{
if(! Traits::eq_int_type(ch, Traits::eof()))
{
Traits::assign(*this->pptr(),
static_cast<CharT>(ch));
flush(1);
prepare();
return ch;
}
flush();
return traits_type::eof();
}
int
sync() override
{
flush();
prepare();
return 0;
}
private:
void
prepare()
{
static auto const growth_factor = 1.5;
if(len_ < size_ - 1)
{
this->setp(
data_ + len_, data_ + size_ - 2);
return;
}
if(s_.empty())
{
s_.resize(static_cast<std::size_t>(
growth_factor * len_));
Traits::copy(&s_[0], data_, len_);
}
else
{
s_.resize(static_cast<std::size_t>(
growth_factor * len_));
}
this->setp(&s_[len_], &s_[len_] +
s_.size() - len_ - 1);
}
void
flush(int extra = 0)
{
len_ += static_cast<std::size_t>(
this->pptr() - this->pbase() + extra);
}
};
class static_ostream : public std::basic_ostream<char>
{
static_ostream_buffer osb_;
public:
static_ostream(char* data, std::size_t size)
: std::basic_ostream<char>(&this->osb_)
, osb_(data, size)
{
imbue(std::locale::classic());
}
string_view
str() const
{
return osb_.str();
}
};
} // detail
} // beast
} // boost
#endif