/*
* 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 <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#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)<strlen(s2)) len=strlen(s1); else len=strlen(s2);
if (strncmp(s1,s2,len)==0) return(1); else return(0);
}
/*
* str_neq_nocase - string equal test until length n, ignoring case
*
* INPUT: s1 - string 1
* s1 - string 1
* len - max length to compare
*
* RETURN: 1 if is equal, 0 if is not equal (until size len)
*/
int str_neq_nocase(const char *s1, const char *s2, int len) {
int i;
char a,b;
for (i=0;i<len;i++) {
a=s1[i];
b=s2[i];
if (tolower(a)!=tolower(b)) return(0);
}
return(1);
}
/*
* str_beq_nocase - string begin equal test, ignoring case
*
* INPUT: s1 - string 1
* s1 - string 1
*
* RETURN: 1 if begin is equal, 0 if begin is not equal
*/
int str_beq_nocase(const char *s1, const char *s2) {
int len;
if (strlen(s1)<strlen(s2)) len=strlen(s1); else len=strlen(s2);
return(str_neq_nocase(s1,s2,len));
}
/***************************************************************
* simplematch:
*
* simple wildcard matching
*
* ? matches any single character
* * matches any string
* [abc] matches 'a' or 'b' or 'c'
* within [] the characters '?', '*' and '[' are no wildcards
* [^abc] matches every character but not 'a' or 'b' or 'c'
* [a-d] matches 'a' or 'b' or 'c' or 'd' (range)
* this is equal to [abcd]
* [^a-d] matches every character but not 'a' or 'b' or 'c' or 'd' (range)
* this is equal to [^abcd]
* \? test for "true" '?' alternative: [?]
* \* test for "true" '*' alternative: [*]
* \[ test for "true" '[' alternative: [[]
* \a Bell
* \b BackSpace
* \f FormFeed
* \n NewLine
* \r Return
* \t Tab
* \v FormFeed
* \\ Backslash
*
* ACHTUNG: "[]" (empty brackets) always fails!
*
* Copyright (C) 1991 by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation. This software is provided "as is" without express or
* implied warranty.
*/
/*
#include <stddef.h>
#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 <stdio.h>
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);
}
syntax highlighted by Code2HTML, v. 0.9.1