Coverage Report

Created: 2026-05-30 06:22

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
31.7M
parseUInt64(const char *str, size_t size, uint64_t *result) {
31
31.7M
    size_t i = 0;
32
31.7M
    uint64_t n = 0, prev = 0;
33
34
    /* Hex */
35
31.7M
    if(size > 2 && str[0] == '0' && (str[1] | 32) == 'x') {
36
16.4k
        i = 2;
37
416k
        for(; i < size; i++) {
38
402k
            uint8_t c = (uint8_t)str[i] | 32;
39
402k
            if(c >= '0' && c <= '9')
40
318k
                c = (uint8_t)(c - '0');
41
83.9k
            else if(c >= 'a' && c <='f')
42
81.5k
                c = (uint8_t)(c - 'a' + 10);
43
2.44k
            else if(c >= 'A' && c <='F')
44
0
                c = (uint8_t)(c - 'A' + 10);
45
2.44k
            else
46
2.44k
                break;
47
400k
            n = (n << 4) | (c & 0xF);
48
400k
            if(n < prev) /* Check for overflow */
49
42
                return 0;
50
400k
            prev = n;
51
400k
        }
52
16.4k
        *result = n;
53
16.4k
        return (i > 2) ? i : 0; /* 2 -> No digit was parsed */
54
16.4k
    }
55
56
    /* Decimal */
57
77.8M
    for(; i < size; i++) {
58
46.3M
        if(str[i] < '0' || str[i] > '9')
59
241k
            break;
60
        /* Fast multiplication: n*10 == (n*8) + (n*2) */
61
46.1M
        n = (n << 3) + (n << 1) + (uint8_t)(str[i] - '0');
62
46.1M
        if(n < prev) /* Check for overflow */
63
556
            return 0;
64
46.1M
        prev = n;
65
46.1M
    }
66
31.7M
    *result = n;
67
31.7M
    return i;
68
31.7M
}
69
70
size_t
71
15.8M
parseInt64(const char *str, size_t size, int64_t *result) {
72
    /* Negative value? */
73
15.8M
    size_t i = 0;
74
15.8M
    bool neg = false;
75
15.8M
    if(*str == '-' || *str == '+') {
76
594k
        neg = (*str == '-');
77
594k
        i++;
78
594k
    }
79
80
    /* Parse as unsigned */
81
15.8M
    uint64_t n = 0;
82
15.8M
    size_t len = parseUInt64(&str[i], size - i, &n);
83
15.8M
    if(len == 0)
84
913
        return 0;
85
86
    /* Check for overflow, adjust and return */
87
15.8M
    if(!neg) {
88
15.2M
        if(n > 9223372036854775807UL)
89
534
            return 0;
90
15.2M
        *result = (int64_t)n;
91
15.2M
    } else {
92
566k
        if(n > 9223372036854775808UL)
93
23
            return 0;
94
566k
        *result = -(int64_t)n;
95
566k
    }
96
15.8M
    return len + i;
97
15.8M
}
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
}