Mercurial > hg > nnchat
view th_string.c @ 265:b9c650db8a6a
Rename variable nnIgnoreList to setIgnoreList.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 03 Jun 2011 11:18:50 +0300 |
parents | 517c7b22b3c9 |
children | 3dc86d8eb0a9 |
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" /* strdup with a NULL check */ char *th_strdup(const char *s) { char *res; if (s == NULL) return NULL; if ((res = th_malloc(strlen(s) + 1)) == NULL) return NULL; strcpy(res, s); return res; } char *th_strncpy(char * dst, const char * src, const size_t n) { const char *s = src; char *d = dst; size_t i; assert(src != NULL); assert(dst != NULL); /* Copy to the destination */ i = n; 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; } /* Simulate a sprintf() that allocates memory */ char * th_strdup_vprintf(const char *fmt, va_list args) { int size = 100; char *buf, *nbuf = NULL; if ((buf = th_malloc(size)) == NULL) return NULL; while (1) { int n = vsnprintf(buf, size, fmt, args); if (n > -1 && n < size) return buf; if (n > -1) size = n + 1; else size *= 2; if ((nbuf = th_realloc(nbuf, size)) == NULL) { th_free(buf); return NULL; } buf = nbuf; } } char * th_strdup_printf(const char *fmt, ...) { char *res; va_list ap; va_start(ap, fmt); res = th_strdup_vprintf(fmt, ap); va_end(ap); return res; } /* Compare two strings ignoring case [strcasecmp, strncasecmp] */ int th_strcasecmp(const char * str1, const char * str2) { const char *s1 = str1, *s2 = str2; assert(str1 != NULL); assert(str2 != NULL); if (str1 == str2) return 0; while (*s1 && *s2 && th_tolower(*s1) == th_tolower(*s2)) { s1++; s2++; } return (th_tolower(*s1) - th_tolower(*s2)); } int th_strncasecmp(const char * str1, const char * str2, size_t n) { const char *s1 = str1, *s2 = str2; assert(str1 != NULL); assert(str2 != NULL); if (str1 == str2) return 0; while (n > 0 && *s1 && *s2 && th_tolower(*s1) == th_tolower(*s2)) { s1++; s2++; n--; } return n > 0 ? (th_tolower(*s1) - th_tolower(*s2)) : 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 != NULL); 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, const char * str) { assert(result != NULL); if (str == NULL) return -1; th_free(*result); if ((*result = th_malloc(strlen(str) + 1)) == NULL) return -2; strcpy(*result, str); return 0; } /* Concatenates a given string into string pointed by *result. */ int th_pstrcat(char ** result, const char * str) { assert(result != NULL); if (str == NULL) return -1; if (*result != NULL) { *result = th_realloc(*result, strlen(*result) + strlen(str) + 1); if (*result == NULL) return -1; strcat(*result, str); } else { *result = th_malloc(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. */ const char *th_findnext(const char * str, size_t * pos) { assert(str != NULL); /* Terminating NULL-character is not whitespace! */ while (th_isspace(str[*pos])) (*pos)++; return &str[*pos]; } /* Find next sep-character from string */ const char *th_findsep(const char * str, size_t * pos, char sep) { assert(str != NULL); while (str[*pos] && str[*pos] != sep) (*pos)++; return &str[*pos]; } /* Find next sep- or whitespace from string */ const char *th_findseporspace(const char * str, size_t * pos, char sep) { assert(str != NULL); while (!th_isspace(str[*pos]) && str[*pos] != sep) (*pos)++; return &str[*pos]; } /* 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(const char * str, const char * pattern) { BOOL didMatch = TRUE, isAnyMode = FALSE, isEnd = FALSE; const char *tmpPattern = NULL; /* Check given pattern and string */ if (str == NULL || pattern == NULL) return 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(const char * str, const char * pattern) { BOOL didMatch = TRUE, isAnyMode = FALSE, isEnd = FALSE; const char *tmpPattern = NULL; /* Check given pattern and string */ if (str == NULL || pattern == NULL) return 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; } int th_get_hex_triplet(const char *str) { const char *p = str; int len, val = 0; for (len = 0; *p && len < 6; p++, len++) { if (*p >= '0' && *p <= '9') { val *= 16; val += (*p - '0'); } else if (*p >= 'A' && *p <= 'F') { val *= 16; val += (*p - 'A') + 10; } else if (*p >= 'a' && *p <= 'f') { val *= 16; val += (*p - 'a') + 10; } else return -1; } return (len == 6) ? val : -1; } static BOOL th_growbuf(char **buf, size_t *bufsize, size_t *len, size_t grow) { assert(buf != NULL); assert(bufsize != NULL); assert(len != NULL); if (*buf == NULL) *bufsize = 0; if (*buf == NULL || *len + grow >= *bufsize) { *bufsize += grow + TH_BUFGROW; *buf = (char *) th_realloc(*buf, *bufsize); if (*buf == NULL) return FALSE; } return TRUE; } void th_vputch(char **buf, size_t *bufsize, size_t *len, const char ch) { if (!th_growbuf(buf, bufsize, len, 1)) return; (*buf)[*len] = ch; (*len)++; } void th_vputs(char **buf, size_t *bufsize, size_t *len, const char *str) { size_t slen; if (str == NULL) return; slen = strlen(str); if (!th_growbuf(buf, bufsize, len, slen)) return; strcat(*buf + *len, str); (*len) += slen; }