/* * File: string.c * * Author: Ulli Horlacher (framstag@rus.uni-stuttgart.de) * * Contrib.: Ingo Wilken (Ingo.Wilken@Informatik.Uni-Oldenburg.DE) * Christoph 'GNUish' Goern (goern@beuel.rhein.de) * Joerg 'Mufti' Scheurich (Joerg.Scheurich@RUS.Uni-Stuttgart.DE) * * * History: * * 1995-08-12 Framstag initial version * 1996-02-05 Framstag faster str_trim function * 1996-05-07 Framstag added strbeq() * 1997-01-14 GNUish added strerror() * 1997-02-03 Framstag included snprintf() from apache-source * 1997-02-04 GNUish added the #ifdef for snprintf() * 1997-02-07 Ingo improved simplematch() * 1997-02-23 Framstag modified str_* function names * added str_beq_nocase and str_neq_nocase * 1997-10-03 Framstag better BSD support in strerror() * 1997-12-12 Framstag simplematch now supports the regular expressions * [A-Z], [^ABC] and [^A-Z] * 1998-01-05 Mufti fixed bug in str_trim() * 1998-04-01 Framstag fixed bug in [a-b] match in simplematch() * 2000-12-10 Framstag added fgetl() (substitution for fgets()) * 2001-02-01 Framstag fixed bug in fgetl() * * Extended string functions for the sendfile package, which are not found * in the standard C library. * Look at string.h for a list of the functions. * * Copyright © 1995-2001 Ulli Horlacher * This file is covered by the GNU General Public License */ #include "config.h" #include #include #include #include "string.h" /* #ifdef IRIX int toupper(char); int tolower(char); #endif */ /* * str_trim - substitute multiple white spaces with one space * and delete heading and trailing whitespace * * INPUT: string - string to trim * * OUTPUT: string - trimmed string * * RETURN: trimmed string */ char *str_trim(char *string) { char *rp, /* reading string pointer */ *wp; /* writing string pointer */ int ws; /* white space flag */ ws=0; if (*string) { /* loop over string */ for (wp=rp=string; *rp; rp++) { /* is it a white space? */ if (*rp==' ' || *rp=='\t' || *rp=='\n' || *rp=='\r') { /* store a blank if the last character was not a white space */ if (!ws) { *wp++=' '; ws=1; } } else /* no white space */ { /* store the character */ *wp++=*rp; ws=0; } } /* delete trailing blank */ if (ws) wp--; *wp=0; } return(string); } /* * str_toupper - transform string to upper case * * INPUT: string - string to transform * * OUTPUT: string - transformed string * * RETURN: string - transformed string */ char *str_toupper(char *string) { char *cp; /* change each character to it's upper case pedant */ for (cp=string; *cp; cp++) *cp = (char) toupper(*cp); return(string); } /* * str_tolower - transform string to lower case * * INPUT: string - string to transform * * OUTPUT: string - transformed string * * RETURN: string - transformed string */ char *str_tolower(char *string) { char *cp; /* change each character to it's upper case pedant */ for (cp=string; *cp; cp++) *cp = (char) tolower(*cp); return(string); } /* * str_beq - string begin equal test * * INPUT: s1 - string 1 * s1 - string 1 * * RETURN: 1 if begin is equal, 0 if begin is not equal */ int str_beq(const char *s1, const char *s2) { int len; if (strlen(s1) #define NULL (char *)0 */ #define SM_MATCH 1 #define SM_NOMATCH 0 #define SM_ERROR -1 /* Fehler im Pattern */ static char sm_escchar( c ) char c; { switch( c ) { case 'a': c = '\a'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'v': c = '\v'; break; } return(c); } int simplematch( text, pattern, nocase ) char *text, *pattern; int nocase; { char *retrypat = NULL, *retrytxt; unsigned char c,c1,c2; int notfound; retrytxt = text; while (*text || *pattern) { c = *(pattern++); if (nocase) c = tolower(c); switch (c) { case '*': retrypat = pattern; retrytxt = text; break; case '[': notfound = 1; if (*pattern == '^') { notfound = 0; pattern++; } while ((c = *(pattern++)) != ']') { if (c == '\\') c = sm_escchar(*(pattern++)); if (c == '\0') return(SM_ERROR); if (*pattern == '-') { c1 = c; c2 = *(++pattern); if (c2 == ']' || c2 == '\0' || c1 == '[') return(SM_ERROR); if ((*text >= c1 && *text <= c2) || (tolower(*text) >= tolower(c1) && tolower(*text) <= tolower(c2) && nocase)) notfound = !notfound; pattern++; } else if (*text == c || (nocase && tolower(*text) == tolower(c))) notfound = !notfound; } if (notfound) { pattern = retrypat; text = ++retrytxt; } case '?': if (*(text++) == '\0') return(SM_NOMATCH); break; case '\\': c = sm_escchar(*(pattern++)); if (c == '\0') return(SM_ERROR); default : if (*text == c || (nocase && tolower(*text) == c)) { if (*text) text++; } else { if (*text) { pattern = retrypat; text = ++retrytxt; } else return(SM_NOMATCH); } } if( pattern == NULL ) return(SM_NOMATCH); } return(SM_MATCH); } #ifdef SM_TEST #include main() { char s[1000],p[1000]; while(1) { printf("Text : "); fflush(stdout); scanf("%s",s); printf("Pattern: "); fflush(stdout); scanf("%s",p); printf("Result case-sensitive : %d\n",simplematch(s,p,0)); printf("Result case-insensitive: %d\n\n",simplematch(s,p,1)); } } #endif #if !defined(HAVE_STRERROR) /* * strerror - like strerror on many Unices, but not on SunOS 4.1.4 * * INPUT: int - error number to look up * * OUTPUT: none * * RETURN: string - string of the error number */ char *strerror(int errornumber) { #if __GLIBC__ < 2 && !defined(BSD) extern int sys_nerr; extern char *sys_errlist[]; #endif static char buffer[40]; if ((unsigned int) errornumber < sys_nerr) { return (char *)(sys_errlist[errornumber]); } (void) sprintf(buffer, "Unknown error: %d", errornumber); return (buffer); } #endif #if !defined(HAVE_SNPRINTF) #include "snprintf.c" #endif /* sfgetl: secure version of gets() : read a text line from a stream * * INPUT: s - string * z - size of string * f - input stream * * OUTPUT: s - read line (correctly terminated with \0) * * RETURN: s on success, NULL on error * * Remark: if line is longer than z, munch it */ char *sfgetl(char *s, int z, FILE *f) { char *S; int c; S=fgets(s,z,f); /* munch to EOL or EOF if there are chars pending */ if (S && *s && s[strlen(s)-1] != '\n') { do { c=fgetc(f); } while (c != EOF && c != '\n' && c != 0); } return(S); }