src/ucx/cx/string.h

changeset 490
d218607f5a7e
parent 415
d938228c382e
--- a/src/ucx/cx/string.h	Sat Mar 25 17:18:51 2023 +0100
+++ b/src/ucx/cx/string.h	Fri May 05 18:02:11 2023 +0200
@@ -79,16 +79,77 @@
 typedef struct cx_string_s cxstring;
 
 /**
+ * Context for string tokenizing.
+ */
+struct cx_strtok_ctx_s {
+    /**
+     * The string to tokenize.
+     */
+    cxstring str;
+    /**
+     * The primary delimiter.
+     */
+    cxstring delim;
+    /**
+     * Optional array of more delimiters.
+     */
+    cxstring const *delim_more;
+    /**
+     * Length of the array containing more delimiters.
+     */
+    size_t delim_more_count;
+    /**
+     * Position of the currently active token in the source string.
+     */
+    size_t pos;
+    /**
+     * Position of next delimiter in the source string.
+     *
+     * If the tokenizer has not yet returned a token, the content of this field
+     * is undefined. If the tokenizer reached the end of the string, this field
+     * contains the length of the source string.
+     */
+    size_t delim_pos;
+    /**
+     * The position of the next token in the source string.
+     */
+    size_t next_pos;
+    /**
+     * The number of already found tokens.
+     */
+    size_t found;
+    /**
+     * The maximum number of tokens that shall be returned.
+     */
+    size_t limit;
+};
+
+/**
+ * A string tokenizing context.
+ */
+typedef struct cx_strtok_ctx_s CxStrtokCtx;
+
+#ifdef __cplusplus
+extern "C" {
+
+/**
+ * A literal initializer for an UCX string structure.
+ *
+ * @param literal the string literal
+ */
+#define CX_STR(literal) cxstring{literal, sizeof(literal) - 1}
+
+#else // __cplusplus
+
+/**
  * A literal initializer for an UCX string structure.
  *
  * The argument MUST be a string (const char*) \em literal.
  *
  * @param literal the string literal
  */
-#define CX_STR(literal) {literal, sizeof(literal) - 1}
+#define CX_STR(literal) (cxstring){literal, sizeof(literal) - 1}
 
-#ifdef __cplusplus
-extern "C" {
 #endif
 
 
@@ -214,7 +275,7 @@
  */
 __attribute__((__nonnull__))
 void cx_strfree_a(
-        CxAllocator *alloc,
+        CxAllocator const *alloc,
         cxmutstr *str
 );
 
@@ -235,28 +296,50 @@
 );
 
 /**
- * Concatenates two or more strings.
+ * Concatenates strings.
  *
  * The resulting string will be allocated by the specified allocator.
-  * So developers \em must pass the return value to cx_strfree() eventually.
-  *
-  * \note It is guaranteed that there is only one allocation.
-  * It is also guaranteed that the returned string is zero-terminated.
+ * So developers \em must pass the return value to cx_strfree_a() eventually.
+ *
+ * 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.
+ * It is also guaranteed that the returned string is zero-terminated.
  *
  * @param alloc the allocator to use
- * @param count   the total number of strings to concatenate
- * @param ...     all strings
+ * @param str   the string the other strings shall be concatenated to
+ * @param count the number of the other following strings to concatenate
+ * @param ...   all other strings
  * @return the concatenated string
  */
 __attribute__((__warn_unused_result__, __nonnull__))
-cxmutstr cx_strcat_a(
-        CxAllocator *alloc,
+cxmutstr cx_strcat_ma(
+        CxAllocator const *alloc,
+        cxmutstr str,
         size_t count,
         ...
 );
 
 /**
- * Concatenates two or more strings.
+ * Concatenates strings and returns a new string.
+ *
+ * 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.
+ * It is also guaranteed that the returned string is zero-terminated.
+ *
+ * @param alloc the allocator to use
+ * @param count the number of the other following strings to concatenate
+ * @param ...   all other strings
+ * @return the concatenated string
+ */
+#define cx_strcat_a(alloc, count, ...) \
+cx_strcat_ma(alloc, cx_mutstrn(NULL, 0), count, __VA_ARGS__)
+
+/**
+ * Concatenates strings and returns a new string.
  *
  * The resulting string will be allocated by standard \c malloc().
  * So developers \em must pass the return value to cx_strfree() eventually.
@@ -264,12 +347,32 @@
  * \note It is guaranteed that there is only one allocation.
  * It is also guaranteed that the returned string is zero-terminated.
  *
- * @param count   the total number of strings to concatenate
- * @param ...     all strings
+ * @param count   the number of the other following strings to concatenate
+ * @param ...     all other strings
  * @return the concatenated string
  */
 #define cx_strcat(count, ...) \
-cx_strcat_a(cxDefaultAllocator, count, __VA_ARGS__)
+cx_strcat_ma(cxDefaultAllocator, cx_mutstrn(NULL, 0), count, __VA_ARGS__)
+
+/**
+ * Concatenates strings.
+ *
+ * The resulting string will be allocated by standard \c malloc().
+ * So developers \em must pass the return value to cx_strfree() eventually.
+ *
+ * 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.
+ * It is also guaranteed that the returned string is zero-terminated.
+ *
+ * @param str     the string the other strings shall be concatenated to
+ * @param count   the number of the other following strings to concatenate
+ * @param ...     all other strings
+ * @return the concatenated string
+ */
+#define cx_strcat_m(str, count, ...) \
+cx_strcat_ma(cxDefaultAllocator, str, count, __VA_ARGS__)
 
 /**
  * Returns a substring starting at the specified location.
@@ -522,7 +625,7 @@
  */
 __attribute__((__warn_unused_result__, __nonnull__))
 size_t cx_strsplit_a(
-        CxAllocator *allocator,
+        CxAllocator const *allocator,
         cxstring string,
         cxstring delim,
         size_t limit,
@@ -571,7 +674,7 @@
  */
 __attribute__((__warn_unused_result__, __nonnull__))
 size_t cx_strsplit_ma(
-        CxAllocator *allocator,
+        CxAllocator const *allocator,
         cxmutstr string,
         cxstring delim,
         size_t limit,
@@ -606,6 +709,38 @@
         cxstring s2
 );
 
+/**
+ * Compares two strings.
+ *
+ * This function has a compatible signature for the use as a cx_compare_func.
+ *
+ * @param s1 the first string
+ * @param s2 the second string
+ * @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__))
+int cx_strcmp_p(
+        void const *s1,
+        void const *s2
+);
+
+/**
+ * Compares two strings ignoring case.
+ *
+ * This function has a compatible signature for the use as a cx_compare_func.
+ *
+ * @param s1 the first string
+ * @param s2 the second string
+ * @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__))
+int cx_strcasecmp_p(
+        void const *s1,
+        void const *s2
+);
+
 
 /**
  * Creates a duplicate of the specified string.
@@ -621,7 +756,7 @@
  */
 __attribute__((__warn_unused_result__, __nonnull__))
 cxmutstr cx_strdup_a(
-        CxAllocator *allocator,
+        CxAllocator const *allocator,
         cxstring string
 );
 
@@ -639,6 +774,35 @@
  */
 #define cx_strdup(string) cx_strdup_a(cxDefaultAllocator, string)
 
+
+/**
+ * Creates a duplicate of the specified string.
+ *
+ * The new string will contain a copy allocated by \p allocator.
+ *
+ * \note The returned string is guaranteed to be zero-terminated.
+ *
+ * @param allocator the allocator to use
+ * @param string the string to duplicate
+ * @return a duplicate of the string
+ * @see cx_strdup_m()
+ */
+#define cx_strdup_ma(allocator, string) cx_strdup_a(allocator, cx_strcast(string))
+
+/**
+ * Creates a duplicate of the specified string.
+ *
+ * The new string will contain a copy allocated by standard
+ * \c malloc(). So developers \em must pass the return value to cx_strfree().
+ *
+ * \note The returned string is guaranteed to be zero-terminated.
+ *
+ * @param string the string to duplicate
+ * @return a duplicate of the string
+ * @see cx_strdup_ma()
+ */
+#define cx_strdup_m(string) cx_strdup_a(cxDefaultAllocator, cx_strcast(string))
+
 /**
  * Omits leading and trailing spaces.
  *
@@ -760,7 +924,7 @@
  */
 __attribute__((__warn_unused_result__, __nonnull__))
 cxmutstr cx_strreplacen_a(
-        CxAllocator *allocator,
+        CxAllocator const *allocator,
         cxstring str,
         cxstring pattern,
         cxstring replacement,
@@ -828,6 +992,85 @@
 #define cx_strreplace(str, pattern, replacement) \
 cx_strreplacen_a(cxDefaultAllocator, str, pattern, replacement, SIZE_MAX)
 
+/**
+ * Creates a string tokenization context.
+ *
+ * @param str the string to tokenize
+ * @param delim the delimiter (must not be empty)
+ * @param limit the maximum number of tokens that shall be returned
+ * @return a new string tokenization context
+ */
+__attribute__((__warn_unused_result__))
+CxStrtokCtx cx_strtok(
+        cxstring str,
+        cxstring delim,
+        size_t limit
+);
+
+/**
+* Creates a string tokenization context for a mutable string.
+*
+* @param str the string to tokenize
+* @param delim the delimiter (must not be empty)
+* @param limit the maximum number of tokens that shall be returned
+* @return a new string tokenization context
+*/
+__attribute__((__warn_unused_result__))
+CxStrtokCtx cx_strtok_m(
+        cxmutstr str,
+        cxstring delim,
+        size_t limit
+);
+
+/**
+ * Returns the next token.
+ *
+ * The token will point to the source string.
+ *
+ * @param ctx the tokenization context
+ * @param token a pointer to memory where the next token shall be stored
+ * @return true if successful, false if the limit or the end of the string
+ * has been reached
+ */
+__attribute__((__warn_unused_result__, __nonnull__))
+bool cx_strtok_next(
+        CxStrtokCtx *ctx,
+        cxstring *token
+);
+
+/**
+ * Returns the next token of a mutable string.
+ *
+ * The token will point to the source string.
+ * If the context was not initialized over a mutable string, modifying
+ * the data of the returned token is undefined behavior.
+ *
+ * @param ctx the tokenization context
+ * @param token a pointer to memory where the next token shall be stored
+ * @return true if successful, false if the limit or the end of the string
+ * has been reached
+ */
+__attribute__((__warn_unused_result__, __nonnull__))
+bool cx_strtok_next_m(
+        CxStrtokCtx *ctx,
+        cxmutstr *token
+);
+
+/**
+ * Defines an array of more delimiters for the specified tokenization context.
+ *
+ * @param ctx the tokenization context
+ * @param delim array of more delimiters
+ * @param count number of elements in the array
+ */
+__attribute__((__nonnull__))
+void cx_strtok_delim(
+        CxStrtokCtx *ctx,
+        cxstring const *delim,
+        size_t count
+);
+
+
 #ifdef __cplusplus
 } // extern "C"
 #endif

mercurial