boost/log/detail/attachable_sstream_buf.hpp
/*
* Copyright Andrey Semashev 2007 - 2013.
* 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)
*/
/*!
* \file attachable_sstream_buf.hpp
* \author Andrey Semashev
* \date 29.07.2007
*
* \brief This header is the Boost.Log library implementation, see the library documentation
* at http://www.boost.org/libs/log/doc/log.html.
*/
#ifndef BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_
#define BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_
#include <memory>
#include <string>
#include <streambuf>
#include <boost/assert.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
//! A streambuf that puts the formatted data to an external string
template<
typename CharT,
typename TraitsT = std::char_traits< CharT >,
typename AllocatorT = std::allocator< CharT >
>
class basic_ostringstreambuf :
public std::basic_streambuf< CharT, TraitsT >
{
//! Self type
typedef basic_ostringstreambuf< CharT, TraitsT, AllocatorT > this_type;
//! Base type
typedef std::basic_streambuf< CharT, TraitsT > base_type;
//! Buffer size
enum { buffer_size = 16 };
public:
//! Character type
typedef typename base_type::char_type char_type;
//! Traits type
typedef typename base_type::traits_type traits_type;
//! String type
typedef std::basic_string< char_type, traits_type, AllocatorT > string_type;
//! Int type
typedef typename base_type::int_type int_type;
private:
//! A reference to the string that will be filled
string_type* m_Storage;
//! A buffer used to temporarily store output
char_type m_Buffer[buffer_size];
public:
//! Constructor
explicit basic_ostringstreambuf() : m_Storage(0)
{
base_type::setp(m_Buffer, m_Buffer + (sizeof(m_Buffer) / sizeof(*m_Buffer)));
}
//! Constructor
explicit basic_ostringstreambuf(string_type& storage) : m_Storage(boost::addressof(storage))
{
base_type::setp(m_Buffer, m_Buffer + (sizeof(m_Buffer) / sizeof(*m_Buffer)));
}
//! Clears the buffer to the initial state
void clear()
{
register char_type* pBase = this->pbase();
register char_type* pPtr = this->pptr();
if (pBase != pPtr)
this->pbump(static_cast< int >(pBase - pPtr));
}
//! Detaches the buffer from the string
void detach()
{
if (m_Storage)
{
this_type::sync();
m_Storage = 0;
}
}
//! Attaches the buffer to another string
void attach(string_type& storage)
{
detach();
m_Storage = boost::addressof(storage);
}
//! Returns a pointer to the attached string
string_type* storage() const { return m_Storage; }
protected:
//! Puts all buffered data to the string
int sync()
{
BOOST_ASSERT(m_Storage != 0);
register char_type* pBase = this->pbase();
register char_type* pPtr = this->pptr();
if (pBase != pPtr)
{
m_Storage->append(pBase, pPtr);
this->pbump(static_cast< int >(pBase - pPtr));
}
return 0;
}
//! Puts an unbuffered character to the string
int_type overflow(int_type c)
{
BOOST_ASSERT(m_Storage != 0);
basic_ostringstreambuf::sync();
if (!traits_type::eq_int_type(c, traits_type::eof()))
{
m_Storage->push_back(traits_type::to_char_type(c));
return c;
}
else
return traits_type::not_eof(c);
}
//! Puts a character sequence to the string
std::streamsize xsputn(const char_type* s, std::streamsize n)
{
BOOST_ASSERT(m_Storage != 0);
basic_ostringstreambuf::sync();
typedef typename string_type::size_type string_size_type;
register const string_size_type max_storage_left =
m_Storage->max_size() - m_Storage->size();
if (static_cast< string_size_type >(n) < max_storage_left)
{
m_Storage->append(s, static_cast< string_size_type >(n));
return n;
}
else
{
m_Storage->append(s, max_storage_left);
return static_cast< std::streamsize >(max_storage_left);
}
}
//! Copy constructor (closed)
BOOST_LOG_DELETED_FUNCTION(basic_ostringstreambuf(basic_ostringstreambuf const& that))
//! Assignment (closed)
BOOST_LOG_DELETED_FUNCTION(basic_ostringstreambuf& operator= (basic_ostringstreambuf const& that))
};
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_