Coverage Report

Created: 2025-07-01 07:00

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