summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlejandro Colomar <alx@kernel.org>2024-04-16 17:47:12 +0200
committerAlejandro Colomar <alx@kernel.org>2024-04-16 20:28:41 +0200
commit1420e41a0d100add7bf4e3aedcafdecf886a036d (patch)
treef86805e757461c6ee41ff2059cc3f48137bc8846
parent605d8d66f6e1aea0a03191b86bcd6e713895071b (diff)
downloadliba2i-1420e41a0d100add7bf4e3aedcafdecf886a036d.tar.gz
include/a2i/a2i*: Add const-generic macros
Signed-off-by: Alejandro Colomar <alx@kernel.org>
-rw-r--r--include/a2i/a2i.h140
-rw-r--r--include/a2i/a2i_func.h180
-rw-r--r--lib/src/a2i/a2i_func.c53
3 files changed, 313 insertions, 60 deletions
diff --git a/include/a2i/a2i.h b/include/a2i/a2i.h
index 34be7fa..426f2d4 100644
--- a/include/a2i/a2i.h
+++ b/include/a2i/a2i.h
@@ -12,21 +12,40 @@
#include <a2i/typetraits.h>
-#define a2i(TYPE, ...) \
+#define a2i(TYPE, n, s, endp, ...) \
( \
- _Generic((TYPE) 0, \
- signed char: a2shh, \
- short: a2sh, \
- int: a2si, \
- long: a2sl, \
- long long: a2sll, \
- \
- unsigned char: a2uhh, \
- unsigned short: a2uh, \
- unsigned int: a2ui, \
- unsigned long: a2ul, \
- unsigned long long: a2ull \
- )(__VA_ARGS__) \
+ _Generic((void (*)(TYPE, typeof(endp))) 0, \
+ void (*)(signed char, const char **): a2shh_c, \
+ void (*)(signed char, char **): a2shh_nc, \
+ void (*)(signed char, void *): a2shh_nc, \
+ void (*)(short, const char **): a2sh_c, \
+ void (*)(short, char **): a2sh_nc, \
+ void (*)(short, void *): a2sh_nc, \
+ void (*)(int, const char **): a2si_c, \
+ void (*)(int, char **): a2si_nc, \
+ void (*)(int, void *): a2si_nc, \
+ void (*)(long, const char **): a2sl_c, \
+ void (*)(long, char **): a2sl_nc, \
+ void (*)(long, void *): a2sl_nc, \
+ void (*)(long long, const char **): a2sll_c, \
+ void (*)(long long, char **): a2sll_nc, \
+ void (*)(long long, void *): a2sll_nc, \
+ void (*)(unsigned char, const char **): a2uhh_c, \
+ void (*)(unsigned char, char **): a2uhh_nc, \
+ void (*)(unsigned char, void *): a2uhh_nc, \
+ void (*)(unsigned short, const char **): a2uh_c, \
+ void (*)(unsigned short, char **): a2uh_nc, \
+ void (*)(unsigned short, void *): a2uh_nc, \
+ void (*)(unsigned int, const char **): a2ui_c, \
+ void (*)(unsigned int, char **): a2ui_nc, \
+ void (*)(unsigned int, void *): a2ui_nc, \
+ void (*)(unsigned long, const char **): a2ul_c, \
+ void (*)(unsigned long, char **): a2ul_nc, \
+ void (*)(unsigned long, void *): a2ul_nc, \
+ void (*)(unsigned long long, const char **): a2ull_c, \
+ void (*)(unsigned long long, char **): a2ull_nc, \
+ void (*)(unsigned long long, void *): a2ull_nc \
+ )(n, s, endp, __VA_ARGS__) \
)
@@ -36,7 +55,6 @@
a2i(TYPE, __VA_ARGS__); \
})
-
#define a2u(TYPE, ...) \
({ \
static_assert(a2i_is_unsigned(TYPE), ""); \
@@ -44,4 +62,96 @@
})
+#define a2shh(n, s, endp, ...) \
+( \
+ _Generic(endp, \
+ const char **: a2shh_c, \
+ char **: a2shh_nc, \
+ void *: a2shh_nc \
+ )(n, s, endp, __VA_ARGS__) \
+)
+
+#define a2sh(n, s, endp, ...) \
+( \
+ _Generic(endp, \
+ const char **: a2sh_c, \
+ char **: a2sh_nc, \
+ void *: a2sh_nc \
+ )(n, s, endp, __VA_ARGS__) \
+)
+
+#define a2si(n, s, endp, ...) \
+( \
+ _Generic(endp, \
+ const char **: a2si_c, \
+ char **: a2si_nc, \
+ void *: a2si_nc \
+ )(n, s, endp, __VA_ARGS__) \
+)
+
+#define a2sl(n, s, endp, ...) \
+( \
+ _Generic(endp, \
+ const char **: a2sl_c, \
+ char **: a2sl_nc, \
+ void *: a2sl_nc \
+ )(n, s, endp, __VA_ARGS__) \
+)
+
+#define a2sll(n, s, endp, ...) \
+( \
+ _Generic(endp, \
+ const char **: a2sll_c, \
+ char **: a2sll_nc, \
+ void *: a2sll_nc \
+ )(n, s, endp, __VA_ARGS__) \
+)
+
+
+#define a2uhh(n, s, endp, ...) \
+( \
+ _Generic(endp, \
+ const char **: a2uhh_c, \
+ char **: a2uhh_nc, \
+ void *: a2uhh_nc \
+ )(n, s, endp, __VA_ARGS__) \
+)
+
+#define a2uh(n, s, endp, ...) \
+( \
+ _Generic(endp, \
+ const char **: a2uh_c, \
+ char **: a2uh_nc, \
+ void *: a2uh_nc \
+ )(n, s, endp, __VA_ARGS__) \
+)
+
+#define a2ui(n, s, endp, ...) \
+( \
+ _Generic(endp, \
+ const char **: a2ui_c, \
+ char **: a2ui_nc, \
+ void *: a2ui_nc \
+ )(n, s, endp, __VA_ARGS__) \
+)
+
+#define a2ul(n, s, endp, ...) \
+( \
+ _Generic(endp, \
+ const char **: a2ul_c, \
+ char **: a2ul_nc, \
+ void *: a2ul_nc \
+ )(n, s, endp, __VA_ARGS__) \
+)
+
+#define a2ull(n, s, endp, ...) \
+( \
+ _Generic(endp, \
+ const char **: a2ull_c, \
+ char **: a2ull_nc, \
+ void *: a2ull_nc \
+ )(n, s, endp, __VA_ARGS__) \
+)
+
+
#endif // include guard
diff --git a/include/a2i/a2i_func.h b/include/a2i/a2i_func.h
index 30f3f18..448b361 100644
--- a/include/a2i/a2i_func.h
+++ b/include/a2i/a2i_func.h
@@ -16,7 +16,24 @@
#include <a2i/strtoi.h>
-#define a2i_a2S(n, s, endp, base, min, max) \
+#define a2i_a2S_c(n, s, endp, ...) \
+({ \
+ _Pragma("GCC diagnostic push"); \
+ _Pragma("GCC diagnostic ignored \"-Wcast-qual\""); \
+ a2i_a2S_nc(n, s, (char **a2i_nullable) endp, __VA_ARGS__); \
+ _Pragma("GCC diagnostic pop"); \
+})
+
+#define a2i_a2U_c(n, s, endp, ...) \
+({ \
+ _Pragma("GCC diagnostic push"); \
+ _Pragma("GCC diagnostic ignored \"-Wcast-qual\""); \
+ a2i_a2U_nc(n, s, (char **a2i_nullable) endp, __VA_ARGS__); \
+ _Pragma("GCC diagnostic pop"); \
+})
+
+
+#define a2i_a2S_nc(n, s, endp, base, min, max) \
({ \
int status_; \
intmax_t n_; \
@@ -30,8 +47,7 @@
-!!status_; \
})
-
-#define a2i_a2U(n, s, endp, base, min, max) \
+#define a2i_a2U_nc(n, s, endp, base, min, max) \
({ \
int status_; \
uintmax_t n_; \
@@ -46,118 +62,212 @@
})
-#define A2I_A2I_PROTOTYPE(name, TYPE) \
+#define A2I_A2I_PROTOTYPE(name, TYPE, TYPE2) \
A2I_ATTR_ACCESS(write_only, 1) \
A2I_ATTR_ACCESS(read_only, 2) \
A2I_ATTR_ACCESS(write_only, 3) \
A2I_ATTR_STRING(2) \
a2i_inline int name(TYPE *restrict n, const char *s, \
- char **a2i_nullable restrict endp, int base, TYPE min, TYPE max)
+ TYPE2 a2i_nullable restrict endp, int base, TYPE min, TYPE max)
+
+#define A2I_A2I_PROTOTYPES(name, TYPE) \
+ A2I_A2I_PROTOTYPE(name ## _c, TYPE, const char **); \
+ A2I_A2I_PROTOTYPE(name ## _nc, TYPE, char **)
#if defined(__clang__)
# pragma clang assume_nonnull begin
#endif
-A2I_A2I_PROTOTYPE(a2shh, signed char);
-A2I_A2I_PROTOTYPE(a2sh, short);
-A2I_A2I_PROTOTYPE(a2si, int);
-A2I_A2I_PROTOTYPE(a2sl, long);
-A2I_A2I_PROTOTYPE(a2sll, long long);
+A2I_A2I_PROTOTYPES(a2shh, signed char);
+A2I_A2I_PROTOTYPES(a2sh, short);
+A2I_A2I_PROTOTYPES(a2si, int);
+A2I_A2I_PROTOTYPES(a2sl, long);
+A2I_A2I_PROTOTYPES(a2sll, long long);
+
+A2I_A2I_PROTOTYPES(a2uhh, unsigned char);
+A2I_A2I_PROTOTYPES(a2uh, unsigned short);
+A2I_A2I_PROTOTYPES(a2ui, unsigned int);
+A2I_A2I_PROTOTYPES(a2ul, unsigned long);
+A2I_A2I_PROTOTYPES(a2ull, unsigned long long);
+
+
+a2i_inline int
+a2shh_c(signed char *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ signed char min, signed char max)
+{
+ return a2i_a2S_c(n, s, endp, base, min, max);
+}
+
+
+a2i_inline int
+a2sh_c(short *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ short min, short max)
+{
+ return a2i_a2S_c(n, s, endp, base, min, max);
+}
+
+
+a2i_inline int
+a2si_c(int *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ int min, int max)
+{
+ return a2i_a2S_c(n, s, endp, base, min, max);
+}
+
+
+a2i_inline int
+a2sl_c(long *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ long min, long max)
+{
+ return a2i_a2S_c(n, s, endp, base, min, max);
+}
+
-A2I_A2I_PROTOTYPE(a2uhh, unsigned char);
-A2I_A2I_PROTOTYPE(a2uh, unsigned short);
-A2I_A2I_PROTOTYPE(a2ui, unsigned int);
-A2I_A2I_PROTOTYPE(a2ul, unsigned long);
-A2I_A2I_PROTOTYPE(a2ull, unsigned long long);
+a2i_inline int
+a2sll_c(long long *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ long long min, long long max)
+{
+ return a2i_a2S_c(n, s, endp, base, min, max);
+}
+
+
+a2i_inline int
+a2uhh_c(unsigned char *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ unsigned char min, unsigned char max)
+{
+ return a2i_a2U_c(n, s, endp, base, min, max);
+}
+
+
+a2i_inline int
+a2uh_c(unsigned short *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ unsigned short min, unsigned short max)
+{
+ return a2i_a2U_c(n, s, endp, base, min, max);
+}
+
+
+a2i_inline int
+a2ui_c(unsigned int *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ unsigned int min, unsigned int max)
+{
+ return a2i_a2U_c(n, s, endp, base, min, max);
+}
+
+
+a2i_inline int
+a2ul_c(unsigned long *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ unsigned long min, unsigned long max)
+{
+ return a2i_a2U_c(n, s, endp, base, min, max);
+}
+
+
+a2i_inline int
+a2ull_c(unsigned long long *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ unsigned long long min, unsigned long long max)
+{
+ return a2i_a2U_c(n, s, endp, base, min, max);
+}
a2i_inline int
-a2shh(signed char *restrict n, const char *s,
+a2shh_nc(signed char *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
signed char min, signed char max)
{
- return a2i_a2S(n, s, endp, base, min, max);
+ return a2i_a2S_nc(n, s, endp, base, min, max);
}
a2i_inline int
-a2sh(short *restrict n, const char *s,
+a2sh_nc(short *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
short min, short max)
{
- return a2i_a2S(n, s, endp, base, min, max);
+ return a2i_a2S_nc(n, s, endp, base, min, max);
}
a2i_inline int
-a2si(int *restrict n, const char *s,
+a2si_nc(int *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
int min, int max)
{
- return a2i_a2S(n, s, endp, base, min, max);
+ return a2i_a2S_nc(n, s, endp, base, min, max);
}
a2i_inline int
-a2sl(long *restrict n, const char *s,
+a2sl_nc(long *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
long min, long max)
{
- return a2i_a2S(n, s, endp, base, min, max);
+ return a2i_a2S_nc(n, s, endp, base, min, max);
}
a2i_inline int
-a2sll(long long *restrict n, const char *s,
+a2sll_nc(long long *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
long long min, long long max)
{
- return a2i_a2S(n, s, endp, base, min, max);
+ return a2i_a2S_nc(n, s, endp, base, min, max);
}
a2i_inline int
-a2uhh(unsigned char *restrict n, const char *s,
+a2uhh_nc(unsigned char *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
unsigned char min, unsigned char max)
{
- return a2i_a2U(n, s, endp, base, min, max);
+ return a2i_a2U_nc(n, s, endp, base, min, max);
}
a2i_inline int
-a2uh(unsigned short *restrict n, const char *s,
+a2uh_nc(unsigned short *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
unsigned short min, unsigned short max)
{
- return a2i_a2U(n, s, endp, base, min, max);
+ return a2i_a2U_nc(n, s, endp, base, min, max);
}
a2i_inline int
-a2ui(unsigned int *restrict n, const char *s,
+a2ui_nc(unsigned int *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
unsigned int min, unsigned int max)
{
- return a2i_a2U(n, s, endp, base, min, max);
+ return a2i_a2U_nc(n, s, endp, base, min, max);
}
a2i_inline int
-a2ul(unsigned long *restrict n, const char *s,
+a2ul_nc(unsigned long *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
unsigned long min, unsigned long max)
{
- return a2i_a2U(n, s, endp, base, min, max);
+ return a2i_a2U_nc(n, s, endp, base, min, max);
}
a2i_inline int
-a2ull(unsigned long long *restrict n, const char *s,
+a2ull_nc(unsigned long long *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
unsigned long long min, unsigned long long max)
{
- return a2i_a2U(n, s, endp, base, min, max);
+ return a2i_a2U_nc(n, s, endp, base, min, max);
}
#if defined(__clang__)
# pragma clang assume_nonnull end
diff --git a/lib/src/a2i/a2i_func.c b/lib/src/a2i/a2i_func.c
index 4ae9a20..a11e93e 100644
--- a/lib/src/a2i/a2i_func.c
+++ b/lib/src/a2i/a2i_func.c
@@ -8,35 +8,68 @@
#pragma clang assume_nonnull begin
-extern inline int a2shh(signed char *restrict n, const char *s,
+extern inline int a2shh_c(signed char *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ signed char min, signed char max);
+extern inline int a2sh_c(short *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ short min, short max);
+extern inline int a2si_c(int *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ int min, int max);
+extern inline int a2sl_c(long *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ long min, long max);
+extern inline int a2sll_c(long long *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ long long min, long long max);
+
+extern inline int a2uhh_c(unsigned char *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ unsigned char min, unsigned char max);
+extern inline int a2uh_c(unsigned short *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ unsigned short min, unsigned short max);
+extern inline int a2ui_c(unsigned int *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ unsigned int min, unsigned int max);
+extern inline int a2ul_c(unsigned long *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ unsigned long min, unsigned long max);
+extern inline int a2ull_c(unsigned long long *restrict n, const char *s,
+ const char **a2i_nullable restrict endp, int base,
+ unsigned long long min, unsigned long long max);
+
+
+extern inline int a2shh_nc(signed char *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
signed char min, signed char max);
-extern inline int a2sh(short *restrict n, const char *s,
+extern inline int a2sh_nc(short *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
short min, short max);
-extern inline int a2si(int *restrict n, const char *s,
+extern inline int a2si_nc(int *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
int min, int max);
-extern inline int a2sl(long *restrict n, const char *s,
+extern inline int a2sl_nc(long *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
long min, long max);
-extern inline int a2sll(long long *restrict n, const char *s,
+extern inline int a2sll_nc(long long *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
long long min, long long max);
-extern inline int a2uhh(unsigned char *restrict n, const char *s,
+extern inline int a2uhh_nc(unsigned char *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
unsigned char min, unsigned char max);
-extern inline int a2uh(unsigned short *restrict n, const char *s,
+extern inline int a2uh_nc(unsigned short *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
unsigned short min, unsigned short max);
-extern inline int a2ui(unsigned int *restrict n, const char *s,
+extern inline int a2ui_nc(unsigned int *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
unsigned int min, unsigned int max);
-extern inline int a2ul(unsigned long *restrict n, const char *s,
+extern inline int a2ul_nc(unsigned long *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
unsigned long min, unsigned long max);
-extern inline int a2ull(unsigned long long *restrict n, const char *s,
+extern inline int a2ull_nc(unsigned long long *restrict n, const char *s,
char **a2i_nullable restrict endp, int base,
unsigned long long min, unsigned long long max);
#pragma clang assume_nonnull end