Mercurial > hg > dmlib
view src/dmstring.c @ 2433:2fcd8d712b1e
More improvements to the grep mode.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Wed, 19 Feb 2020 18:25:50 +0200 |
parents | 9b6027d51f76 |
children | 63dd0a611586 |
line wrap: on
line source
#include "dmlib.h" #include <stdarg.h> /* 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. */ char *dm_strrcasecmp(char *str, const char *needle) { if (str == NULL || needle == NULL) return NULL; const size_t slen = strlen(str), nlen = strlen(needle); if (slen < nlen) return NULL; if (dm_strcasecmp(str + slen - nlen, needle) == 0) return str + slen - nlen; else return NULL; } /* Implementation of strdup() with a NULL check */ char *dm_strdup(const char *s) { char *res; if (s == NULL) return NULL; if ((res = dmMalloc(strlen(s) + 1)) == NULL) return NULL; strcpy(res, s); return res; } /* Implementation of strndup() with NULL check */ char *dm_strndup(const char *str, const size_t n) { char *res; if (str == NULL) return NULL; size_t len = strlen(str); if (len > n) len = n; if ((res = dmMalloc(len + 1)) == NULL) return NULL; 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) { int size = 64; char *buf, *tmp; if ((buf = dmMalloc(size)) == NULL) return NULL; while (1) { va_list ap; va_copy(ap, args); *len = vsnprintf(buf, size, fmt, ap); va_end(ap); if (*len > -1 && *len < size) return buf; if (*len > -1) size = *len + 1; else size *= 2; if ((tmp = dmRealloc(buf, size)) == NULL) { dmFree(buf); return NULL; } else buf = tmp; } } char *dm_strdup_vprintf(const char *fmt, va_list args) { int len; return dm_strdup_vprintf_len(fmt, args, &len); } char *dm_strdup_printf(const char *fmt, ...) { int len; char *res; va_list ap; va_start(ap, fmt); res = dm_strdup_vprintf_len(fmt, ap, &len); va_end(ap); return res; }