Coverage Report

Created: 2026-05-16 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/log4cplus/src/ndc.cxx
Line
Count
Source
1
// Module:  Log4CPLUS
2
// File:    ndc.cxx
3
// Created: 6/2001
4
// Author:  Tad E. Smith
5
//
6
//
7
// Copyright 2001-2017 Tad E. Smith
8
//
9
// Licensed under the Apache License, Version 2.0 (the "License");
10
// you may not use this file except in compliance with the License.
11
// You may obtain a copy of the License at
12
//
13
//     http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software
16
// distributed under the License is distributed on an "AS IS" BASIS,
17
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
// See the License for the specific language governing permissions and
19
// limitations under the License.
20
21
#include <log4cplus/ndc.h>
22
#include <log4cplus/internal/internal.h>
23
#include <utility>
24
#include <algorithm>
25
26
#if defined (LOG4CPLUS_WITH_UNIT_TESTS)
27
#include <catch.hpp>
28
#endif
29
30
31
namespace log4cplus
32
{
33
34
35
36
///////////////////////////////////////////////////////////////////////////////
37
// log4cplus::DiagnosticContext ctors
38
///////////////////////////////////////////////////////////////////////////////
39
40
41
namespace
42
{
43
44
45
static
46
void
47
init_full_message (log4cplus::tstring & fullMessage,
48
    log4cplus::tstring const & message, DiagnosticContext const * parent)
49
0
{
50
0
    if (parent)
51
0
    {
52
0
        fullMessage.reserve (parent->fullMessage.size () + 1
53
0
            + message.size ());
54
0
        fullMessage = parent->fullMessage;
55
0
        fullMessage += LOG4CPLUS_TEXT(" ");
56
0
        fullMessage += message;
57
0
    }
58
0
    else
59
0
        fullMessage = message;
60
0
}
61
62
63
} // namespace
64
65
66
DiagnosticContext::DiagnosticContext(const log4cplus::tstring& message_,
67
                                     DiagnosticContext const * parent)
68
0
    : message(message_)
69
0
    , fullMessage()
70
0
{
71
0
    init_full_message (fullMessage, message, parent);
72
0
}
73
74
75
DiagnosticContext::DiagnosticContext(tchar const * message_,
76
                                     DiagnosticContext const * parent)
77
0
    : message(message_)
78
0
    , fullMessage()
79
0
{
80
0
    init_full_message (fullMessage, message, parent);
81
0
}
82
83
84
DiagnosticContext::DiagnosticContext(const log4cplus::tstring& message_)
85
0
    : message(message_)
86
0
    , fullMessage(message)
87
0
{
88
0
}
89
90
91
DiagnosticContext::DiagnosticContext(tchar const * message_)
92
0
    : message(message_)
93
0
    , fullMessage(message)
94
0
{
95
0
}
96
97
98
DiagnosticContext::DiagnosticContext (DiagnosticContext const & other)
99
0
    : message (other.message)
100
0
    , fullMessage (other.fullMessage)
101
0
{ }
102
103
104
DiagnosticContext & DiagnosticContext::operator = (
105
    DiagnosticContext const & other)
106
0
{
107
0
    DiagnosticContext (other).swap (*this);
108
0
    return *this;
109
0
}
110
111
112
DiagnosticContext::DiagnosticContext (DiagnosticContext && other)
113
0
    : message (std::move (other.message))
114
0
    , fullMessage (std::move (other.fullMessage))
115
0
{ }
116
117
118
DiagnosticContext &
119
DiagnosticContext::operator = (DiagnosticContext && other)
120
0
{
121
0
    DiagnosticContext (std::move (other)).swap (*this);
122
0
    return *this;
123
0
}
124
125
126
void
127
DiagnosticContext::swap (DiagnosticContext & other)
128
0
{
129
0
    using std::swap;
130
0
    swap (message, other.message);
131
0
    swap (fullMessage, other.fullMessage);
132
0
}
133
134
///////////////////////////////////////////////////////////////////////////////
135
// log4cplus::NDC ctor and dtor
136
///////////////////////////////////////////////////////////////////////////////
137
138
NDC::NDC()
139
68
{ }
140
141
142
NDC::~NDC()
143
0
{ }
144
145
146
147
///////////////////////////////////////////////////////////////////////////////
148
// log4cplus::NDC public methods
149
///////////////////////////////////////////////////////////////////////////////
150
151
void
152
NDC::clear()
153
0
{
154
0
    DiagnosticContextStack* ptr = getPtr();
155
0
    DiagnosticContextStack ().swap (*ptr);
156
0
}
157
158
159
void
160
NDC::remove()
161
0
{
162
0
    clear();
163
0
}
164
165
166
DiagnosticContextStack
167
NDC::cloneStack() const
168
0
{
169
0
    DiagnosticContextStack* ptr = getPtr();
170
0
    return DiagnosticContextStack(*ptr);
171
0
}
172
173
174
void
175
NDC::inherit(const DiagnosticContextStack& stack)
176
0
{
177
0
    DiagnosticContextStack* ptr = getPtr();
178
0
    DiagnosticContextStack (stack).swap (*ptr);
179
0
}
180
181
182
log4cplus::tstring const &
183
NDC::get() const
184
0
{
185
0
    DiagnosticContextStack* ptr = getPtr();
186
0
    if(!ptr->empty())
187
0
        return ptr->back().fullMessage;
188
0
    else
189
0
        return internal::empty_str;
190
0
}
191
192
193
std::size_t
194
NDC::getDepth() const
195
0
{
196
0
    DiagnosticContextStack* ptr = getPtr();
197
0
    return ptr->size();
198
0
}
199
200
201
log4cplus::tstring
202
NDC::pop()
203
0
{
204
0
    DiagnosticContextStack* ptr = getPtr();
205
0
    if(!ptr->empty())
206
0
    {
207
0
        tstring message;
208
0
        message.swap (ptr->back ().message);
209
0
        ptr->pop_back();
210
0
        return message;
211
0
    }
212
0
    else
213
0
        return log4cplus::tstring ();
214
0
}
215
216
217
void
218
NDC::pop_void ()
219
0
{
220
0
    DiagnosticContextStack* ptr = getPtr ();
221
0
    if (! ptr->empty ())
222
0
        ptr->pop_back ();
223
0
}
224
225
226
log4cplus::tstring const &
227
NDC::peek() const
228
0
{
229
0
    DiagnosticContextStack* ptr = getPtr();
230
0
    if(!ptr->empty())
231
0
        return ptr->back().message;
232
0
    else
233
0
        return internal::empty_str;
234
0
}
235
236
237
void
238
NDC::push(const log4cplus::tstring& message)
239
0
{
240
0
    push_worker (message);
241
0
}
242
243
244
void
245
NDC::push(tchar const * message)
246
0
{
247
0
    push_worker (message);
248
0
}
249
250
251
template <typename StringType>
252
void
253
NDC::push_worker (StringType const & message)
254
0
{
255
0
    DiagnosticContextStack* ptr = getPtr();
256
0
    if (ptr->empty())
257
0
        ptr->push_back( DiagnosticContext(message, nullptr) );
258
0
    else
259
0
    {
260
0
        DiagnosticContext const & dc = ptr->back();
261
0
        ptr->push_back( DiagnosticContext(message, &dc) );
262
0
    }
263
0
}
Unexecuted instantiation: void log4cplus::NDC::push_worker<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: void log4cplus::NDC::push_worker<char const*>(char const* const&)
264
265
266
void
267
NDC::setMaxDepth(std::size_t maxDepth)
268
0
{
269
0
    DiagnosticContextStack* ptr = getPtr();
270
0
    while(maxDepth < ptr->size())
271
0
        ptr->pop_back();
272
0
}
273
274
275
DiagnosticContextStack* NDC::getPtr()
276
0
{
277
0
    internal::per_thread_data * ptd = internal::get_ptd ();
278
0
    return &ptd->ndc_dcs;
279
0
}
280
281
282
//
283
//
284
//
285
286
NDCContextCreator::NDCContextCreator(const log4cplus::tstring& msg)
287
0
{
288
0
    getNDC().push(msg);
289
0
}
290
291
292
NDCContextCreator::NDCContextCreator(tchar const * msg)
293
0
{
294
0
    getNDC().push(msg);
295
0
}
296
297
298
NDCContextCreator::~NDCContextCreator()
299
0
{
300
0
    getNDC().pop_void();
301
0
}
302
303
304
#if defined (LOG4CPLUS_WITH_UNIT_TESTS)
305
CATCH_TEST_CASE ("NDC", "[NDC]")
306
{
307
    NDC & ndc = getNDC ();
308
    ndc.clear ();
309
    static tchar const CONTEXT1[] = LOG4CPLUS_TEXT ("c1");
310
    static tchar const CONTEXT2[] = LOG4CPLUS_TEXT ("c2");
311
    static tchar const CONTEXT3[] = LOG4CPLUS_TEXT ("c3");
312
    static tstring const C1C2 = tstring (CONTEXT1)
313
        + LOG4CPLUS_TEXT (' ')
314
        + CONTEXT2;
315
    static tstring const C1C2C3 = C1C2
316
        + LOG4CPLUS_TEXT (' ')
317
        + CONTEXT3;
318
319
    CATCH_SECTION ("basic")
320
    {
321
        CATCH_REQUIRE (ndc.get ().empty ());
322
        CATCH_REQUIRE (ndc.peek ().empty ());
323
        CATCH_REQUIRE (ndc.getDepth () == 0);
324
        NDCContextCreator c1 (CONTEXT1);
325
        CATCH_REQUIRE (ndc.peek () == CONTEXT1);
326
        CATCH_REQUIRE (ndc.get () == CONTEXT1);
327
        CATCH_REQUIRE (ndc.getDepth () == 1);
328
        {
329
            NDCContextCreator c2 (LOG4CPLUS_C_STR_TO_TSTRING (CONTEXT2));
330
            CATCH_REQUIRE (ndc.get () == C1C2);
331
            CATCH_REQUIRE (ndc.getDepth () == 2);
332
            CATCH_REQUIRE (ndc.peek () == CONTEXT2);
333
334
            ndc.push (CONTEXT3);
335
            CATCH_REQUIRE (ndc.get () == C1C2C3);
336
            CATCH_REQUIRE (ndc.peek () == CONTEXT3);
337
            CATCH_REQUIRE (ndc.pop () == CONTEXT3);
338
        }
339
        CATCH_REQUIRE (ndc.peek () == CONTEXT1);
340
        CATCH_REQUIRE (ndc.get () == CONTEXT1);
341
        CATCH_REQUIRE (ndc.getDepth () == 1);
342
    }
343
344
    CATCH_SECTION ("remove")
345
    {
346
        ndc.push (CONTEXT1);
347
        CATCH_REQUIRE (ndc.peek () == CONTEXT1);
348
        CATCH_REQUIRE (ndc.get () == CONTEXT1);
349
        CATCH_REQUIRE (ndc.getDepth () == 1);
350
351
        ndc.remove ();
352
        CATCH_REQUIRE (ndc.get ().empty ());
353
        CATCH_REQUIRE (ndc.peek ().empty ());
354
        CATCH_REQUIRE (ndc.getDepth () == 0);
355
    }
356
}
357
358
#endif
359
360
} // namespace log4cplus