Coverage Report

Created: 2026-06-30 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541/deps/parse_num.c
Line
Count
Source
1
/* Originally released by the musl project (http://www.musl-libc.org/) under the
2
 * MIT license. Taken and adapted from the file src/stdlib/atoi.c 
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
5
 * of this software and associated documentation files (the "Software"), to deal
6
 * in the Software without restriction, including without limitation the rights
7
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
 * copies of the Software, and to permit persons to whom the Software is
9
 * furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in
12
 * all copies or substantial portions of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
 * THE SOFTWARE.
21
 */
22
23
#include "parse_num.h"
24
25
#include <string.h>
26
#include <stdlib.h>
27
#include <errno.h>
28
29
size_t
30
182k
parseUInt64(const char *str, size_t size, uint64_t *result) {
31
182k
    size_t i = 0;
32
182k
    uint64_t n = 0, prev = 0;
33
34
    /* Hex */
35
182k
    if(size > 2 && str[0] == '0' && (str[1] | 32) == 'x') {
36
45
        i = 2;
37
456
        for(; i < size; i++) {
38
432
            uint8_t c = (uint8_t)str[i] | 32;
39
432
            if(c >= '0' && c <= '9')
40
304
                c = (uint8_t)(c - '0');
41
128
            else if(c >= 'a' && c <='f')
42
112
                c = (uint8_t)(c - 'a' + 10);
43
16
            else if(c >= 'A' && c <='F')
44
0
                c = (uint8_t)(c - 'A' + 10);
45
16
            else
46
16
                break;
47
416
            n = (n << 4) | (c & 0xF);
48
416
            if(n < prev) /* Check for overflow */
49
5
                return 0;
50
411
            prev = n;
51
411
        }
52
40
        *result = n;
53
40
        return (i > 2) ? i : 0; /* 2 -> No digit was parsed */
54
45
    }
55
56
    /* Decimal */
57
368k
    for(; i < size; i++) {
58
185k
        if(str[i] < '0' || str[i] > '9')
59
38
            break;
60
        /* Fast multiplication: n*10 == (n*8) + (n*2) */
61
185k
        n = (n << 3) + (n << 1) + (uint8_t)(str[i] - '0');
62
185k
        if(n < prev) /* Check for overflow */
63
5
            return 0;
64
185k
        prev = n;
65
185k
    }
66
182k
    *result = n;
67
182k
    return i;
68
182k
}
69
70
size_t
71
178k
parseInt64(const char *str, size_t size, int64_t *result) {
72
    /* Negative value? */
73
178k
    size_t i = 0;
74
178k
    bool neg = false;
75
178k
    if(*str == '-' || *str == '+') {
76
121k
        neg = (*str == '-');
77
121k
        i++;
78
121k
    }
79
80
    /* Parse as unsigned */
81
178k
    uint64_t n = 0;
82
178k
    size_t len = parseUInt64(&str[i], size - i, &n);
83
178k
    if(len == 0)
84
0
        return 0;
85
86
    /* Check for overflow, adjust and return */
87
178k
    if(!neg) {
88
57.4k
        if(n > 9223372036854775807UL)
89
0
            return 0;
90
57.4k
        *result = (int64_t)n;
91
121k
    } else {
92
121k
        if(n > 9223372036854775808UL)
93
0
            return 0;
94
121k
        *result = -(int64_t)n;
95
121k
    }
96
178k
    return len + i;
97
178k
}
98
99
3
size_t parseDouble(const char *str, size_t size, double *result) {
100
3
    char buf[2000];
101
3
    if(size >= 2000)
102
0
        return 0;
103
3
    memcpy(buf, str, size);
104
3
    buf[size] = 0;
105
3
    errno = 0;
106
3
    char *endptr;
107
3
    *result = strtod(buf, &endptr);
108
3
    if(errno != 0 && errno != ERANGE)
109
0
        return 0;
110
3
    return (uintptr_t)endptr - (uintptr_t)buf;
111
3
}