Coverage Report

Created: 2026-02-26 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/cpp/timezone.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
#define __STDC_CONSTANT_MACROS
19
#include <log4cxx/logstring.h>
20
#include <log4cxx/helpers/timezone.h>
21
#include <stdlib.h>
22
23
#include <apr_time.h>
24
#include <apr_pools.h>
25
#include <apr_strings.h>
26
#include <log4cxx/helpers/exception.h>
27
#include <log4cxx/helpers/transcoder.h>
28
#include <log4cxx/helpers/stringhelper.h>
29
#include <log4cxx/helpers/pool.h>
30
#include <log4cxx/logger.h>
31
32
using namespace LOG4CXX_NS;
33
using namespace LOG4CXX_NS::helpers;
34
35
IMPLEMENT_LOG4CXX_OBJECT( TimeZone )
36
37
namespace LOG4CXX_NS
38
{
39
namespace helpers
40
{
41
namespace TimeZoneImpl
42
{
43
/** Time zone object that represents GMT. */
44
class GMTTimeZone : public TimeZone
45
{
46
  public:
47
    /** Class factory. */
48
    static const TimeZonePtr& getInstance()
49
15.9k
    {
50
15.9k
      static WideLife<TimeZonePtr> tz = std::make_shared<GMTTimeZone>();
51
15.9k
      return tz;
52
15.9k
    }
53
54
    /** Explode time to human readable form. */
55
    log4cxx_status_t explode( apr_time_exp_t* result, log4cxx_time_t input ) const
56
27.4k
    {
57
27.4k
      apr_status_t stat;
58
59
      //  APR 1.1 and early mishandles microseconds on dates
60
      //   before 1970, APR bug 32520
61
27.4k
      if (LOG4CXX_UNLIKELY(input < 0 && apr_time_usec(input) < 0))
62
0
      {
63
0
        apr_time_t floorTime = (apr_time_sec(input) - 1) * APR_USEC_PER_SEC;
64
0
        stat = apr_time_exp_gmt(result, floorTime);
65
0
        result->tm_usec = (int) (input - floorTime);
66
0
      }
67
27.4k
      else
68
27.4k
      {
69
27.4k
        stat = apr_time_exp_gmt( result, input );
70
27.4k
      }
71
72
27.4k
      return stat;
73
27.4k
    }
74
75
6
    GMTTimeZone() : TimeZone( LOG4CXX_STR("GMT") )
76
6
    {
77
6
    }
78
};
79
80
81
82
/** Time zone object that represents GMT. */
83
class LocalTimeZone : public TimeZone
84
{
85
  public:
86
    /** Class factory. */
87
    static const TimeZonePtr& getInstance()
88
153k
    {
89
153k
      static WideLife<TimeZonePtr> tz = std::make_shared<LocalTimeZone>();
90
153k
      return tz;
91
153k
    }
92
93
    /** Explode time to human readable form. */
94
    log4cxx_status_t explode( apr_time_exp_t* result, log4cxx_time_t input ) const
95
19.3k
    {
96
19.3k
      apr_status_t stat;
97
98
      //  APR 1.1 and early mishandles microseconds on dates
99
      //   before 1970, APR bug 32520
100
19.3k
      if (LOG4CXX_UNLIKELY(input < 0 && apr_time_usec(input) < 0))
101
0
      {
102
0
        apr_time_t floorTime = (apr_time_sec(input) - 1) * APR_USEC_PER_SEC;
103
0
        stat = apr_time_exp_lt(result, floorTime);
104
0
        result->tm_usec = (int) (input - floorTime);
105
0
      }
106
19.3k
      else
107
19.3k
      {
108
19.3k
        stat = apr_time_exp_lt( result, input );
109
19.3k
      }
110
111
19.3k
      return stat;
112
19.3k
    }
113
114
115
9
    LocalTimeZone() : TimeZone( getTimeZoneName() )
116
9
    {
117
9
    }
118
119
  private:
120
    static const LogString getTimeZoneName()
121
18
    {
122
18
      const int MAX_TZ_LENGTH = 255;
123
18
      char tzName[MAX_TZ_LENGTH];
124
18
      apr_size_t tzLength;
125
18
      apr_time_exp_t tm;
126
18
      apr_time_exp_lt(&tm, 0);
127
18
      apr_strftime(tzName, &tzLength, MAX_TZ_LENGTH, "%Z", &tm);
128
129
18
      if (tzLength == 0)
130
0
      {
131
0
        apr_strftime(tzName, &tzLength, MAX_TZ_LENGTH, "%z", &tm);
132
0
      }
133
134
18
      tzName[tzLength] = 0;
135
18
      LogString retval;
136
18
      LOG4CXX_NS::helpers::Transcoder::decode(tzName, retval);
137
18
      return retval;
138
18
    }
log4cxx::helpers::TimeZoneImpl::LocalTimeZone::getTimeZoneName()
Line
Count
Source
121
9
    {
122
9
      const int MAX_TZ_LENGTH = 255;
123
9
      char tzName[MAX_TZ_LENGTH];
124
9
      apr_size_t tzLength;
125
9
      apr_time_exp_t tm;
126
9
      apr_time_exp_lt(&tm, 0);
127
9
      apr_strftime(tzName, &tzLength, MAX_TZ_LENGTH, "%Z", &tm);
128
129
9
      if (tzLength == 0)
130
0
      {
131
0
        apr_strftime(tzName, &tzLength, MAX_TZ_LENGTH, "%z", &tm);
132
0
      }
133
134
9
      tzName[tzLength] = 0;
135
9
      LogString retval;
136
9
      LOG4CXX_NS::helpers::Transcoder::decode(tzName, retval);
137
9
      return retval;
138
9
    }
log4cxx::helpers::TimeZoneImpl::LocalTimeZone::getTimeZoneName()
Line
Count
Source
121
9
    {
122
9
      const int MAX_TZ_LENGTH = 255;
123
9
      char tzName[MAX_TZ_LENGTH];
124
9
      apr_size_t tzLength;
125
9
      apr_time_exp_t tm;
126
9
      apr_time_exp_lt(&tm, 0);
127
9
      apr_strftime(tzName, &tzLength, MAX_TZ_LENGTH, "%Z", &tm);
128
129
9
      if (tzLength == 0)
130
0
      {
131
0
        apr_strftime(tzName, &tzLength, MAX_TZ_LENGTH, "%z", &tm);
132
0
      }
133
134
9
      tzName[tzLength] = 0;
135
9
      LogString retval;
136
9
      LOG4CXX_NS::helpers::Transcoder::decode(tzName, retval);
137
9
      return retval;
138
9
    }
139
140
};
141
142
143
144
/** Time zone object that represents a fixed offset from GMT. */
145
class FixedTimeZone : public TimeZone
146
{
147
  public:
148
7.50k
    FixedTimeZone( const LogString& name, apr_int32_t offset1 ) : TimeZone( name ), offset( offset1 )
149
7.50k
    {
150
7.50k
    }
log4cxx::helpers::TimeZoneImpl::FixedTimeZone::FixedTimeZone(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int)
Line
Count
Source
148
4.46k
    FixedTimeZone( const LogString& name, apr_int32_t offset1 ) : TimeZone( name ), offset( offset1 )
149
4.46k
    {
150
4.46k
    }
log4cxx::helpers::TimeZoneImpl::FixedTimeZone::FixedTimeZone(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&, int)
Line
Count
Source
148
3.03k
    FixedTimeZone( const LogString& name, apr_int32_t offset1 ) : TimeZone( name ), offset( offset1 )
149
3.03k
    {
150
3.03k
    }
151
152
    /** Explode time to human readable form. */
153
    log4cxx_status_t explode( apr_time_exp_t* result, log4cxx_time_t input ) const
154
1.26k
    {
155
1.26k
      apr_status_t stat;
156
157
      //  APR 1.1 and early mishandles microseconds on dates
158
      //   before 1970, APR bug 32520
159
1.26k
      if (LOG4CXX_UNLIKELY(input < 0 && apr_time_usec(input) < 0))
160
0
      {
161
0
        apr_time_t floorTime = (apr_time_sec(input) - 1) * APR_USEC_PER_SEC;
162
0
        stat = apr_time_exp_tz(result, floorTime, offset);
163
0
        result->tm_usec = (int) (input - floorTime);
164
0
      }
165
1.26k
      else
166
1.26k
      {
167
1.26k
        stat = apr_time_exp_tz( result, input, offset );
168
1.26k
      }
169
170
1.26k
      return stat;
171
1.26k
    }
172
173
174
  private:
175
    const apr_int32_t offset;
176
};
177
178
}
179
}
180
}
181
182
183
184
7.51k
TimeZone::TimeZone( const LogString& id1 ) : id( id1 )
185
7.51k
{
186
7.51k
}
log4cxx::helpers::TimeZone::TimeZone(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
184
4.47k
TimeZone::TimeZone( const LogString& id1 ) : id( id1 )
185
4.47k
{
186
4.47k
}
log4cxx::helpers::TimeZone::TimeZone(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
Line
Count
Source
184
3.04k
TimeZone::TimeZone( const LogString& id1 ) : id( id1 )
185
3.04k
{
186
3.04k
}
187
188
TimeZone::~TimeZone()
189
7.51k
{
190
7.51k
}
191
192
const TimeZonePtr& TimeZone::getDefault()
193
307k
{
194
307k
  return LOG4CXX_NS::helpers::TimeZoneImpl::LocalTimeZone::getInstance();
195
307k
}
log4cxx::helpers::TimeZone::getDefault()
Line
Count
Source
193
153k
{
194
153k
  return LOG4CXX_NS::helpers::TimeZoneImpl::LocalTimeZone::getInstance();
195
153k
}
log4cxx::helpers::TimeZone::getDefault()
Line
Count
Source
193
153k
{
194
153k
  return LOG4CXX_NS::helpers::TimeZoneImpl::LocalTimeZone::getInstance();
195
153k
}
196
197
const TimeZonePtr& TimeZone::getGMT()
198
30.9k
{
199
30.9k
  return LOG4CXX_NS::helpers::TimeZoneImpl::GMTTimeZone::getInstance();
200
30.9k
}
log4cxx::helpers::TimeZone::getGMT()
Line
Count
Source
198
15.4k
{
199
15.4k
  return LOG4CXX_NS::helpers::TimeZoneImpl::GMTTimeZone::getInstance();
200
15.4k
}
log4cxx::helpers::TimeZone::getGMT()
Line
Count
Source
198
15.4k
{
199
15.4k
  return LOG4CXX_NS::helpers::TimeZoneImpl::GMTTimeZone::getInstance();
200
15.4k
}
201
202
const TimeZonePtr TimeZone::getTimeZone( const LogString& id )
203
28.3k
{
204
28.3k
  const logchar gmt[] = { 0x47, 0x4D, 0x54, 0 };
205
206
28.3k
  if ( id == gmt )
207
426
  {
208
426
    return LOG4CXX_NS::helpers::TimeZoneImpl::GMTTimeZone::getInstance();
209
426
  }
210
211
27.9k
  if ( id.length() >= 5 && id.substr( 0, 3 ) == gmt )
212
19.4k
  {
213
19.4k
    int hours = 0;
214
19.4k
    int minutes = 0;
215
19.4k
    int sign = 1;
216
217
19.4k
    if (id[3] == 0x2D /* '-' */)
218
4.10k
    {
219
4.10k
      sign = -1;
220
4.10k
    }
221
222
19.4k
    LogString off( id.substr( 4 ) );
223
224
19.4k
    if ( id.length() >= 7 )
225
13.4k
    {
226
13.4k
      size_t colonPos = off.find( 0x3A /* ':' */);
227
228
13.4k
      if ( colonPos == LogString::npos )
229
6.23k
      {
230
6.23k
        minutes = StringHelper::toInt(off.substr(off.length() - 2));
231
6.23k
        hours = StringHelper::toInt(off.substr(0, off.length() - 2));
232
6.23k
      }
233
7.25k
      else
234
7.25k
      {
235
7.25k
        minutes = StringHelper::toInt(off.substr(colonPos + 1));
236
7.25k
        hours = StringHelper::toInt(off.substr(0, colonPos));
237
7.25k
      }
238
13.4k
    }
239
5.93k
    else
240
5.93k
    {
241
5.93k
      hours = StringHelper::toInt(off);
242
5.93k
    }
243
244
    // Make sure that our offset can't be crazy
245
19.4k
    if( hours < -12 || 14 < hours)
246
1.86k
    {
247
1.86k
      throw RuntimeException(LOG4CXX_STR("Hour offset must be in (-12..14)"));
248
1.86k
    }
249
17.5k
    if (minutes < 0 || 60 < minutes)
250
1.18k
    {
251
1.18k
      throw RuntimeException(LOG4CXX_STR("Minute offset must be in (0..60)"));
252
1.18k
    }
253
254
16.3k
    LogString s(gmt);
255
16.3k
    Pool p;
256
16.3k
    LogString hh;
257
16.3k
    StringHelper::toString(hours, p, hh);
258
259
16.3k
    if (sign > 0)
260
5.53k
    {
261
5.53k
      s.append(1, (logchar) 0x2B /* '+' */);
262
5.53k
    }
263
10.8k
    else
264
10.8k
    {
265
10.8k
      s.append(1, (logchar) 0x2D /* '-' */);
266
10.8k
    }
267
268
16.3k
    if (hh.length() == 1)
269
6.09k
    {
270
6.09k
      s.append(1, (logchar) 0x30 /* '0' */);
271
6.09k
    }
272
273
16.3k
    s.append(hh);
274
16.3k
    s.append(1, (logchar) 0x3A /*' :' */);
275
16.3k
    LogString mm;
276
16.3k
    StringHelper::toString(minutes, p, mm);
277
278
16.3k
    if (mm.length() == 1)
279
6.34k
    {
280
6.34k
      s.append(1, (logchar) 0x30 /* '0' */);
281
6.34k
    }
282
283
16.3k
    s.append(mm);
284
16.3k
    apr_int32_t offset = sign * (hours * 3600 + minutes * 60);
285
16.3k
    return std::make_shared<helpers::TimeZoneImpl::FixedTimeZone>( s, offset );
286
17.5k
  }
287
288
8.50k
  const TimeZonePtr& ltz = getDefault();
289
290
8.50k
  if ( ltz->getID() == id )
291
774
  {
292
774
    return ltz;
293
774
  }
294
295
7.72k
  return getGMT();
296
8.50k
}
log4cxx::helpers::TimeZone::getTimeZone(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
203
13.2k
{
204
13.2k
  const logchar gmt[] = { 0x47, 0x4D, 0x54, 0 };
205
206
13.2k
  if ( id == gmt )
207
226
  {
208
226
    return LOG4CXX_NS::helpers::TimeZoneImpl::GMTTimeZone::getInstance();
209
226
  }
210
211
13.0k
  if ( id.length() >= 5 && id.substr( 0, 3 ) == gmt )
212
9.65k
  {
213
9.65k
    int hours = 0;
214
9.65k
    int minutes = 0;
215
9.65k
    int sign = 1;
216
217
9.65k
    if (id[3] == 0x2D /* '-' */)
218
1.24k
    {
219
1.24k
      sign = -1;
220
1.24k
    }
221
222
9.65k
    LogString off( id.substr( 4 ) );
223
224
9.65k
    if ( id.length() >= 7 )
225
6.91k
    {
226
6.91k
      size_t colonPos = off.find( 0x3A /* ':' */);
227
228
6.91k
      if ( colonPos == LogString::npos )
229
3.14k
      {
230
3.14k
        minutes = StringHelper::toInt(off.substr(off.length() - 2));
231
3.14k
        hours = StringHelper::toInt(off.substr(0, off.length() - 2));
232
3.14k
      }
233
3.77k
      else
234
3.77k
      {
235
3.77k
        minutes = StringHelper::toInt(off.substr(colonPos + 1));
236
3.77k
        hours = StringHelper::toInt(off.substr(0, colonPos));
237
3.77k
      }
238
6.91k
    }
239
2.73k
    else
240
2.73k
    {
241
2.73k
      hours = StringHelper::toInt(off);
242
2.73k
    }
243
244
    // Make sure that our offset can't be crazy
245
9.65k
    if( hours < -12 || 14 < hours)
246
811
    {
247
811
      throw RuntimeException(LOG4CXX_STR("Hour offset must be in (-12..14)"));
248
811
    }
249
8.84k
    if (minutes < 0 || 60 < minutes)
250
632
    {
251
632
      throw RuntimeException(LOG4CXX_STR("Minute offset must be in (0..60)"));
252
632
    }
253
254
8.21k
    LogString s(gmt);
255
8.21k
    Pool p;
256
8.21k
    LogString hh;
257
8.21k
    StringHelper::toString(hours, p, hh);
258
259
8.21k
    if (sign > 0)
260
3.67k
    {
261
3.67k
      s.append(1, (logchar) 0x2B /* '+' */);
262
3.67k
    }
263
4.53k
    else
264
4.53k
    {
265
4.53k
      s.append(1, (logchar) 0x2D /* '-' */);
266
4.53k
    }
267
268
8.21k
    if (hh.length() == 1)
269
3.57k
    {
270
3.57k
      s.append(1, (logchar) 0x30 /* '0' */);
271
3.57k
    }
272
273
8.21k
    s.append(hh);
274
8.21k
    s.append(1, (logchar) 0x3A /*' :' */);
275
8.21k
    LogString mm;
276
8.21k
    StringHelper::toString(minutes, p, mm);
277
278
8.21k
    if (mm.length() == 1)
279
3.77k
    {
280
3.77k
      s.append(1, (logchar) 0x30 /* '0' */);
281
3.77k
    }
282
283
8.21k
    s.append(mm);
284
8.21k
    apr_int32_t offset = sign * (hours * 3600 + minutes * 60);
285
8.21k
    return std::make_shared<helpers::TimeZoneImpl::FixedTimeZone>( s, offset );
286
8.84k
  }
287
288
3.39k
  const TimeZonePtr& ltz = getDefault();
289
290
3.39k
  if ( ltz->getID() == id )
291
762
  {
292
762
    return ltz;
293
762
  }
294
295
2.63k
  return getGMT();
296
3.39k
}
log4cxx::helpers::TimeZone::getTimeZone(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
Line
Count
Source
203
15.0k
{
204
15.0k
  const logchar gmt[] = { 0x47, 0x4D, 0x54, 0 };
205
206
15.0k
  if ( id == gmt )
207
200
  {
208
200
    return LOG4CXX_NS::helpers::TimeZoneImpl::GMTTimeZone::getInstance();
209
200
  }
210
211
14.8k
  if ( id.length() >= 5 && id.substr( 0, 3 ) == gmt )
212
9.77k
  {
213
9.77k
    int hours = 0;
214
9.77k
    int minutes = 0;
215
9.77k
    int sign = 1;
216
217
9.77k
    if (id[3] == 0x2D /* '-' */)
218
2.85k
    {
219
2.85k
      sign = -1;
220
2.85k
    }
221
222
9.77k
    LogString off( id.substr( 4 ) );
223
224
9.77k
    if ( id.length() >= 7 )
225
6.57k
    {
226
6.57k
      size_t colonPos = off.find( 0x3A /* ':' */);
227
228
6.57k
      if ( colonPos == LogString::npos )
229
3.09k
      {
230
3.09k
        minutes = StringHelper::toInt(off.substr(off.length() - 2));
231
3.09k
        hours = StringHelper::toInt(off.substr(0, off.length() - 2));
232
3.09k
      }
233
3.48k
      else
234
3.48k
      {
235
3.48k
        minutes = StringHelper::toInt(off.substr(colonPos + 1));
236
3.48k
        hours = StringHelper::toInt(off.substr(0, colonPos));
237
3.48k
      }
238
6.57k
    }
239
3.20k
    else
240
3.20k
    {
241
3.20k
      hours = StringHelper::toInt(off);
242
3.20k
    }
243
244
    // Make sure that our offset can't be crazy
245
9.77k
    if( hours < -12 || 14 < hours)
246
1.05k
    {
247
1.05k
      throw RuntimeException(LOG4CXX_STR("Hour offset must be in (-12..14)"));
248
1.05k
    }
249
8.71k
    if (minutes < 0 || 60 < minutes)
250
550
    {
251
550
      throw RuntimeException(LOG4CXX_STR("Minute offset must be in (0..60)"));
252
550
    }
253
254
8.16k
    LogString s(gmt);
255
8.16k
    Pool p;
256
8.16k
    LogString hh;
257
8.16k
    StringHelper::toString(hours, p, hh);
258
259
8.16k
    if (sign > 0)
260
1.85k
    {
261
1.85k
      s.append(1, (logchar) 0x2B /* '+' */);
262
1.85k
    }
263
6.31k
    else
264
6.31k
    {
265
6.31k
      s.append(1, (logchar) 0x2D /* '-' */);
266
6.31k
    }
267
268
8.16k
    if (hh.length() == 1)
269
2.52k
    {
270
2.52k
      s.append(1, (logchar) 0x30 /* '0' */);
271
2.52k
    }
272
273
8.16k
    s.append(hh);
274
8.16k
    s.append(1, (logchar) 0x3A /*' :' */);
275
8.16k
    LogString mm;
276
8.16k
    StringHelper::toString(minutes, p, mm);
277
278
8.16k
    if (mm.length() == 1)
279
2.56k
    {
280
2.56k
      s.append(1, (logchar) 0x30 /* '0' */);
281
2.56k
    }
282
283
8.16k
    s.append(mm);
284
8.16k
    apr_int32_t offset = sign * (hours * 3600 + minutes * 60);
285
8.16k
    return std::make_shared<helpers::TimeZoneImpl::FixedTimeZone>( s, offset );
286
8.71k
  }
287
288
5.10k
  const TimeZonePtr& ltz = getDefault();
289
290
5.10k
  if ( ltz->getID() == id )
291
12
  {
292
12
    return ltz;
293
12
  }
294
295
5.09k
  return getGMT();
296
5.10k
}
297