changeset 2027:750a7e125546

Add in several string helper functions from th-libs.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 27 Nov 2018 11:31:10 +0200
parents b137d324e13f
children 8a9ef75fd3cd
files src/dmlib.h src/dmstring.c
diffstat 2 files changed, 127 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/dmlib.h	Fri Oct 26 09:56:25 2018 +0300
+++ b/src/dmlib.h	Tue Nov 27 11:31:10 2018 +0200
@@ -408,14 +408,30 @@
 void *     dmMemset(void *ptr, const int c, size_t n);
 #endif
 
+
+/** String trimming option flags for dm_strdup_trim()
+ */
+enum
+{
+    DM_TRIM_START    = 1,
+    DM_TRIM_END      = 2,
+    DM_TRIM_BOTH     = 3
+};
+
+
+
 char *     dm_strdup(const char *str);
 char *     dm_strndup(const char *str, const size_t n);
+char *     dm_strdup_trim(const char *src, const int flags);
+char *     dm_strndup_trim(const char *src, const size_t n, const int flags);
 char *     dm_strdup_vprintf_len(const char *fmt, va_list args, int *len);
 char *     dm_strdup_vprintf(const char *fmt, va_list args);
 char *     dm_strdup_printf(const char *fmt, ...);
 
 char *     dm_basefilename(const char *filename);
 char *     dm_strdup_fext(const char *filename, const char *fmt);
+int        dm_strcasecmp(const char *haystack, const char *needle);
+int        dm_strncasecmp(const char *haystack, const char *needle, size_t n);
 char *     dm_strrcasecmp(char *str, const char *needle);
 
 BOOL       dmGetIntVal(const char *str, unsigned int *value, BOOL *neg);
--- a/src/dmstring.c	Fri Oct 26 09:56:25 2018 +0300
+++ b/src/dmstring.c	Tue Nov 27 11:31:10 2018 +0200
@@ -42,6 +42,53 @@
 }
 
 
+/* Compare two strings ignoring case [strcasecmp, strncasecmp]
+ */
+int dm_strcasecmp(const char *haystack, const char *needle)
+{
+    const char *s1 = haystack, *s2 = needle;
+    assert(haystack != NULL);
+    assert(needle != NULL);
+
+    if (haystack == needle)
+        return 0;
+
+    while (*s1 && *s2)
+    {
+        int k = tolower(*s1) - tolower(*s2);
+        if (k != 0)
+            return k;
+        s1++;
+        s2++;
+    }
+
+    return 0;
+}
+
+
+int dm_strncasecmp(const char *haystack, const char *needle, size_t n)
+{
+    const char *s1 = haystack, *s2 = needle;
+    assert(haystack != NULL);
+    assert(needle != NULL);
+
+    if (haystack == needle)
+        return 0;
+
+    while (n > 0 && *s1 && *s2)
+    {
+        int k = tolower(*s1) - tolower(*s2);
+        if (k != 0)
+            return k;
+        s1++;
+        s2++;
+        n--;
+    }
+
+    return 0;
+}
+
+
 /* Check if end of the given string str matches needle
  * case-insensitively, return pointer to start of the match,
  * if found, NULL otherwise.
@@ -58,7 +105,7 @@
     if (slen < nlen)
         return NULL;
 
-    if (strcasecmp(str - nlen - 1, needle) == 0)
+    if (dm_strcasecmp(str - nlen - 1, needle) == 0)
         return str - nlen - 1;
     else
         return NULL;
@@ -83,26 +130,85 @@
 
 /* Implementation of strndup() with NULL check
  */
-char *dm_strndup(const char *s, const size_t n)
+char *dm_strndup(const char *str, const size_t n)
 {
     char *res;
-    if (s == NULL)
+    if (str == NULL)
         return NULL;
 
-    size_t len = strlen(s);
+    size_t len = strlen(str);
     if (len > n)
         len = n;
 
     if ((res = dmMalloc(len + 1)) == NULL)
         return NULL;
 
-    memcpy(res, s, len);
+    memcpy(res, str, len);
     res[len] = 0;
 
     return res;
 }
 
 
+/* Like strdup, but trims whitespace from the string according to specified flags.
+ * See DM_TRIM_* in dmlib.h. If the resulting string would be empty (length 0),
+ * NULL is returned.
+ */
+static char * dm_strdup_trim_do(const char *src, size_t len, const int flags)
+{
+    char *res;
+    size_t start, end;
+
+    if (len == 0)
+        return NULL;
+
+    // Trim start: find first non-whitespace character
+    if (flags & DM_TRIM_START)
+        for (start = 0; start < len && isspace(src[start]); start++);
+    else
+        start = 0;
+
+    // Trim end: find last non-whitespace character
+    if (flags & DM_TRIM_END)
+        for (end = len - 1; end > start && isspace(src[end]); end--);
+    else
+        end = len;
+
+    // Allocate memory for result
+    if (src[end] == 0 || isspace(src[end]))
+        return NULL;
+
+    len = end - start + 1;
+    if ((res = dmMalloc(len + 1)) == NULL)
+        return NULL;
+
+    memcpy(res, src + start, len);
+    res[len] = 0;
+    return res;
+}
+
+
+char *dm_strdup_trim(const char *src, const int flags)
+{
+    if (src == NULL)
+        return NULL;
+
+    return dm_strdup_trim_do(src, strlen(src), flags);
+}
+
+
+char *dm_strndup_trim(const char *src, const size_t n, const int flags)
+{
+    size_t len;
+    if (src == NULL || n == 0)
+        return NULL;
+
+    for (len = 0; len < n && src[len]; len++);
+
+    return dm_strdup_trim_do(src, len, flags);
+}
+
+
 /* Simulate a sprintf() that allocates memory
  */
 char *dm_strdup_vprintf_len(const char *fmt, va_list args, int *len)