Coverage Report

Created: 2025-07-18 06:17

/src/logging-log4cxx/src/main/cpp/nameabbreviator.cpp
Line
Count
Source (jump to first uncovered line)
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/pattern/nameabbreviator.h>
19
#include <log4cxx/helpers/exception.h>
20
#include <log4cxx/helpers/stringhelper.h>
21
#include <log4cxx/helpers/loglog.h>
22
#include <vector>
23
#include <limits.h>
24
#include <stdexcept>
25
26
using namespace LOG4CXX_NS;
27
using namespace LOG4CXX_NS::pattern;
28
using namespace LOG4CXX_NS::helpers;
29
30
IMPLEMENT_LOG4CXX_OBJECT(NameAbbreviator)
31
32
NameAbbreviator::NameAbbreviator()
33
0
{
34
0
}
35
36
NameAbbreviator::~NameAbbreviator()
37
0
{
38
0
}
39
40
namespace LOG4CXX_NS
41
{
42
namespace pattern
43
{
44
/**
45
 * Abbreviator that simply appends full name to buffer.
46
 */
47
class NOPAbbreviator : public NameAbbreviator
48
{
49
  public:
50
    DECLARE_ABSTRACT_LOG4CXX_OBJECT(NOPAbbreviator)
51
0
    BEGIN_LOG4CXX_CAST_MAP()
52
0
    LOG4CXX_CAST_ENTRY(NOPAbbreviator)
53
0
    LOG4CXX_CAST_ENTRY_CHAIN(NameAbbreviator)
54
0
    END_LOG4CXX_CAST_MAP()
55
56
    /**
57
     * Constructor.
58
     */
59
    NOPAbbreviator()
60
0
    {
61
0
    }
62
63
    /**
64
     * {@inheritDoc}
65
     */
66
    void abbreviate(LogString::size_type /* nameStart */, LogString& /* buf */) const override
67
0
    {
68
0
    }
69
};
70
71
72
/**
73
 * Abbreviator that drops starting path elements.
74
 */
75
class MaxElementAbbreviator : public NameAbbreviator
76
{
77
    /**
78
     * Maximum number of path elements to output.
79
     */
80
    const int count;
81
82
  public:
83
    DECLARE_ABSTRACT_LOG4CXX_OBJECT(MaxElementAbbreviator)
84
0
    BEGIN_LOG4CXX_CAST_MAP()
85
0
    LOG4CXX_CAST_ENTRY(MaxElementAbbreviator)
86
0
    LOG4CXX_CAST_ENTRY_CHAIN(NameAbbreviator)
87
0
    END_LOG4CXX_CAST_MAP()
88
    /**
89
     * Create new instance.
90
     * @param count maximum number of path elements to output.
91
     */
92
0
    MaxElementAbbreviator(const int count1) : count(count1)
93
0
    {
94
0
    }
95
96
    /**
97
     * Abbreviate name.
98
     * @param buf buffer to append abbreviation.
99
     * @param nameStart start of name to abbreviate.
100
     */
101
    void abbreviate(LogString::size_type nameStart, LogString& buf) const override
102
0
    {
103
      // We substract 1 from 'len' when assigning to 'end' to avoid out of
104
      // bounds exception in return r.substring(end+1, len). This can happen if
105
      // precision is 1 and the logger name ends with a dot.
106
0
      LogString::size_type end = buf.length() - 1;
107
108
0
      for (LogString::size_type i = count; i > 0; i--)
109
0
      {
110
0
        end = buf.rfind(0x2E /* '.' */, end - 1);
111
112
0
        if ((end == LogString::npos) || (end < nameStart))
113
0
        {
114
0
          return;
115
0
        }
116
0
      }
117
118
0
      buf.erase(buf.begin() + nameStart, buf.begin() + (end + 1));
119
0
    }
120
};
121
122
/**
123
 * Fragment of an pattern abbreviator.
124
 *
125
 */
126
class PatternAbbreviatorFragment
127
{
128
    /**
129
     * Count of initial characters of element to output.
130
     */
131
    LogString::size_type charCount;
132
133
    /**
134
     *  Character used to represent dropped characters.
135
     * '\0' indicates no representation of dropped characters.
136
     */
137
    logchar ellipsis;
138
139
  public:
140
    /**
141
     * Creates a PatternAbbreviatorFragment.
142
     * @param charCount number of initial characters to preserve.
143
     * @param ellipsis character to represent elimination of characters,
144
     *    '\0' if no ellipsis is desired.
145
     */
146
    PatternAbbreviatorFragment(
147
      const int charCount1, const logchar ellipsis1)
148
0
      : charCount(charCount1), ellipsis(ellipsis1)
149
0
    {
150
0
    }
151
    PatternAbbreviatorFragment() : charCount(0), ellipsis(0)
152
0
    {
153
0
    }
154
155
    PatternAbbreviatorFragment(const PatternAbbreviatorFragment& src)
156
0
      : charCount(src.charCount), ellipsis(src.ellipsis)
157
0
    {
158
0
    }
159
160
    PatternAbbreviatorFragment& operator=(const PatternAbbreviatorFragment& src)
161
0
    {
162
0
      charCount = src.charCount;
163
0
      ellipsis = src.ellipsis;
164
0
      return *this;
165
0
    }
166
167
    /**
168
     * Abbreviate element of name.
169
     * @param buf buffer to receive element.
170
     * @param startPos starting index of name element.
171
     * @return starting index of next element.
172
     */
173
    LogString::size_type abbreviate(LogString& buf, LogString::size_type startPos) const
174
0
    {
175
0
      LogString::size_type nextDot = buf.find(0x2E /* '.' */, startPos);
176
177
0
      if (nextDot != LogString::npos)
178
0
      {
179
0
        if ((nextDot - startPos) > charCount)
180
0
        {
181
0
          buf.erase(buf.begin() + (startPos + charCount), buf.begin() + nextDot);
182
0
          nextDot = startPos + charCount;
183
184
0
          if (ellipsis != 0x00)
185
0
          {
186
0
            buf.insert(nextDot, 1, ellipsis);
187
0
            nextDot++;
188
0
          }
189
0
        }
190
191
0
        nextDot++;
192
0
      }
193
194
0
      return nextDot;
195
0
    }
196
};
197
198
/**
199
 * Pattern abbreviator.
200
 *
201
 *
202
 */
203
class PatternAbbreviator : public NameAbbreviator
204
{
205
    /**
206
     * Element abbreviation patterns.
207
     */
208
    std::vector<PatternAbbreviatorFragment> fragments;
209
210
  public:
211
    DECLARE_ABSTRACT_LOG4CXX_OBJECT(PatternAbbreviator)
212
0
    BEGIN_LOG4CXX_CAST_MAP()
213
0
    LOG4CXX_CAST_ENTRY(PatternAbbreviator)
214
0
    LOG4CXX_CAST_ENTRY_CHAIN(NameAbbreviator)
215
0
    END_LOG4CXX_CAST_MAP()
216
    /**
217
     * Create PatternAbbreviator.
218
     *
219
     * @param fragments element abbreviation patterns.
220
     */
221
    PatternAbbreviator(const std::vector<PatternAbbreviatorFragment>& fragments1) :
222
0
      fragments(fragments1)
223
0
    {
224
0
      if (fragments1.size() == 0)
225
0
      {
226
0
        throw IllegalArgumentException(LOG4CXX_STR("fragments parameter must contain at least one element"));
227
0
      }
228
0
    }
229
230
    /**
231
     * Abbreviate name.
232
     * @param buf buffer that abbreviated name is appended.
233
     * @param nameStart start of name.
234
     */
235
    void abbreviate(LogString::size_type nameStart, LogString& buf) const override
236
0
    {
237
      //
238
      //  all non-terminal patterns are executed once
239
      //
240
0
      LogString::size_type pos = nameStart;
241
242
0
      for (LogString::size_type i = 0; (i < (fragments.size() - 1)) && (pos < buf.length());
243
0
        i++)
244
0
      {
245
0
        pos = fragments[i].abbreviate(buf, pos);
246
0
      }
247
248
      //
249
      //   last pattern in executed repeatedly
250
      //
251
0
      PatternAbbreviatorFragment terminalFragment =
252
0
        fragments[fragments.size() - 1];
253
254
0
      while (pos < buf.length())
255
0
      {
256
0
        pos = terminalFragment.abbreviate(buf, pos);
257
0
      }
258
0
    }
259
};
260
}
261
}
262
263
IMPLEMENT_LOG4CXX_OBJECT(NOPAbbreviator)
264
IMPLEMENT_LOG4CXX_OBJECT(MaxElementAbbreviator)
265
IMPLEMENT_LOG4CXX_OBJECT(PatternAbbreviator)
266
267
268
269
NameAbbreviatorPtr NameAbbreviator::getAbbreviator(const LogString& pattern)
270
0
{
271
0
  if (pattern.length() > 0)
272
0
  {
273
    //  if pattern is just spaces and numbers then
274
    //     use MaxElementAbbreviator
275
0
    LogString trimmed(StringHelper::trim(pattern));
276
277
0
    if (trimmed.length() == 0)
278
0
    {
279
0
      return getDefaultAbbreviator();
280
0
    }
281
282
0
    LogString::size_type i = 0;
283
284
0
    while (
285
0
      (i < trimmed.length()) && (trimmed[i] >= 0x30 /* '0' */)
286
0
      && (trimmed[i] <= 0x39 /* '9' */))
287
0
    {
288
0
      i++;
289
0
    }
290
291
    //
292
    //  if all blanks and digits
293
    //
294
0
    if (i == trimmed.length())
295
0
    {
296
0
      int len = 256;
297
0
      try
298
0
      {
299
0
        len = StringHelper::toInt(trimmed);
300
0
      }
301
0
      catch (const std::out_of_range& ex)
302
0
      {
303
0
        LogLog::warn(LOG4CXX_STR("Invalid name abreviator pattern: ") + pattern, ex);
304
0
      }
305
306
0
      if(len > 256){
307
0
        len = 256;
308
0
      }else if( len < 0 ){
309
0
        len = 0;
310
0
      }
311
312
0
      return std::make_shared<MaxElementAbbreviator>(len);
313
0
    }
314
315
0
    std::vector<PatternAbbreviatorFragment> fragments;
316
0
    logchar ellipsis;
317
0
    int charCount;
318
0
    LogString::size_type pos = 0;
319
320
0
    while (pos < trimmed.length())
321
0
    {
322
0
      LogString::size_type ellipsisPos = pos;
323
324
0
      if (trimmed[pos] == 0x2A /* '*' */)
325
0
      {
326
0
        charCount = INT_MAX;
327
0
        ellipsisPos++;
328
0
      }
329
0
      else
330
0
      {
331
0
        if ((trimmed[pos] >= 0x30 /* '0' */)
332
0
          && (trimmed[pos] <= 0x39 /* '9' */))
333
0
        {
334
0
          charCount = trimmed[pos] - 0x30 /* '0' */;
335
0
          ellipsisPos++;
336
0
        }
337
0
        else
338
0
        {
339
0
          charCount = 0;
340
0
        }
341
0
      }
342
343
0
      ellipsis = 0;
344
345
0
      if (ellipsisPos < trimmed.length())
346
0
      {
347
0
        ellipsis = trimmed[ellipsisPos];
348
349
0
        if (ellipsis == 0x2E /* '.' */)
350
0
        {
351
0
          ellipsis = 0;
352
0
        }
353
0
      }
354
355
0
      fragments.push_back(PatternAbbreviatorFragment(charCount, ellipsis));
356
0
      pos = trimmed.find(0x2E /* '.' */, pos);
357
358
0
      if (pos == LogString::npos)
359
0
      {
360
0
        break;
361
0
      }
362
363
0
      pos++;
364
0
    }
365
366
0
    return std::make_shared<PatternAbbreviator>(fragments);
367
0
  }
368
369
  //
370
  //  no matching abbreviation, return defaultAbbreviator
371
  //
372
0
  return getDefaultAbbreviator();
373
0
}
374
375
/**
376
 * Gets default abbreviator.
377
 *
378
 * @return default abbreviator.
379
 */
380
NameAbbreviatorPtr NameAbbreviator::getDefaultAbbreviator()
381
0
{
382
0
  static WideLife<NameAbbreviatorPtr> def = std::make_shared<NOPAbbreviator>();
383
0
  return def;
384
0
}
385