Skip to content

Commit

Permalink
Use C++20's efficient access to basic_stringbuf’s buffer (p0408r7)
Browse files Browse the repository at this point in the history
  • Loading branch information
stephen-webb committed Jul 17, 2023
1 parent 3a85f5c commit 0d1a58d
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 110 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ else()
set(ENABLE_FMT_LAYOUT "OFF")
endif()

# Request C++17, if available
# Request C++20, if available
# This *should* fallback to an older standard if it is not available
if( NOT "${CMAKE_CXX_STANDARD}")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
endif()

# Don't allow for compiler-specific extensions
Expand Down
174 changes: 66 additions & 108 deletions src/main/cpp/messagebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,39 +27,80 @@
#endif
#include <log4cxx/private/log4cxx_private.h>

#if __cplusplus >= 202002L
#define std_basic_ostringstream_provides_efficient_access_to_basic_stringbuf 1
#elif _HAS_CXX20
#define std_basic_ostringstream_provides_efficient_access_to_basic_stringbuf 1
#else
#define std_basic_ostringstream_provides_efficient_access_to_basic_stringbuf 0
#endif

using namespace log4cxx::helpers;

template <typename T>
void ResetStream(std::basic_ostringstream<T>& stream)
struct StringOrStream
{
stream.seekp(0);
stream.str(std::basic_string<T>());
stream.clear();
}

struct CharMessageBuffer::CharMessageBufferPrivate{
CharMessageBufferPrivate() :
stream(nullptr){}
std::basic_string<T> buf;
std::basic_ostringstream<T>* stream;

StringOrStream()
: stream(nullptr)
{}
~StringOrStream()
{
#if !LOG4CXX_HAS_THREAD_LOCAL
delete stream;
#endif
}
/**
* Encapsulated std::string.
*/
std::basic_string<char> buf;
* Move the character buffer from \c buf to \c stream
*/
std::basic_ostringstream<T>& StreamFromBuf()
{
if (!this->stream)
{
#if LOG4CXX_HAS_THREAD_LOCAL
thread_local static std::basic_ostringstream<T> sStream;
this->stream = &sStream;
#else
this->stream = new std::basic_ostringstream<T>();
#endif
#if std_basic_ostringstream_provides_efficient_access_to_basic_stringbuf
auto index = this->buf.size();
this->stream->str(std::move(this->buf));
this->stream->seekp(index);
#else
*this->stream << this->buf;
#endif
}
return *this->stream;
}
/**
* Encapsulated stream, created on demand.
* Move the character buffer from \c stream to \c buf
*/
std::basic_ostringstream<char>* stream;
std::basic_string<T>& BufFromStream()
{
if (this->stream)
{
this->buf = std::move(*this->stream).str();
#if !std_basic_ostringstream_provides_efficient_access_to_basic_stringbuf
this->stream->seekp(0);
this->stream->str(std::basic_string<T>());
this->stream->clear();
#endif
}
return this->buf;
}
};

struct CharMessageBuffer::CharMessageBufferPrivate : public StringOrStream<char> {};

CharMessageBuffer::CharMessageBuffer() : m_priv(std::make_unique<CharMessageBufferPrivate>())
{
}

CharMessageBuffer::~CharMessageBuffer()
{
#if !LOG4CXX_HAS_THREAD_LOCAL
delete m_priv->stream;
#endif
}

CharMessageBuffer& CharMessageBuffer::operator<<(const std::basic_string<char>& msg)
Expand Down Expand Up @@ -118,30 +159,12 @@ CharMessageBuffer& CharMessageBuffer::operator<<(const char msg)

CharMessageBuffer::operator std::basic_ostream<char>& ()
{
if (!m_priv->stream)
{
#if LOG4CXX_HAS_THREAD_LOCAL
thread_local static std::basic_ostringstream<char> sStream;
m_priv->stream = &sStream;
#else
m_priv->stream = new std::basic_ostringstream<char>();
#endif
if (!m_priv->buf.empty())
{
*m_priv->stream << m_priv->buf;
}
}

return *m_priv->stream;
return m_priv->StreamFromBuf();
}

const std::basic_string<char>& CharMessageBuffer::str(std::basic_ostream<char>&)
{
m_priv->buf = m_priv->stream->str();

ResetStream(*m_priv->stream);

return m_priv->buf;
return m_priv->BufFromStream();
}

const std::basic_string<char>& CharMessageBuffer::str(CharMessageBuffer&)
Expand Down Expand Up @@ -203,20 +226,7 @@ std::ostream& CharMessageBuffer::operator<<(void* val)
}

#if LOG4CXX_WCHAR_T_API
struct WideMessageBuffer::WideMessageBufferPrivate{
WideMessageBufferPrivate() :
stream(nullptr){}

/**
* Encapsulated std::string.
*/
std::basic_string<wchar_t> buf;
/**
* Encapsulated stream, created on demand.
*/
std::basic_ostringstream<wchar_t>* stream;
};

struct WideMessageBuffer::WideMessageBufferPrivate : public StringOrStream<wchar_t> {};

WideMessageBuffer::WideMessageBuffer() :
m_priv(std::make_unique<WideMessageBufferPrivate>())
Expand All @@ -225,9 +235,6 @@ WideMessageBuffer::WideMessageBuffer() :

WideMessageBuffer::~WideMessageBuffer()
{
#if !LOG4CXX_HAS_THREAD_LOCAL
delete m_priv->stream;
#endif
}

WideMessageBuffer& WideMessageBuffer::operator<<(const std::basic_string<wchar_t>& msg)
Expand Down Expand Up @@ -287,30 +294,12 @@ WideMessageBuffer& WideMessageBuffer::operator<<(const wchar_t msg)

WideMessageBuffer::operator std::basic_ostream<wchar_t>& ()
{
if (!m_priv->stream)
{
#if LOG4CXX_HAS_THREAD_LOCAL
thread_local static std::basic_ostringstream<wchar_t> sStream;
m_priv->stream = &sStream;
#else
m_priv->stream = new std::basic_ostringstream<wchar_t>();
#endif
if (!m_priv->buf.empty())
{
*m_priv->stream << m_priv->buf;
}
}

return *m_priv->stream;
return m_priv->StreamFromBuf();
}

const std::basic_string<wchar_t>& WideMessageBuffer::str(std::basic_ostream<wchar_t>&)
{
m_priv->buf = m_priv->stream->str();

ResetStream(*m_priv->stream);

return m_priv->buf;
return m_priv->BufFromStream();
}

const std::basic_string<wchar_t>& WideMessageBuffer::str(WideMessageBuffer&)
Expand Down Expand Up @@ -561,19 +550,7 @@ const std::basic_string<log4cxx::UniChar>& MessageBuffer::str(std::basic_ostream
#endif // LOG4CXX_WCHAR_T_API

#if LOG4CXX_UNICHAR_API || LOG4CXX_CFSTRING_API
struct UniCharMessageBuffer::UniCharMessageBufferPrivate {
UniCharMessageBufferPrivate() :
stream(nullptr){}

/**
* Encapsulated std::string.
*/
std::basic_string<UniChar> buf;
/**
* Encapsulated stream, created on demand.
*/
std::basic_ostringstream<UniChar>* stream;
};
struct UniCharMessageBuffer::UniCharMessageBufferPrivate : public StringOrStream<UniChar> {};

UniCharMessageBuffer::UniCharMessageBuffer() :
m_priv(std::make_unique<UniCharMessageBufferPrivate>())
Expand All @@ -582,9 +559,6 @@ UniCharMessageBuffer::UniCharMessageBuffer() :

UniCharMessageBuffer::~UniCharMessageBuffer()
{
#if !LOG4CXX_HAS_THREAD_LOCAL
delete m_priv->stream;
#endif
}


Expand Down Expand Up @@ -645,28 +619,12 @@ UniCharMessageBuffer& UniCharMessageBuffer::operator<<(const log4cxx::UniChar ms

UniCharMessageBuffer::operator UniCharMessageBuffer::uostream& ()
{
if (!m_priv->stream)
{
#if LOG4CXX_HAS_THREAD_LOCAL
thread_local static std::basic_ostringstream<log4cxx::UniChar> sStream;
m_priv->stream = &sStream;
#else
m_priv->stream = new std::basic_ostringstream<log4cxx::UniChar>();
#endif
if (!m_priv->buf.empty())
{
*m_priv->stream << m_priv->buf;
}
}

return *m_priv->stream;
return m_priv->StreamFromBuf();
}

const std::basic_string<log4cxx::UniChar>& UniCharMessageBuffer::str(UniCharMessageBuffer::uostream&)
{
m_priv->buf = m_priv->stream->str();
ResetStream(*m_priv->stream);
return m_priv->buf;
return m_priv->BufFromStream();
}

const std::basic_string<log4cxx::UniChar>& UniCharMessageBuffer::str(UniCharMessageBuffer&)
Expand Down

0 comments on commit 0d1a58d

Please sign in to comment.