Coverage Report

Created: 2023-06-07 06:06

/src/open62541/deps/libc_time.c
Line
Count
Source (jump to first uncovered line)
1
/* Originally released by the musl project (http://www.musl-libc.org/) under the
2
 * MIT license. Taken from the file /src/time/__secs_to_tm.c */
3
4
#include <limits.h>
5
#include "libc_time.h"
6
7
/* 2000-03-01 (mod 400 year, immediately after feb29 */
8
145
#define LEAPOCH (946684800LL + 86400*(31+29))
9
10
435
#define DAYS_PER_400Y (365*400 + 97)
11
290
#define DAYS_PER_100Y (365*100 + 24)
12
290
#define DAYS_PER_4Y   (365*4   + 1)
13
14
145
int __secs_to_tm(long long t, struct mytm *tm) {
15
145
    long long days, secs, years;
16
145
    int remdays, remsecs, remyears;
17
145
    int qc_cycles, c_cycles, q_cycles;
18
145
    int months;
19
145
    static const char days_in_month[] = {31,30,31,30,31,31,30,31,30,31,31,29};
20
21
    /* Reject time_t values whose year would overflow int */
22
145
    if (t < INT_MIN * 31622400LL || t > INT_MAX * 31622400LL)
23
0
        return -1;
24
25
145
    secs = t - LEAPOCH;
26
145
    days = secs / 86400LL;
27
145
    remsecs = (int)(secs % 86400);
28
145
    if (remsecs < 0) {
29
145
        remsecs += 86400;
30
145
        --days;
31
145
    }
32
33
145
    qc_cycles = (int)(days / DAYS_PER_400Y);
34
145
    remdays = (int)(days % DAYS_PER_400Y);
35
145
    if (remdays < 0) {
36
145
        remdays += DAYS_PER_400Y;
37
145
        --qc_cycles;
38
145
    }
39
40
145
    c_cycles = remdays / DAYS_PER_100Y;
41
145
    if (c_cycles == 4) --c_cycles;
42
145
    remdays -= c_cycles * DAYS_PER_100Y;
43
44
145
    q_cycles = remdays / DAYS_PER_4Y;
45
145
    if (q_cycles == 25) --q_cycles;
46
145
    remdays -= q_cycles * DAYS_PER_4Y;
47
48
145
    remyears = remdays / 365;
49
145
    if (remyears == 4) --remyears;
50
145
    remdays -= remyears * 365;
51
52
145
    years = remyears + 4*q_cycles + 100*c_cycles + 400LL*qc_cycles;
53
54
1.59k
    for (months=0; days_in_month[months] <= remdays; ++months)
55
1.45k
        remdays -= days_in_month[months];
56
57
145
    if (years+100 > INT_MAX || years+100 < INT_MIN)
58
0
        return -1;
59
60
145
    tm->tm_year = (int)(years + 100);
61
145
    tm->tm_mon = months + 2;
62
145
    if (tm->tm_mon >= 12) {
63
145
        tm->tm_mon -=12;
64
145
        ++tm->tm_year;
65
145
    }
66
145
    tm->tm_mday = remdays + 1;
67
145
    tm->tm_hour = remsecs / 3600;
68
145
    tm->tm_min = remsecs / 60 % 60;
69
145
    tm->tm_sec = remsecs % 60;
70
71
145
    return 0;
72
145
}
73
74
static const int secs_through_month[] =
75
    {0, 31*86400, 59*86400, 90*86400,
76
     120*86400, 151*86400, 181*86400, 212*86400,
77
     243*86400, 273*86400, 304*86400, 334*86400 };
78
79
static int
80
0
__month_to_secs(int month, int is_leap) {
81
0
    int t = secs_through_month[month];
82
0
    if (is_leap && month >= 2)
83
0
        t+=86400;
84
0
    return t;
85
0
}
86
87
static long long
88
0
__year_to_secs(const long long year, int *is_leap) {
89
0
    int cycles, centuries, leaps, rem;
90
0
    int is_leap_val = 0;
91
0
    if (!is_leap) {
92
0
        is_leap = &is_leap_val;
93
0
    }
94
0
    cycles = (int)((year-100) / 400);
95
0
    rem = (int)((year-100) % 400);
96
0
    if (rem < 0) {
97
0
        cycles--;
98
0
        rem += 400;
99
0
    }
100
0
    if (!rem) {
101
0
        *is_leap = 1;
102
0
        centuries = 0;
103
0
        leaps = 0;
104
0
    } else {
105
0
        if (rem >= 200) {
106
0
            if (rem >= 300) centuries = 3, rem -= 300;
107
0
            else centuries = 2, rem -= 200;
108
0
        } else {
109
0
            if (rem >= 100) centuries = 1, rem -= 100;
110
0
            else centuries = 0;
111
0
        }
112
0
        if (!rem) {
113
0
            *is_leap = 0;
114
0
            leaps = 0;
115
0
        } else {
116
0
            leaps = (rem / (int)4U);
117
0
            rem %= (int)4U;
118
0
            *is_leap = !rem;
119
0
        }
120
0
    }
121
122
0
    leaps += 97*cycles + 24*centuries - *is_leap;
123
124
0
    return (year-100) * 31536000LL + leaps * 86400LL + 946684800 + 86400;
125
0
}
126
127
0
long long __tm_to_secs(const struct mytm *tm) {
128
0
    int is_leap;
129
0
    long long year = tm->tm_year;
130
0
    int month = tm->tm_mon;
131
0
    if (month >= 12 || month < 0) {
132
0
        int adj = month / 12;
133
0
        month %= 12;
134
0
        if (month < 0) {
135
0
            adj--;
136
0
            month += 12;
137
0
        }
138
0
        year += adj;
139
0
    }
140
0
    long long t = __year_to_secs(year, &is_leap);
141
0
    t += __month_to_secs(month, is_leap);
142
0
    t += 86400LL * (tm->tm_mday-1);
143
0
    t += 3600LL * tm->tm_hour;
144
0
    t += 60LL * tm->tm_min;
145
0
    t += tm->tm_sec;
146
0
    return t;
147
0
}