| /* |
| * 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 |
| |