Coverage Report

Created: 2026-05-16 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541_15/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
28.2M
parseUInt64(const char *str, size_t size, uint64_t *result) {
31
28.2M
    size_t i = 0;
32
28.2M
    uint64_t n = 0, prev = 0;
33
34
    /* Hex */
35
28.2M
    if(size > 2 && str[0] == '0' && (str[1] | 32) == 'x') {
36
17.9k
        i = 2;
37
591k
        for(; i < size; i++) {
38
577k
            uint8_t c = (uint8_t)str[i] | 32;
39
577k
            if(c >= '0' && c <= '9')
40
433k
                c = (uint8_t)(c - '0');
41
144k
            else if(c >= 'a' && c <='f')
42
140k
                c = (uint8_t)(c - 'a' + 10);
43
3.49k
            else if(c >= 'A' && c <='F')
44
0
                c = (uint8_t)(c - 'A' + 10);
45
3.49k
            else
46
3.49k
                break;
47
573k
            n = (n << 4) | (c & 0xF);
48
573k
            if(n < prev) /* Check for overflow */
49
46
                return 0;
50
573k
            prev = n;
51
573k
        }
52
17.9k
        *result = n;
53
17.9k
        return (i > 2) ? i : 0; /* 2 -> No digit was parsed */
54
17.9k
    }
55
56
    /* Decimal */
57
70.4M
    for(; i < size; i++) {
58
42.4M
        if(str[i] < '0' || str[i] > '9')
59
223k
            break;
60
        /* Fast multiplication: n*10 == (n*8) + (n*2) */
61
42.2M
        n = (n << 3) + (n << 1) + (uint8_t)(str[i] - '0');
62
42.2M
        if(n < prev) /* Check for overflow */
63
553
            return 0;
64
42.2M
        prev = n;
65
42.2M
    }
66
28.1M
    *result = n;
67
28.1M
    return i;
68
28.1M
}
69
70
size_t
71
15.9M
parseInt64(const char *str, size_t size, int64_t *result) {
72
    /* Negative value? */
73
15.9M
    size_t i = 0;
74
15.9M
    bool neg = false;
75
15.9M
    if(*str == '-' || *str == '+') {
76
562k
        neg = (*str == '-');
77
562k
        i++;
78
562k
    }
79
80
    /* Parse as unsigned */
81
15.9M
    uint64_t n = 0;
82
15.9M
    size_t len = parseUInt64(&str[i], size - i, &n);
83
15.9M
    if(len == 0)
84
921
        return 0;
85
86
    /* Check for overflow, adjust and return */
87
15.9M
    if(!neg) {
88
15.4M
        if(n > 9223372036854775807UL)
89
542
            return 0;
90
15.3M
        *result = (int64_t)n;
91
15.3M
    } else {
92
534k
        if(n > 9223372036854775808UL)
93
21
            return 0;
94
534k
        *result = -(int64_t)n;
95
534k
    }
96
15.9M
    return len + i;
97
15.9M
}
98
99
1.37M
size_t parseDouble(const char *str, size_t size, double *result) {
100
1.37M
    char buf[2000];
101
1.37M
    if(size >= 2000)
102
9
        return 0;
103
1.37M
    memcpy(buf, str, size);
104
1.37M
    buf[size] = 0;
105
1.37M
    errno = 0;
106
1.37M
    char *endptr;
107
1.37M
    *result = strtod(buf, &endptr);
108
1.37M
    if(errno != 0 && errno != ERANGE)
109
0
        return 0;
110
1.37M
    return (uintptr_t)endptr - (uintptr_t)buf;
111
1.37M
}