| /* | |
| * 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 LOG4CXX_CONCEPTS | |
| #include <variant> | |
| #endif // LOG4CXX_CONCEPTS | |
| namespace LOG4CXX_NS | |
| { | |
| namespace helpers | |
| { | |
| struct AsyncBuffer::Private | |
| { | |
| #if LOG4CXX_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(value_t&& f) | |
| : data{ std::move(f) } | |
| {} | |
| #if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT | |
| StringViewType fmt_string; | |
| FmtArgStore fmt_args; | |
| Private(const StringViewType& format_string, FmtArgStore&& args) | |
| : fmt_string{ format_string } | |
| , fmt_args{ std::move(args) } | |
| {} | |
| #if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR | |
| WideStringViewType fmt_wstring; | |
| WideFmtArgStore fmt_wargs; | |
| Private(const WideStringViewType& format_string, WideFmtArgStore&& args) | |
| : fmt_wstring{ 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(const StringViewType& format_string, FmtArgStore&& args) | |
| { | |
| if (!m_priv) | |
| m_priv = std::make_unique<Private>(format_string, std::move(args)); | |
| else | |
| { | |
| m_priv->fmt_string = format_string; | |
| m_priv->fmt_args = std::move(args); | |
| } | |
| } | |
| #if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR | |
| void AsyncBuffer::initializeForFmt(const WideStringViewType& format_string, WideFmtArgStore&& args) | |
| { | |
| if (!m_priv) | |
| m_priv = std::make_unique<Private>(format_string, std::move(args)); | |
| else | |
| { | |
| m_priv->fmt_wstring = 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 LOG4CXX_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 // !LOG4CXX_CONCEPTS | |
| renderer(msg); | |
| #endif // !LOG4CXX_CONCEPTS | |
| #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 LOG4CXX_CONCEPTS | |
| /** | |
| * Append \c function to this buffer. | |
| */ | |
| void AsyncBuffer::append(MessageBufferAppender&& f) | |
| { | |
| if (!m_priv) | |
| m_priv = std::make_unique<Private>(std::move(f)); | |
| else | |
| m_priv->data.push_back(std::move(f)); | |
| } | |
| #if LOG4CXX_WCHAR_T_API | |
| /** | |
| * Append \c function to this buffer. | |
| */ | |
| void AsyncBuffer::append(WideMessageBufferAppender&& f) | |
| { | |
| if (!m_priv) | |
| m_priv = std::make_unique<Private>(std::move(f)); | |
| else | |
| m_priv->data.push_back(std::move(f)); | |
| } | |
| #endif // LOG4CXX_WCHAR_T_API | |
| #else // !LOG4CXX_CONCEPTS | |
| /** | |
| * Append \c function to this buffer. | |
| */ | |
| void AsyncBuffer::append(MessageBufferAppender&& f) | |
| { | |
| if (!m_priv) | |
| m_priv = std::make_unique<Private>(std::move(f)); | |
| else | |
| m_priv->data.push_back(std::move(f)); | |
| } | |
| #endif // !LOG4CXX_CONCEPTS | |
| } // namespace helpers | |
| } // namespace LOG4CXX_NS | |