Coverage Report

Created: 2025-11-24 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/cpp/asyncbuffer.cpp
Line
Count
Source
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
#include <log4cxx/helpers/asyncbuffer.h>
19
#include <log4cxx/helpers/transcoder.h>
20
#if defined(__cpp_concepts) && 202002 <= __cpp_concepts
21
#include <variant>
22
#endif // defined(__cpp_concepts) && 202002 <= __cpp_concepts
23
24
namespace LOG4CXX_NS
25
{
26
27
namespace helpers
28
{
29
30
struct AsyncBuffer::Private
31
{
32
#if defined(__cpp_concepts) && 202002 <= __cpp_concepts && LOG4CXX_WCHAR_T_API
33
    using value_t = std::variant<MessageBufferAppender, WideMessageBufferAppender>;
34
#else // !(defined(__cpp_concepts) && 202002 <= __cpp_concepts && LOG4CXX_WCHAR_T_API)
35
    using value_t = MessageBufferAppender;
36
#endif // !(defined(__cpp_concepts) && 202002 <= __cpp_concepts && LOG4CXX_WCHAR_T_API)
37
  std::vector<value_t> data;
38
39
  Private(const value_t& f)
40
0
    : data{ f }
41
0
  {}
42
43
#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
44
  StringViewType fmt_string;
45
  FmtArgStore    fmt_args;
46
47
  Private(StringViewType&& format_string, FmtArgStore&& args)
48
    : fmt_string{ std::move(format_string) }
49
    , fmt_args{ std::move(args) }
50
  {}
51
52
#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
53
  WideStringViewType fmt_wstring;
54
  WideFmtArgStore    fmt_wargs;
55
56
  Private(WideStringViewType&& format_string, WideFmtArgStore&& args)
57
    : fmt_wstring{ std::move(format_string) }
58
    , fmt_wargs{ std::move(args) }
59
  {}
60
#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
61
#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
62
63
};
64
65
#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
66
void AsyncBuffer::initializeForFmt(StringViewType&& format_string, FmtArgStore&& args)
67
{
68
  if (!m_priv)
69
    m_priv = std::make_unique<Private>(std::move(format_string), std::move(args));
70
  else
71
  {
72
    m_priv->fmt_string = std::move(format_string);
73
    m_priv->fmt_args = std::move(args);
74
  }
75
}
76
77
#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
78
void AsyncBuffer::initializeForFmt(WideStringViewType&& format_string, WideFmtArgStore&& args)
79
{
80
  if (!m_priv)
81
    m_priv = std::make_unique<Private>(std::move(format_string), std::move(args));
82
  else
83
  {
84
    m_priv->fmt_wstring = std::move(format_string);
85
    m_priv->fmt_wargs = std::move(args);
86
  }
87
}
88
#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
89
#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
90
91
/** An empty buffer.
92
*/
93
AsyncBuffer::AsyncBuffer()
94
4.37k
{}
95
96
/** A new buffer with the content of \c other
97
*/
98
AsyncBuffer::AsyncBuffer(AsyncBuffer&& other)
99
0
  : m_priv(std::move(other.m_priv))
100
0
{
101
0
}
102
103
/** Release resources.
104
*/
105
AsyncBuffer::~AsyncBuffer()
106
4.37k
{
107
4.37k
}
108
109
/**
110
* Has no item been added to this?
111
*/
112
bool AsyncBuffer::empty() const
113
4.37k
{
114
4.37k
  bool result{ true };
115
4.37k
  if (m_priv)
116
0
  {
117
0
    result = m_priv->data.empty();
118
#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
119
    if (result)
120
      result = (0 == m_priv->fmt_string.size());
121
#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
122
    if (result)
123
      result = (0 == m_priv->fmt_wstring.size());
124
#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
125
#endif
126
0
  }
127
4.37k
  return result;
128
4.37k
}
129
130
/**
131
* Add text version of buffered values to \c msg
132
*/
133
void AsyncBuffer::renderMessage(LogCharMessageBuffer& msg) const
134
0
{
135
0
  if (m_priv)
136
0
  {
137
0
    for (auto& renderer : m_priv->data)
138
0
#if defined(__cpp_concepts) && 202002 <= __cpp_concepts && LOG4CXX_WCHAR_T_API
139
0
    {
140
0
#if LOG4CXX_LOGCHAR_IS_UTF8
141
0
      if (auto pRenderer = std::get_if<MessageBufferAppender>(&renderer))
142
0
        (*pRenderer)(msg);
143
0
      else
144
0
      {
145
0
        WideMessageBuffer wideBuf;
146
0
        std::get<WideMessageBufferAppender>(renderer)(wideBuf);
147
0
        LOG4CXX_DECODE_WCHAR(lsMsg, wideBuf.extract_str(wideBuf));
148
0
        msg << lsMsg;
149
0
      }
150
#else // !LOG4CXX_LOGCHAR_IS_UTF8
151
      if (auto pRenderer = std::get_if<WideMessageBufferAppender>(&renderer))
152
        (*pRenderer)(msg);
153
      else
154
      {
155
        CharMessageBuffer narrowBuf;
156
        std::get<MessageBufferAppender>(renderer)(narrowBuf);
157
        LOG4CXX_DECODE_CHAR(lsMsg, narrowBuf.extract_str(narrowBuf));
158
        msg << lsMsg;
159
      }
160
#endif // !LOG4CXX_LOGCHAR_IS_UTF8
161
0
    }
162
#else // !(defined(__cpp_concepts) && 202002 <= __cpp_concepts && LOG4CXX_WCHAR_T_API)
163
      renderer(msg);
164
#endif // !(defined(__cpp_concepts) && 202002 <= __cpp_concepts && LOG4CXX_WCHAR_T_API)
165
166
#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
167
#if LOG4CXX_LOGCHAR_IS_UTF8
168
    if (0 < m_priv->fmt_string.size())
169
      msg << fmt::vformat(m_priv->fmt_string, m_priv->fmt_args);
170
#if LOG4CXX_WCHAR_T_API
171
    if (0 < m_priv->fmt_wstring.size())
172
    {
173
      LOG4CXX_DECODE_WCHAR(lsMsg, fmt::vformat(m_priv->fmt_wstring, m_priv->fmt_wargs));
174
      msg << lsMsg;
175
    }
176
#endif // LOG4CXX_WCHAR_T_API
177
#endif // LOG4CXX_LOGCHAR_IS_UTF8
178
179
#if LOG4CXX_LOGCHAR_IS_WCHAR
180
    if (0 < m_priv->fmt_wstring.size())
181
      msg << fmt::vformat(m_priv->fmt_wstring, m_priv->fmt_wargs);
182
    if (0 < m_priv->fmt_string.size())
183
    {
184
      LOG4CXX_DECODE_CHAR(lsMsg, fmt::vformat(m_priv->fmt_string, m_priv->fmt_args));
185
      msg << lsMsg;
186
    }
187
#endif // LOG4CXX_LOGCHAR_IS_WCHAR
188
#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
189
0
  }
190
0
}
191
192
/**
193
* Remove all message appenders
194
*/
195
void AsyncBuffer::clear()
196
0
{
197
0
  if (m_priv)
198
0
  {
199
0
    m_priv->data.clear();
200
#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
201
    m_priv->fmt_string = {};
202
#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
203
    m_priv->fmt_wstring = {};
204
#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
205
#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
206
0
  }
207
0
}
208
209
#if defined(__cpp_concepts) && 202002 <= __cpp_concepts
210
/**
211
 *   Append \c function to this buffer.
212
 */
213
void AsyncBuffer::append(const MessageBufferAppender& f)
214
0
{
215
0
  if (!m_priv)
216
0
    m_priv = std::make_unique<Private>(f);
217
0
  else
218
0
    m_priv->data.push_back(f);
219
0
}
220
221
#if LOG4CXX_WCHAR_T_API
222
/**
223
 *   Append \c function to this buffer.
224
 */
225
void AsyncBuffer::append(const WideMessageBufferAppender& f)
226
0
{
227
0
  if (!m_priv)
228
0
    m_priv = std::make_unique<Private>(f);
229
0
  else
230
0
    m_priv->data.push_back(f);
231
0
}
232
#endif // LOG4CXX_WCHAR_T_API
233
#else // !(defined(__cpp_concepts) && 202002 <= __cpp_concepts
234
/**
235
 *   Append \c function to this buffer.
236
 */
237
void AsyncBuffer::append(const MessageBufferAppender& f)
238
{
239
  if (!m_priv)
240
    m_priv = std::make_unique<Private>(f);
241
  else
242
    m_priv->data.push_back(f);
243
}
244
#endif // !(defined(__cpp_concepts) && 202002 <= __cpp_concepts
245
246
} // namespace helpers
247
} // namespace LOG4CXX_NS
248