diff --git a/include/re.h b/include/re.h index 18b82b86c..25d9868ae 100644 --- a/include/re.h +++ b/include/re.h @@ -25,6 +25,7 @@ extern "C" { #include "re_bfcp.h" #include "re_btrace.h" #include "re_conf.h" +#include "re_convert.h" #include "re_crc32.h" #include "re_dns.h" #include "re_hash.h" diff --git a/include/re_convert.h b/include/re_convert.h new file mode 100644 index 000000000..9cfe892e3 --- /dev/null +++ b/include/re_convert.h @@ -0,0 +1,79 @@ +/** + * @file re_convert.h Conversion helpers + * + * Copyright (C) 2022 Sebastian Reimers + */ +#include + +static inline int try_into_u16_from_size(uint16_t *dest, const size_t src) +{ + *dest = 0; + + if (src > UINT16_MAX) + return ERANGE; + + *dest = (uint16_t)src; + + return 0; +} + + +static inline int try_into_u16_from_int(uint16_t *dest, const int src) +{ + *dest = 0; + + if (src > UINT16_MAX) + return ERANGE; + + if (src < 0) + return ERANGE; + + *dest = (uint16_t)src; + + return 0; +} + + +static inline int try_into_int_from_size(int *dest, const size_t src) +{ + *dest = 0; + + if (src > INT_MAX) + return ERANGE; + + *dest = (int)src; + + return 0; +} + + +static inline int try_into_err(void *dest, ...) +{ + (void)dest; + + return ENOTSUP; +} + + +/** + * Try to convert safely from one type (src) into another (dest). + * Types are auto detected. + * + * @param dest Destination + * @param src Source value + * + * @return 0 if success, ERANGE if value overflow and ENOTSUP if not supported + */ +#define try_into(dest, src) \ + _Generic((dest), \ + uint16_t: _Generic((src), \ + size_t: try_into_u16_from_size, \ + int: try_into_u16_from_int, \ + default: try_into_err \ + ), \ + int: _Generic((src), \ + size_t: try_into_int_from_size, \ + default: try_into_err \ + ) \ + ) \ + (&(dest), (src))