Mercurial > hg > nnchat
view th_string.c @ 43:40ba8cdcf03a
Cleanups, added a silly morse code conversion mode.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 27 Oct 2008 01:00:49 +0200 |
parents | 707e35b03f89 |
children | e47955d42b55 |
line wrap: on
line source
/* * 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; }