1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
#ifndef INCLUDE_A2I_STRTOI_H_
#define INCLUDE_A2I_STRTOI_H_
#include <errno.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/param.h>
#include <a2i/attr.h>
#include <a2i/inline.h>
#include <a2i/qual.h>
#define a2i_strtoI(TYPE, s, endp, base, min, max, status) \
({ \
const char *s_ = s; \
char **endp_ = endp; \
int base_ = base; \
TYPE min_ = min; \
TYPE max_ = max; \
int *status_ = status; \
\
int errno_saved_, st_; \
char *e_; \
TYPE n_; \
\
if (endp_ == NULL) \
endp_ = &e_; \
if (status_ == NULL) \
status_ = &st_; \
\
if (base != 0 && (base_ < 2 || base_ > 36)) { \
*status_ = EINVAL; \
n_ = 0; \
\
} else { \
errno_saved_ = errno; \
errno = 0; \
n_ = _Generic((TYPE) 0, \
intmax_t: strtoimax, \
uintmax_t: strtoumax \
)(s_, endp_, base_); \
\
if (*endp_ == s_) \
*status_ = ECANCELED; \
else if (errno == ERANGE || n_ < min_ || n_ > max_) \
*status_ = ERANGE; \
else if (**endp_ != '\0') \
*status_ = ENOTSUP; \
else \
*status_ = 0; \
\
errno = errno_saved_; \
} \
MAX(min_, MIN(max_, n_)); \
})
#if defined(__clang__)
# pragma clang assume_nonnull begin
#endif
A2I_ATTR_ACCESS(read_only, 1)
A2I_ATTR_ACCESS(write_only, 2)
A2I_ATTR_ACCESS(write_only, 6)
A2I_ATTR_STRING(1)
a2i_inline intmax_t a2i_strtoi(const char *s,
char **a2i_nullable restrict endp, int base,
intmax_t min, intmax_t max, int *a2i_nullable restrict status);
A2I_ATTR_ACCESS(read_only, 1)
A2I_ATTR_ACCESS(write_only, 2)
A2I_ATTR_ACCESS(write_only, 6)
A2I_ATTR_STRING(1)
a2i_inline uintmax_t a2i_strtou(const char *s,
char **a2i_nullable restrict endp, int base,
uintmax_t min, uintmax_t max, int *a2i_nullable restrict status);
A2I_ATTR_ACCESS(read_only, 1)
A2I_ATTR_ACCESS(write_only, 2)
A2I_ATTR_ACCESS(write_only, 6)
A2I_ATTR_STRING(1)
a2i_inline uintmax_t a2i_strtou_noneg(const char *s,
char **a2i_nullable restrict endp, int base,
uintmax_t min, uintmax_t max, int *a2i_nullable restrict status);
a2i_inline intmax_t
a2i_strtoi(const char *s,
char **a2i_nullable restrict endp, int base,
intmax_t min, intmax_t max, int *a2i_nullable restrict status)
{
return a2i_strtoI(intmax_t, s, endp, base, min, max, status);
}
a2i_inline uintmax_t
a2i_strtou(const char *s,
char **a2i_nullable restrict endp, int base,
uintmax_t min, uintmax_t max, int *a2i_nullable restrict status)
{
return a2i_strtoI(uintmax_t, s, endp, base, min, max, status);
}
a2i_inline uintmax_t
a2i_strtou_noneg(const char *s,
char **a2i_nullable restrict endp, int base,
uintmax_t min, uintmax_t max, int *a2i_nullable restrict status)
{
int st;
if (status == NULL)
status = &st;
if (a2i_strtoi(s, endp, base, 0, 1, status) == 0 && *status == ERANGE)
return min;
return a2i_strtou(s, endp, base, min, max, status);
}
#if defined(__clang__)
# pragma clang assume_nonnull end
#endif
#endif // include guard
|