ucx/cx/string.h

changeset 11
0aa8cbd7912e
parent 0
1a157da63d7c
child 16
04c9f8d8f03b
--- 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"

mercurial