Coverage Report

Created: 2026-03-19 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/cpp/transform.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/logstring.h>
19
#include <log4cxx/helpers/transform.h>
20
#include <log4cxx/helpers/widelife.h>
21
#include <functional>
22
23
using namespace LOG4CXX_NS;
24
using namespace LOG4CXX_NS::helpers;
25
26
namespace
27
{
28
using CharProcessor = std::function<void(LogString&, int)>;
29
30
void appendValidCharacters(LogString& buf, const LogString& input, CharProcessor handler = {})
31
67.5k
{
32
67.5k
  static const logchar specials[] =
33
67.5k
    { 0x22 /* " */
34
67.5k
    , 0x26 /* & */
35
67.5k
    , 0x3C /* < */
36
67.5k
    , 0x3E /* > */
37
67.5k
    , 0x00
38
67.5k
    };
39
67.5k
  size_t start = 0;
40
298M
  for (size_t index = 0; index < input.size(); ++index)
41
298M
  {
42
298M
    int ch = input[index];
43
    // Allowable XML 1.0 characters are:
44
    // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
45
298M
    if (0x20 <= ch && ch <= 0xD7FF)
46
217M
    {
47
217M
      auto pSpecial = &specials[0];
48
498M
      while (*pSpecial && *pSpecial != ch)
49
281M
        ++pSpecial;
50
217M
      if (!*pSpecial)
51
65.4M
        continue;
52
217M
    }
53
81.0M
    else if (0x9 == ch || 0xA == ch || 0xD == ch ||
54
79.9M
        (0xE000 <= ch && ch <= 0xFFFD) ||
55
79.9M
        (0x10000 <= ch && ch <= 0x10FFFF))
56
1.09M
    {
57
1.09M
      continue;
58
1.09M
    }
59
60
232M
    if (start < index)
61
8.51M
      buf.append(input, start, index - start);
62
232M
    start = index + 1;
63
232M
    switch (ch)
64
232M
    {
65
26.7M
      case 0: // Do not output a NUL character
66
26.7M
        break;
67
143M
      case 0x22:
68
143M
        buf.append(LOG4CXX_STR("&quot;"));
69
143M
        break;
70
71
204k
      case 0x26:
72
204k
        buf.append(LOG4CXX_STR("&amp;"));
73
204k
        break;
74
75
5.65M
      case 0x3C:
76
5.65M
        buf.append(LOG4CXX_STR("&lt;"));
77
5.65M
        break;
78
79
2.53M
      case 0x3E:
80
2.53M
        buf.append(LOG4CXX_STR("&gt;"));
81
2.53M
        break;
82
83
53.1M
      default:
84
53.1M
        if (handler)
85
51.7M
          handler(buf, ch);
86
53.1M
        break;
87
232M
    }
88
232M
  }
89
90
67.5k
  if (start < input.size())
91
46.1k
  {
92
46.1k
    buf.append(input, start, input.size() - start);
93
46.1k
  }
94
67.5k
}
95
96
} // namespace
97
98
void Transform::appendEscapingCDATA(
99
  LogString& buf, const LogString& input)
100
0
{
101
0
  static const LogString CDATA_END(LOG4CXX_STR("]]>"));
102
0
  const LogString::size_type CDATA_END_LEN = 3;
103
0
  static const LogString CDATA_EMBEDED_END(LOG4CXX_STR("]]&gt;<![CDATA["));
104
0
  size_t start = 0;
105
0
  for (size_t index = 0; index < input.size(); ++index)
106
0
  {
107
0
    int ch = input[index];
108
0
    bool cdataEnd = false;
109
    // Allowable XML 1.0 characters are:
110
    // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
111
0
    if (0x20 <= ch && ch <= 0xD7FF)
112
0
    {
113
0
      if (CDATA_END[0] == ch &&
114
0
        index + CDATA_END_LEN <= input.size() &&
115
0
        0 == input.compare(index, CDATA_END_LEN, CDATA_END))
116
0
      {
117
0
        index += CDATA_END_LEN;
118
0
        cdataEnd = true;
119
0
      }
120
0
      else
121
0
      {
122
0
        continue;
123
0
      }
124
0
    }
125
0
    else if (0x9 == ch || 0xA == ch || 0xD == ch ||
126
0
        (0xE000 <= ch && ch <= 0xFFFD) ||
127
0
        (0x10000 <= ch && ch <= 0x10FFFF))
128
0
    {
129
0
      continue;
130
0
    }
131
132
0
    if (start < index)
133
0
      buf.append(input, start, index - start);
134
0
    if (cdataEnd)
135
0
    {
136
0
      buf.append(CDATA_EMBEDED_END);
137
0
      --index;
138
0
    }
139
0
    else if (0 != ch)
140
0
      appendCharacterReference(buf, ch);
141
0
    start = index + 1;
142
0
  }
143
144
0
  if (start < input.size())
145
0
    buf.append(input, start, input.size() - start);
146
0
}
147
148
void Transform::appendCharacterReference(LogString& buf, int ch)
149
51.7M
{
150
51.7M
  auto toHexDigit = [](int ch) -> int
151
62.3M
  {
152
62.3M
    return (10 <= ch ? (0x61 - 10) : 0x30) + ch;
153
62.3M
  };
154
51.7M
  buf.push_back('&');
155
51.7M
  buf.push_back('#');
156
51.7M
  buf.push_back('x');
157
51.7M
  if (0xFFFFFFF < ch)
158
0
    buf.push_back(toHexDigit((ch & 0x70000000) >> 28));
159
51.7M
  if (0xFFFFFF < ch)
160
0
    buf.push_back(toHexDigit((ch & 0xF000000) >> 24));
161
51.7M
  if (0xFFFFF < ch)
162
0
    buf.push_back(toHexDigit((ch & 0xF00000) >> 20));
163
51.7M
  if (0xFFFF < ch)
164
0
    buf.push_back(toHexDigit((ch & 0xF0000) >> 16));
165
51.7M
  if (0xFFF < ch)
166
0
    buf.push_back(toHexDigit((ch & 0xF000) >> 12));
167
51.7M
  if (0xFF < ch)
168
0
    buf.push_back(toHexDigit((ch & 0xF00) >> 8));
169
51.7M
  if (0xF < ch)
170
10.6M
    buf.push_back(toHexDigit((ch & 0xF0) >> 4));
171
51.7M
  buf.push_back(toHexDigit(ch & 0xF));
172
51.7M
  buf.push_back(';');
173
51.7M
}
174
175
void Transform::appendEscapingTags(LogString& buf, const LogString& input)
176
48.1k
{
177
48.1k
  appendValidCharacters(buf, input, appendCharacterReference);
178
48.1k
}
179
180
void Transform::appendLegalCharacters(LogString& buf, const LogString& input)
181
19.3k
{
182
19.3k
  appendValidCharacters(buf, input);
183
19.3k
}