Mercurial > hg > th-libs
diff th_string.c @ 0:bd61a80a6c54
Initial import into Mercurial repository. Discarding old cvs/svn history
here, because it's cluttered and commit messages are mostly crap.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Wed, 26 Mar 2008 04:41:58 +0200 |
parents | |
children | 41885619fc79 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/th_string.c Wed Mar 26 04:41:58 2008 +0200 @@ -0,0 +1,462 @@ +/* + * Miscellaneous string-handling related utility-functions + * Programmed and designed by Matti 'ccr' Hamalainen + * (C) Copyright 2002-2008 Tecnic Software productions (TNSP) + * + * Please read file 'COPYING' for information on license and distribution. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "th_string.h" + +#define LPREV (pNode->pPrev) +#define LNEXT (pNode->pNext) + +/* Allocate memory for a string with given length + */ +char *th_stralloc(const size_t l) +{ + assert(l > 0); + return th_malloc(sizeof(char) * l); +} + + +char *th_strrealloc(char * s, const size_t l) +{ + assert(l > 0); + return th_realloc(s, sizeof(char) * l); +} + + +/* Duplicate a string [strdup] + */ +char *th_strdup(char * str) +{ + char *result, *s, *d; + + if (!str) return NULL; + + /* Allocate memory for destination */ + result = th_stralloc(strlen(str) + 1); + if (!result) + return NULL; + + /* Copy to the destination */ + s = str; + d = result; + while (*s) { + *(d++) = *(s++); + } + *d = 0; + + return result; +} + + +char *th_strncpy(char * dst, char * src, size_t n) +{ + char *s, *d; + size_t i; + assert(src); + assert(dst); + + /* Copy to the destination */ + i = n; + s = src; + d = dst; + while (*s && (i > 0)) { + *(d++) = *(s++); + i--; + } + + /* Fill rest of space with zeros */ + while (i > 0) { + *(d++) = 0; + i--; + } + + /* Ensure that last is always zero */ + dst[n - 1] = 0; + + return dst; +} + + +int th_strncmp(char * str1, char * str2, size_t n) +{ + char *s1, *s2; + assert(str1); + assert(str2); + + /* Check the string pointers */ + if (str1 == str2) + return 0; + + /* Go through the string */ + s1 = str1; + s2 = str2; + while ((n > 0) && *s1 && *s2 && (*s1 == *s2)) { + s1++; + s2++; + n--; + } + + if (n > 0) + return ((*s1) - (*s2)); + else + return 0; +} + + +/* Compare two strings ignoring case [strcasecmp, strncasecmp] + */ +int th_strcasecmp(char * str1, char * str2) +{ + char *s1 = str1, *s2 = str2; + assert(str1); + assert(str2); + + /* Check the string pointers */ + if (str1 == str2) + return 0; + + /* Go through the string */ + while (*s1 && *s2 && (th_tolower(*s1) == th_tolower(*s2))) { + s1++; + s2++; + } + + return (th_tolower(*s1) - th_tolower(*s2)); +} + + +int th_strncasecmp(char * str1, char * str2, size_t n) +{ + char *s1 = str1, *s2 = str2; + assert(str1); + assert(str2); + + /* Check the string pointers */ + if (str1 == str2) + return 0; + + /* Go through the string */ + while ((n > 0) && *s1 && *s2 && (th_tolower(*s1) == th_tolower(*s2))) { + s1++; + s2++; + n--; + } + + if (n > 0) + return (th_tolower(*s1) - th_tolower(*s2)); + else + return 0; +} + + +/* Remove all occurences of control characters, in-place. + * Resulting string is always shorter or same length than original. + */ +void th_strip_ctrlchars(char * str) +{ + char *i, *j; + assert(str); + + i = str; + j = str; + while (*i) { + if (!th_iscntrl(*i)) + *(j++) = *i; + i++; + } + + *j = 0; +} + + +/* Copy a given string over in *result. + */ +int th_pstrcpy(char ** result, char * str) +{ + assert(result); + + /* Check the string pointers */ + if (!str) + return -1; + + /* Allocate memory for destination */ + th_free(*result); + *result = th_stralloc(strlen(str) + 1); + if (!*result) + return -2; + + /* Copy to the destination */ + strcpy(*result, str); + + return 0; +} + + +/* Concatenates a given string into string pointed by *result. + */ +int th_pstrcat(char ** result, char * str) +{ + assert(result); + + /* Check the string pointers */ + if (!str) + return -1; + + if (*result != NULL) { + *result = th_strrealloc(*result, strlen(*result) + strlen(str) + 1); + if (*result == NULL) + return -1; + + strcat(*result, str); + } else { + *result = th_stralloc(strlen(str) + 1); + if (*result == NULL) + return -1; + + strcpy(*result, str); + } + + return 0; +} + + +/* Find next non-whitespace character in string. + * Updates iPos into the position of such character and + * returns pointer to the string. + */ +char *th_findnext(char * str, size_t * iPos) +{ + assert(str); + + /* Terminating NULL-character is not whitespace! */ + while (th_isspace(str[*iPos])) + (*iPos)++; + return &str[*iPos]; +} + + +/* Find next chSep-character from string + */ +char *th_findsep(char * str, size_t * iPos, char chSep) +{ + assert(str); + + /* Terminating NULL-character is not digit! */ + while (str[*iPos] && (str[*iPos] != chSep)) + (*iPos)++; + return &str[*iPos]; +} + + +/* Find next chSep- or whitespace from string + */ +char *th_findseporspace(char * str, size_t * iPos, char chSep) +{ + assert(str); + + /* Terminating NULL-character is not digit! */ + while (!th_isspace(str[*iPos]) && (str[*iPos] != chSep)) + (*iPos)++; + return &str[*iPos]; +} + + +/* Compare a string to a pattern. Case-SENSITIVE version. + * The matching pattern can consist of any normal characters plus + * wildcards ? and *. "?" matches any character and "*" matches + * any number of characters. + */ +BOOL th_strmatch(char * str, char * pattern) +{ + BOOL didMatch, isAnyMode, isEnd; + char *tmpPattern; + + /* Check given pattern and string */ + if (!str) + return FALSE; + if (!pattern) + return FALSE; + + /* Initialize */ + tmpPattern = NULL; + didMatch = TRUE; + isEnd = FALSE; + isAnyMode = FALSE; + + /* Start comparision */ + do { + didMatch = FALSE; + switch (*pattern) { + case '?': + /* Any single character matches */ + if (*str) { + didMatch = TRUE; + pattern++; + str++; + } + break; + + case '*': + didMatch = TRUE; + pattern++; + if (!*pattern) + isEnd = TRUE; + isAnyMode = TRUE; + tmpPattern = pattern; + break; + + case 0: + if (isAnyMode) { + if (*str) + str++; + else + isEnd = TRUE; + } else { + if (*str) { + if (tmpPattern) { + isAnyMode = TRUE; + pattern = tmpPattern; + } else + didMatch = FALSE; + } else + isEnd = TRUE; + } + break; + default: + if (isAnyMode) { + if ((*pattern) == (*str)) { + isAnyMode = FALSE; + didMatch = TRUE; + } else { + if (*str) { + didMatch = TRUE; + str++; + } + } + } else { + if ((*pattern) == (*str)) { + didMatch = TRUE; + if (*pattern) + pattern++; + if (*str) + str++; + } else { + if (tmpPattern) { + didMatch = TRUE; + isAnyMode = TRUE; + pattern = tmpPattern; + } + } + } + + if (!*str && !*pattern) + isEnd = TRUE; + break; + + } /* switch */ + + } while ((didMatch) && (!isEnd)); + + return didMatch; +} + + +/* Compare a string to a pattern. Case-INSENSITIVE version. + */ +BOOL th_strcasematch(char * str, char * pattern) +{ + BOOL didMatch, isAnyMode, isEnd; + char *tmpPattern; + + /* Check given pattern and string */ + if (!str) + return FALSE; + if (!pattern) + return FALSE; + + /* Initialize */ + tmpPattern = NULL; + didMatch = TRUE; + isEnd = FALSE; + isAnyMode = FALSE; + + /* Start comparision */ + do { + switch (*pattern) { + case '?': + /* Any single character matches */ + if (*str) { + pattern++; + str++; + } else + didMatch = FALSE; + break; + + case '*': + pattern++; + if (!*pattern || (*pattern == '?')) + isEnd = TRUE; + isAnyMode = TRUE; + tmpPattern = pattern; + break; + + case 0: + if (isAnyMode) { + if (*str) + str++; + else + isEnd = TRUE; + } else { + if (*str) { + if (tmpPattern) { + isAnyMode = TRUE; + pattern = tmpPattern; + } else + didMatch = FALSE; + } else + isEnd = TRUE; + } + break; + + default: + if (isAnyMode) { + if (th_tolower(*pattern) == th_tolower(*str)) { + isAnyMode = FALSE; + } else { + if (*str) + str++; + else + didMatch = FALSE; + } + } else { + if (th_tolower(*pattern) == th_tolower(*str)) { + if (*pattern) + pattern++; + if (*str) + str++; + } else { + if (tmpPattern) { + isAnyMode = TRUE; + pattern = tmpPattern; + } else + didMatch = FALSE; + } + } + + if (!*str && !*pattern) + isEnd = TRUE; + break; + + } /* switch */ + + } while ((didMatch) && (!isEnd)); + + return didMatch; +} +