--- a/ucx/cx/string.h Fri Jan 03 21:40:57 2025 +0100 +++ b/ucx/cx/string.h Sat Jan 04 13:03:01 2025 +0100 @@ -42,7 +42,7 @@ /** * The maximum length of the "needle" in cx_strstr() that can use SBO. */ -extern unsigned const cx_strstr_sbo_size; +extern const unsigned cx_strstr_sbo_size; /** * The UCX string structure. @@ -72,7 +72,7 @@ * \note The string is not necessarily \c NULL terminated. * Always use the length. */ - char const *ptr; + const char *ptr; /** The length of the string */ size_t length; }; @@ -97,7 +97,7 @@ /** * Optional array of more delimiters. */ - cxstring const *delim_more; + const cxstring *delim_more; /** * Length of the array containing more delimiters. */ @@ -172,7 +172,9 @@ * * @see cx_mutstrn() */ -__attribute__((__warn_unused_result__, __nonnull__)) +cx_attr_nonnull +cx_attr_nodiscard +cx_attr_cstr_arg(1) cxmutstr cx_mutstr(char *cstring); /** @@ -191,7 +193,8 @@ * * @see cx_mutstr() */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard +cx_attr_access_rw(1, 2) cxmutstr cx_mutstrn( char *cstring, size_t length @@ -212,8 +215,10 @@ * * @see cx_strn() */ -__attribute__((__warn_unused_result__, __nonnull__)) -cxstring cx_str(char const *cstring); +cx_attr_nonnull +cx_attr_nodiscard +cx_attr_cstr_arg(1) +cxstring cx_str(const char *cstring); /** @@ -232,24 +237,63 @@ * * @see cx_str() */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard +cx_attr_access_r(1, 2) cxstring cx_strn( - char const *cstring, + const char *cstring, size_t length ); +#ifdef __cplusplus +} // extern "C" +cx_attr_nodiscard +static inline cxstring cx_strcast(cxmutstr str) { + return cx_strn(str.ptr, str.length); +} +cx_attr_nodiscard +static inline cxstring cx_strcast(cxstring str) { + return str; +} +extern "C" { +#else +/** + * Internal function, do not use. + * @param str + * @return + * @see cx_strcast() + */ +cx_attr_nodiscard +static inline cxstring cx_strcast_m(cxmutstr str) { + return (cxstring) {str.ptr, str.length}; +} +/** + * Internal function, do not use. + * @param str + * @return + * @see cx_strcast() + */ +cx_attr_nodiscard +static inline cxstring cx_strcast_c(cxstring str) { + return str; +} + /** * Casts a mutable string to an immutable string. * -* \note This is not seriously a cast. Instead you get a copy +* Does nothing for already immutable strings. +* +* \note This is not seriously a cast. Instead, you get a copy * of the struct with the desired pointer type. Both structs still * point to the same location, though! * * @param str the mutable string to cast * @return an immutable copy of the string pointer */ -__attribute__((__warn_unused_result__)) -cxstring cx_strcast(cxmutstr str); +#define cx_strcast(str) _Generic((str), \ + cxmutstr: cx_strcast_m, \ + cxstring: cx_strcast_c) \ + (str) +#endif /** * Passes the pointer in this string to \c free(). @@ -257,12 +301,11 @@ * The pointer in the struct is set to \c NULL and the length is set to zero. * * \note There is no implementation for cxstring, because it is unlikely that - * you ever have a \c char \c const* you are really supposed to free. If you - * encounter such situation, you should double-check your code. + * you ever have a <code>const char*</code> you are really supposed to free. + * If you encounter such situation, you should double-check your code. * * @param str the string to free */ -__attribute__((__nonnull__)) void cx_strfree(cxmutstr *str); /** @@ -271,20 +314,22 @@ * The pointer in the struct is set to \c NULL and the length is set to zero. * * \note There is no implementation for cxstring, because it is unlikely that - * you ever have a \c char \c const* you are really supposed to free. If you - * encounter such situation, you should double-check your code. + * you ever have a <code>const char*</code> you are really supposed to free. + * If you encounter such situation, you should double-check your code. * * @param alloc the allocator * @param str the string to free */ -__attribute__((__nonnull__)) +cx_attr_nonnull_arg(1) void cx_strfree_a( - CxAllocator const *alloc, + const CxAllocator *alloc, cxmutstr *str ); /** * Returns the accumulated length of all specified strings. + * + * If this sum overflows, errno is set to EOVERFLOW. * * \attention if the count argument is larger than the number of the * specified strings, the behavior is undefined. @@ -293,7 +338,7 @@ * @param ... all strings * @return the accumulated length of all strings */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard size_t cx_strlen( size_t count, ... @@ -308,7 +353,11 @@ * If \p str already contains a string, the memory will be reallocated and * the other strings are appended. Otherwise, new memory is allocated. * - * \note It is guaranteed that there is only one allocation. + * If memory allocation fails, the pointer in the returned string will + * be \c NULL. Depending on the allocator, \c errno might be set. + * + * \note It is guaranteed that there is only one allocation for the + * resulting string. * It is also guaranteed that the returned string is zero-terminated. * * @param alloc the allocator to use @@ -317,9 +366,10 @@ * @param ... all other strings * @return the concatenated string */ -__attribute__((__warn_unused_result__, __nonnull__)) +cx_attr_nodiscard +cx_attr_nonnull cxmutstr cx_strcat_ma( - CxAllocator const *alloc, + const CxAllocator *alloc, cxmutstr str, size_t count, ... @@ -331,7 +381,11 @@ * The resulting string will be allocated by the specified allocator. * So developers \em must pass the return value to cx_strfree_a() eventually. * - * \note It is guaranteed that there is only one allocation. +* If memory allocation fails, the pointer in the returned string will + * be \c NULL. Depending on the allocator, \c errno might be set. + * + * \note It is guaranteed that there is only one allocation for the + * resulting string. * It is also guaranteed that the returned string is zero-terminated. * * @param alloc the allocator to use @@ -348,7 +402,11 @@ * The resulting string will be allocated by standard \c malloc(). * So developers \em must pass the return value to cx_strfree() eventually. * - * \note It is guaranteed that there is only one allocation. +* If memory allocation fails, the pointer in the returned string will + * be \c NULL and \c errno might be set. + * + * \note It is guaranteed that there is only one allocation for the + * resulting string. * It is also guaranteed that the returned string is zero-terminated. * * @param count the number of the other following strings to concatenate @@ -367,7 +425,11 @@ * If \p str already contains a string, the memory will be reallocated and * the other strings are appended. Otherwise, new memory is allocated. * - * \note It is guaranteed that there is only one allocation. +* If memory allocation fails, the pointer in the returned string will + * be \c NULL and \c errno might be set. + * + * \note It is guaranteed that there is only one allocation for the + * resulting string. * It is also guaranteed that the returned string is zero-terminated. * * @param str the string the other strings shall be concatenated to @@ -393,7 +455,7 @@ * @see cx_strsubs_m() * @see cx_strsubsl_m() */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard cxstring cx_strsubs( cxstring string, size_t start @@ -418,7 +480,7 @@ * @see cx_strsubs_m() * @see cx_strsubsl_m() */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard cxstring cx_strsubsl( cxstring string, size_t start, @@ -440,7 +502,7 @@ * @see cx_strsubs() * @see cx_strsubsl() */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard cxmutstr cx_strsubs_m( cxmutstr string, size_t start @@ -465,7 +527,7 @@ * @see cx_strsubs() * @see cx_strsubsl() */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard cxmutstr cx_strsubsl_m( cxmutstr string, size_t start, @@ -484,7 +546,7 @@ * * @see cx_strchr_m() */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard cxstring cx_strchr( cxstring string, int chr @@ -502,7 +564,7 @@ * * @see cx_strchr() */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard cxmutstr cx_strchr_m( cxmutstr string, int chr @@ -520,7 +582,7 @@ * * @see cx_strrchr_m() */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard cxstring cx_strrchr( cxstring string, int chr @@ -538,7 +600,7 @@ * * @see cx_strrchr() */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard cxmutstr cx_strrchr_m( cxmutstr string, int chr @@ -560,7 +622,7 @@ * contained * @see cx_strstr_m() */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard cxstring cx_strstr( cxstring haystack, cxstring needle @@ -582,7 +644,7 @@ * contained * @see cx_strstr() */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard cxmutstr cx_strstr_m( cxmutstr haystack, cxstring needle @@ -600,7 +662,9 @@ * @param output a pre-allocated array of at least \p limit length * @return the actual number of split items */ -__attribute__((__warn_unused_result__, __nonnull__)) +cx_attr_nodiscard +cx_attr_nonnull +cx_attr_access_w(4, 3) size_t cx_strsplit( cxstring string, cxstring delim, @@ -627,9 +691,11 @@ * written to * @return the actual number of split items */ -__attribute__((__warn_unused_result__, __nonnull__)) +cx_attr_nodiscard +cx_attr_nonnull +cx_attr_access_w(5) size_t cx_strsplit_a( - CxAllocator const *allocator, + const CxAllocator *allocator, cxstring string, cxstring delim, size_t limit, @@ -649,7 +715,9 @@ * @param output a pre-allocated array of at least \p limit length * @return the actual number of split items */ -__attribute__((__warn_unused_result__, __nonnull__)) +cx_attr_nodiscard +cx_attr_nonnull +cx_attr_access_w(4, 3) size_t cx_strsplit_m( cxmutstr string, cxstring delim, @@ -676,9 +744,11 @@ * written to * @return the actual number of split items */ -__attribute__((__warn_unused_result__, __nonnull__)) +cx_attr_nodiscard +cx_attr_nonnull +cx_attr_access_w(5) size_t cx_strsplit_ma( - CxAllocator const *allocator, + const CxAllocator *allocator, cxmutstr string, cxstring delim, size_t limit, @@ -693,7 +763,7 @@ * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger * than \p s2, zero if both strings equal */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard int cx_strcmp( cxstring s1, cxstring s2 @@ -707,7 +777,7 @@ * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger * than \p s2, zero if both strings equal ignoring case */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard int cx_strcasecmp( cxstring s1, cxstring s2 @@ -723,10 +793,11 @@ * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger * than \p s2, zero if both strings equal */ -__attribute__((__warn_unused_result__, __nonnull__)) +cx_attr_nodiscard +cx_attr_nonnull int cx_strcmp_p( - void const *s1, - void const *s2 + const void *s1, + const void *s2 ); /** @@ -739,10 +810,11 @@ * @return negative if \p s1 is smaller than \p s2, positive if \p s1 is larger * than \p s2, zero if both strings equal ignoring case */ -__attribute__((__warn_unused_result__, __nonnull__)) +cx_attr_nodiscard +cx_attr_nonnull int cx_strcasecmp_p( - void const *s1, - void const *s2 + const void *s1, + const void *s2 ); @@ -758,9 +830,10 @@ * @return a duplicate of the string * @see cx_strdup() */ -__attribute__((__warn_unused_result__, __nonnull__)) +cx_attr_nodiscard +cx_attr_nonnull cxmutstr cx_strdup_a( - CxAllocator const *allocator, + const CxAllocator *allocator, cxstring string ); @@ -816,7 +889,7 @@ * @param string the string that shall be trimmed * @return the trimmed string */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard cxstring cx_strtrim(cxstring string); /** @@ -828,7 +901,7 @@ * @param string the string that shall be trimmed * @return the trimmed string */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard cxmutstr cx_strtrim_m(cxmutstr string); /** @@ -839,7 +912,7 @@ * @return \c true, if and only if the string has the specified prefix, * \c false otherwise */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard bool cx_strprefix( cxstring string, cxstring prefix @@ -853,7 +926,7 @@ * @return \c true, if and only if the string has the specified suffix, * \c false otherwise */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard bool cx_strsuffix( cxstring string, cxstring suffix @@ -867,7 +940,7 @@ * @return \c true, if and only if the string has the specified prefix, * \c false otherwise */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard bool cx_strcaseprefix( cxstring string, cxstring prefix @@ -881,7 +954,7 @@ * @return \c true, if and only if the string has the specified suffix, * \c false otherwise */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard bool cx_strcasesuffix( cxstring string, cxstring suffix @@ -926,9 +999,10 @@ * @param replmax maximum number of replacements * @return the resulting string after applying the replacements */ -__attribute__((__warn_unused_result__, __nonnull__)) +cx_attr_nodiscard +cx_attr_nonnull cxmutstr cx_strreplacen_a( - CxAllocator const *allocator, + const CxAllocator *allocator, cxstring str, cxstring pattern, cxstring replacement, @@ -1004,7 +1078,7 @@ * @param limit the maximum number of tokens that shall be returned * @return a new string tokenization context */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard CxStrtokCtx cx_strtok( cxstring str, cxstring delim, @@ -1019,7 +1093,7 @@ * @param limit the maximum number of tokens that shall be returned * @return a new string tokenization context */ -__attribute__((__warn_unused_result__)) +cx_attr_nodiscard CxStrtokCtx cx_strtok_m( cxmutstr str, cxstring delim, @@ -1036,7 +1110,9 @@ * @return true if successful, false if the limit or the end of the string * has been reached */ -__attribute__((__warn_unused_result__, __nonnull__)) +cx_attr_nonnull +cx_attr_nodiscard +cx_attr_access_w(2) bool cx_strtok_next( CxStrtokCtx *ctx, cxstring *token @@ -1054,7 +1130,9 @@ * @return true if successful, false if the limit or the end of the string * has been reached */ -__attribute__((__warn_unused_result__, __nonnull__)) +cx_attr_nonnull +cx_attr_nodiscard +cx_attr_access_w(2) bool cx_strtok_next_m( CxStrtokCtx *ctx, cxmutstr *token @@ -1067,13 +1145,400 @@ * @param delim array of more delimiters * @param count number of elements in the array */ -__attribute__((__nonnull__)) +cx_attr_nonnull +cx_attr_access_r(2, 3) void cx_strtok_delim( CxStrtokCtx *ctx, - cxstring const *delim, + const cxstring *delim, size_t count ); +/* ------------------------------------------------------------------------- * + * string to number conversion functions * + * ------------------------------------------------------------------------- */ + +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtos_lc(cxstring str, short *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtoi_lc(cxstring str, int *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtol_lc(cxstring str, long *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtoll_lc(cxstring str, long long *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtoi8_lc(cxstring str, int8_t *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtoi16_lc(cxstring str, int16_t *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtoi32_lc(cxstring str, int32_t *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtoi64_lc(cxstring str, int64_t *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtoz_lc(cxstring str, ssize_t *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtous_lc(cxstring str, unsigned short *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtou_lc(cxstring str, unsigned int *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtoul_lc(cxstring str, unsigned long *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtoull_lc(cxstring str, unsigned long long *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtou8_lc(cxstring str, uint8_t *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtou16_lc(cxstring str, uint16_t *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtou32_lc(cxstring str, uint32_t *output, int base, const char *groupsep); +/** + * \copydoc cx_strtouz_lc() + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtou64_lc(cxstring str, uint64_t *output, int base, const char *groupsep); + +/** + * Converts a string to a number. + * + * The function returns non-zero when conversion is not possible. + * In that case the function sets errno to EINVAL when the reason is an invalid character or an unsupported base. + * It sets errno to ERANGE when the target datatype is too small. + * + * @param str the string to convert + * @param output a pointer to the integer variable where the result shall be stored + * @param base 2, 8, 10, or 16 + * @param groupsep each character in this string is treated as group separator and ignored during conversion + * @return zero on success, non-zero if conversion was not possible + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtouz_lc(cxstring str, size_t *output, int base, const char *groupsep); + +/** + * Converts a string to a single precision floating point number. + * + * The function returns non-zero when conversion is not possible. + * In that case the function sets errno to EINVAL when the reason is an invalid character. + * It sets errno to ERANGE when the necessary representation would exceed the limits defined in libc's float.h. + * + * The decimal separator is assumed to be a dot character. + * The comma character is treated as group separator and ignored during parsing. + * If you want to choose a different format, use cx_strtof_lc(). + * + * @param str the string to convert + * @param output a pointer to the float variable where the result shall be stored + * @param decsep the decimal separator + * @param groupsep each character in this string is treated as group separator and ignored during conversion + * @return zero on success, non-zero if conversion was not possible + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtof_lc(cxstring str, float *output, char decsep, const char *groupsep); + +/** + * Converts a string to a double precision floating point number. + * + * The function returns non-zero when conversion is not possible. + * In that case the function sets errno to EINVAL when the reason is an invalid character. + * It sets errno to ERANGE when the necessary representation would exceed the limits defined in libc's float.h. + * + * The decimal separator is assumed to be a dot character. + * The comma character is treated as group separator and ignored during parsing. + * If you want to choose a different format, use cx_strtof_lc(). + * + * @param str the string to convert + * @param output a pointer to the float variable where the result shall be stored + * @param decsep the decimal separator + * @param groupsep each character in this string is treated as group separator and ignored during conversion + * @return zero on success, non-zero if conversion was not possible + */ +cx_attr_access_w(2) cx_attr_nonnull_arg(2) +int cx_strtod_lc(cxstring str, double *output, char decsep, const char *groupsep); + +#ifndef CX_STR_IMPLEMENTATION +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtos_lc(str, output, base, groupsep) cx_strtos_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtoi_lc(str, output, base, groupsep) cx_strtoi_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtol_lc(str, output, base, groupsep) cx_strtol_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtoll_lc(str, output, base, groupsep) cx_strtoll_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtoi8_lc(str, output, base, groupsep) cx_strtoi8_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtoi16_lc(str, output, base, groupsep) cx_strtoi16_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtoi32_lc(str, output, base, groupsep) cx_strtoi32_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtoi64_lc(str, output, base, groupsep) cx_strtoi64_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtoz_lc(str, output, base, groupsep) cx_strtoz_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtous_lc(str, output, base, groupsep) cx_strtous_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtou_lc(str, output, base, groupsep) cx_strtou_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtoul_lc(str, output, base, groupsep) cx_strtoul_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtoull_lc(str, output, base, groupsep) cx_strtoull_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtou8_lc(str, output, base, groupsep) cx_strtou8_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtou16_lc(str, output, base, groupsep) cx_strtou16_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtou32_lc(str, output, base, groupsep) cx_strtou32_lc(cx_strcast(str), output, base, groupsep) +/** + * \copydoc cx_strtouz_lc() + */ +#define cx_strtou64_lc(str, output, base, groupsep) cx_strtou64_lc(cx_strcast(str), output, base, groupsep) +/** + * Converts a string to a number. + * + * The function returns non-zero when conversion is not possible. + * In that case the function sets errno to EINVAL when the reason is an invalid character or an unsupported base. + * It sets errno to ERANGE when the target datatype is too small. + * + * @param str the string to convert + * @param output a pointer to the integer variable where the result shall be stored + * @param base 2, 8, 10, or 16 + * @param groupsep each character in this string is treated as group separator and ignored during conversion + * @return zero on success, non-zero if conversion was not possible + */ +#define cx_strtouz_lc(str, output, base, groupsep) cx_strtouz_lc(cx_strcast(str), output, base, groupsep) + +/** + * \copydoc cx_strtouz() + */ +#define cx_strtos(str, output, base) cx_strtos_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtoi(str, output, base) cx_strtoi_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtol(str, output, base) cx_strtol_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtoll(str, output, base) cx_strtoll_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtoi8(str, output, base) cx_strtoi8_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtoi16(str, output, base) cx_strtoi16_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtoi32(str, output, base) cx_strtoi32_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtoi64(str, output, base) cx_strtoi64_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtoz(str, output, base) cx_strtoz_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtous(str, output, base) cx_strtous_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtou(str, output, base) cx_strtou_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtoul(str, output, base) cx_strtoul_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtoull(str, output, base) cx_strtoull_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtou8(str, output, base) cx_strtou8_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtou16(str, output, base) cx_strtou16_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtou32(str, output, base) cx_strtou32_lc(str, output, base, ",") +/** + * \copydoc cx_strtouz() + */ +#define cx_strtou64(str, output, base) cx_strtou64_lc(str, output, base, ",") +/** + * Converts a string to a number. + * + * The function returns non-zero when conversion is not possible. + * In that case the function sets errno to EINVAL when the reason is an invalid character or an unsupported base. + * It sets errno to ERANGE when the target datatype is too small. + * + * The comma character is treated as group separator and ignored during parsing. + * If you want to choose the set of group separators, use the \c _lc variant of this function (e.g. cx_strtouz_lc()). + * + * @param str the string to convert + * @param output a pointer to the integer variable where the result shall be stored + * @param base 2, 8, 10, or 16 + * @return zero on success, non-zero if conversion was not possible + */ +#define cx_strtouz(str, output, base) cx_strtouz_lc(str, output, base, ",") + +/** + * Converts a string to a single precision floating point number. + * + * The function returns non-zero when conversion is not possible. + * In that case the function sets errno to EINVAL when the reason is an invalid character. + * It sets errno to ERANGE when the necessary representation would exceed the limits defined in libc's float.h. + * + * The decimal separator is assumed to be a dot character. + * The comma character is treated as group separator and ignored during parsing. + * If you want to choose a different format, use cx_strtof_lc(). + * + * @param str the string to convert + * @param output a pointer to the float variable where the result shall be stored + * @param decsep the decimal separator + * @param groupsep each character in this string is treated as group separator and ignored during conversion + * @return zero on success, non-zero if conversion was not possible + */ +#define cx_strtof_lc(str, output, decsep, groupsep) cx_strtof_lc(cx_strcast(str), output, decsep, groupsep) +/** + * Converts a string to a double precision floating point number. + * + * The function returns non-zero when conversion is not possible. + * In that case the function sets errno to EINVAL when the reason is an invalid character. + * It sets errno to ERANGE when the necessary representation would exceed the limits defined in libc's float.h. + * + * The decimal separator is assumed to be a dot character. + * The comma character is treated as group separator and ignored during parsing. + * If you want to choose a different format, use cx_strtof_lc(). + * + * @param str the string to convert + * @param output a pointer to the float variable where the result shall be stored + * @param decsep the decimal separator + * @param groupsep each character in this string is treated as group separator and ignored during conversion + * @return zero on success, non-zero if conversion was not possible + */ +#define cx_strtod_lc(str, output, decsep, groupsep) cx_strtod_lc(cx_strcast(str), output, decsep, groupsep) + +/** + * Converts a string to a single precision floating point number. + * + * The function returns non-zero when conversion is not possible. + * In that case the function sets errno to EINVAL when the reason is an invalid character. + * It sets errno to ERANGE when the necessary representation would exceed the limits defined in libc's float.h. + * + * The decimal separator is assumed to be a dot character. + * The comma character is treated as group separator and ignored during parsing. + * If you want to choose a different format, use cx_strtof_lc(). + * + * @param str the string to convert + * @param output a pointer to the float variable where the result shall be stored + * @return zero on success, non-zero if conversion was not possible + */ +#define cx_strtof(str, output) cx_strtof_lc(str, output, '.', ",") +/** + * Converts a string to a double precision floating point number. + * + * The function returns non-zero when conversion is not possible. + * In that case the function sets errno to EINVAL when the reason is an invalid character. + * It sets errno to ERANGE when the necessary representation would exceed the limits defined in libc's float.h. + * + * The decimal separator is assumed to be a dot character. + * The comma character is treated as group separator and ignored during parsing. + * If you want to choose a different format, use cx_strtof_lc(). + * + * @param str the string to convert + * @param output a pointer to the float variable where the result shall be stored + * @return zero on success, non-zero if conversion was not possible + */ +#define cx_strtod(str, output) cx_strtod_lc(str, output, '.', ",") + +#endif #ifdef __cplusplus } // extern "C"