blob: f423312234ef6eee8c1a3e0a47c98bc5443cce6d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <log4cxx/helpers/asyncbuffer.h>
#include <log4cxx/helpers/transcoder.h>
#if defined(__cpp_concepts) && 202002 <= __cpp_concepts
#include <variant>
#endif // defined(__cpp_concepts) && 202002 <= __cpp_concepts
namespace LOG4CXX_NS
{
namespace helpers
{
struct AsyncBuffer::Private
{
#if defined(__cpp_concepts) && 202002 <= __cpp_concepts && LOG4CXX_WCHAR_T_API
using value_t = std::variant<MessageBufferAppender, WideMessageBufferAppender>;
#else // !(defined(__cpp_concepts) && 202002 <= __cpp_concepts && LOG4CXX_WCHAR_T_API)
using value_t = MessageBufferAppender;
#endif // !(defined(__cpp_concepts) && 202002 <= __cpp_concepts && LOG4CXX_WCHAR_T_API)
std::vector<value_t> data;
Private(const value_t& f)
: data{ f }
{}
#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
StringViewType fmt_string;
FmtArgStore fmt_args;
Private(StringViewType&& format_string, FmtArgStore&& args)
: fmt_string{ std::move(format_string) }
, fmt_args{ std::move(args) }
{}
#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
WideStringViewType fmt_wstring;
WideFmtArgStore fmt_wargs;
Private(WideStringViewType&& format_string, WideFmtArgStore&& args)
: fmt_wstring{ std::move(format_string) }
, fmt_wargs{ std::move(args) }
{}
#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
};
#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
void AsyncBuffer::initializeForFmt(StringViewType&& format_string, FmtArgStore&& args)
{
if (!m_priv)
m_priv = std::make_unique<Private>(std::move(format_string), std::move(args));
else
{
m_priv->fmt_string = std::move(format_string);
m_priv->fmt_args = std::move(args);
}
}
#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
void AsyncBuffer::initializeForFmt(WideStringViewType&& format_string, WideFmtArgStore&& args)
{
if (!m_priv)
m_priv = std::make_unique<Private>(std::move(format_string), std::move(args));
else
{
m_priv->fmt_wstring = std::move(format_string);
m_priv->fmt_wargs = std::move(args);
}
}
#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
/** An empty buffer.
*/
AsyncBuffer::AsyncBuffer()
{}
/** A new buffer with the content of \c other
*/
AsyncBuffer::AsyncBuffer(AsyncBuffer&& other)
: m_priv(std::move(other.m_priv))
{
}
/** Release resources.
*/
AsyncBuffer::~AsyncBuffer()
{
}
/**
* Has no item been added to this?
*/
bool AsyncBuffer::empty() const
{
bool result{ true };
if (m_priv)
{
result = m_priv->data.empty();
#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
if (result)
result = (0 == m_priv->fmt_string.size());
#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
if (result)
result = (0 == m_priv->fmt_wstring.size());
#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
#endif
}
return result;
}
/**
* Add text version of buffered values to \c msg
*/
void AsyncBuffer::renderMessage(LogCharMessageBuffer& msg) const
{
if (m_priv)
{
for (auto& renderer : m_priv->data)
#if defined(__cpp_concepts) && 202002 <= __cpp_concepts && LOG4CXX_WCHAR_T_API
{
#if LOG4CXX_LOGCHAR_IS_UTF8
if (auto pRenderer = std::get_if<MessageBufferAppender>(&renderer))
(*pRenderer)(msg);
else
{
WideMessageBuffer wideBuf;
std::get<WideMessageBufferAppender>(renderer)(wideBuf);
LOG4CXX_DECODE_WCHAR(lsMsg, wideBuf.extract_str(wideBuf));
msg << lsMsg;
}
#else // !LOG4CXX_LOGCHAR_IS_UTF8
if (auto pRenderer = std::get_if<WideMessageBufferAppender>(&renderer))
(*pRenderer)(msg);
else
{
CharMessageBuffer narrowBuf;
std::get<MessageBufferAppender>(renderer)(narrowBuf);
LOG4CXX_DECODE_CHAR(lsMsg, narrowBuf.extract_str(narrowBuf));
msg << lsMsg;
}
#endif // !LOG4CXX_LOGCHAR_IS_UTF8
}
#else // !(defined(__cpp_concepts) && 202002 <= __cpp_concepts && LOG4CXX_WCHAR_T_API)
renderer(msg);
#endif // !(defined(__cpp_concepts) && 202002 <= __cpp_concepts && LOG4CXX_WCHAR_T_API)
#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
#if LOG4CXX_LOGCHAR_IS_UTF8
if (0 < m_priv->fmt_string.size())
msg << fmt::vformat(m_priv->fmt_string, m_priv->fmt_args);
#if LOG4CXX_WCHAR_T_API
if (0 < m_priv->fmt_wstring.size())
{
LOG4CXX_DECODE_WCHAR(lsMsg, fmt::vformat(m_priv->fmt_wstring, m_priv->fmt_wargs));
msg << lsMsg;
}
#endif // LOG4CXX_WCHAR_T_API
#endif // LOG4CXX_LOGCHAR_IS_UTF8
#if LOG4CXX_LOGCHAR_IS_WCHAR
if (0 < m_priv->fmt_wstring.size())
msg << fmt::vformat(m_priv->fmt_wstring, m_priv->fmt_wargs);
if (0 < m_priv->fmt_string.size())
{
LOG4CXX_DECODE_CHAR(lsMsg, fmt::vformat(m_priv->fmt_string, m_priv->fmt_args));
msg << lsMsg;
}
#endif // LOG4CXX_LOGCHAR_IS_WCHAR
#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
}
}
/**
* Remove all message appenders
*/
void AsyncBuffer::clear()
{
if (m_priv)
{
m_priv->data.clear();
#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
m_priv->fmt_string = {};
#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
m_priv->fmt_wstring = {};
#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
}
}
#if defined(__cpp_concepts) && 202002 <= __cpp_concepts
/**
* Append \c function to this buffer.
*/
void AsyncBuffer::append(const MessageBufferAppender& f)
{
if (!m_priv)
m_priv = std::make_unique<Private>(f);
else
m_priv->data.push_back(f);
}
#if LOG4CXX_WCHAR_T_API
/**
* Append \c function to this buffer.
*/
void AsyncBuffer::append(const WideMessageBufferAppender& f)
{
if (!m_priv)
m_priv = std::make_unique<Private>(f);
else
m_priv->data.push_back(f);
}
#endif // LOG4CXX_WCHAR_T_API
#else // !(defined(__cpp_concepts) && 202002 <= __cpp_concepts
/**
* Append \c function to this buffer.
*/
void AsyncBuffer::append(const MessageBufferAppender& f)
{
if (!m_priv)
m_priv = std::make_unique<Private>(f);
else
m_priv->data.push_back(f);
}
#endif // !(defined(__cpp_concepts) && 202002 <= __cpp_concepts
} // namespace helpers
} // namespace LOG4CXX_NS