⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 htstring.c

📁 用于linux和其他unix下面的
💻 C
📖 第 1 页 / 共 2 页
字号:
/*		Case-independent string comparison		HTString.c****	Original version came with listserv implementation.**	Version TBL Oct 91 replaces one which modified the strings.**	02-Dec-91 (JFG) Added stralloccopy and stralloccat**	23 Jan 92 (TBL) Changed strallocc* to 8 char HTSAC* for VM and suchlike**	 6 Oct 92 (TBL) Moved WWW_TraceFlag in here to be in library**	15 Nov 98 (TD)  Added HTSprintf.*/#include <HTUtils.h>#include <LYLeaks.h>#include <LYStrings.h>#ifndef NO_LYNX_TRACEPUBLIC BOOLEAN WWW_TraceFlag = 0;	/* Global trace flag for ALL W3 code */PUBLIC int WWW_TraceMask = 0;		/* Global trace flag for ALL W3 code */#endif#ifndef VC#define VC "unknown"#endif /* !VC */#ifdef _WINDOWSCONST char * HTLibraryVersion = "2.14FM"; /* String for help screen etc */#elsePUBLIC CONST char * HTLibraryVersion = VC; /* String for help screen etc */#endif/***     strcasecomp8 is a variant of strcasecomp (below)**     ------------		    -----------**     but uses 8bit upper/lower case information**     from the current display charset.**     It returns 0 if exact match.*/PUBLIC int strcasecomp8 ARGS2(       CONST char*,    a,       CONST char *,   b){    CONST char *p = a;    CONST char *q = b;    for ( ; *p && *q; p++, q++) {	int diff = UPPER8(*p, *q);	if (diff) return diff;    }    if (*p)	return 1;	/* p was longer than q */    if (*q)	return -1;	/* p was shorter than q */    return 0;		/* Exact match */}/***     strncasecomp8 is a variant of strncasecomp (below)**     -------------		     ------------**     but uses 8bit upper/lower case information**     from the current display charset.**     It returns 0 if exact match.*/PUBLIC int strncasecomp8 ARGS3(	CONST char*,	a,	CONST char *,	b,	int,		n){    CONST char *p = a;    CONST char *q = b;    for ( ; ; p++, q++) {	int diff;	if (p == (a+n))	    return 0;	/*   Match up to n characters */	if (!(*p && *q))	    return (*p - *q);	diff = UPPER8(*p, *q);	if (diff)	    return diff;    }    /*NOTREACHED*/}#ifndef VM		/* VM has these already it seems */#ifdef SH_EX	/* 1997/12/23 (Tue) 16:40:31 *//* * This array is designed for mapping upper and lower case letter * together for a case independent comparison.  The mappings are * based upon ascii character sequences. */static unsigned char charmap[] = {	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\327',	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337',	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',};PUBLIC int strcasecomp ARGS2(	CONST char*,	s1,	CONST char*,	s2){    register unsigned char *cm = charmap;    register unsigned char *us1 = (unsigned char *)s1;    register unsigned char *us2 = (unsigned char *)s2;    while (cm[*us1] == cm[*us2++])	if (*us1++ == '\0')	    return(0);    return (cm[*us1] - cm[*--us2]);}PUBLIC int strncasecomp ARGS3(	CONST char*,	a,	CONST char*,	b,	int,		n){    register unsigned char *cm = charmap;    register unsigned char *us1 = (unsigned char *)a;    register unsigned char *us2 = (unsigned char *)b;    while ((long)(--n) >= 0 && cm[*us1] == cm[*us2++])	if (*us1++ == '\0')	    return(0);    return ((long)n < 0 ? 0 : cm[*us1] - cm[*--us2]);}#else	/* SH_EX *//*	Strings of any length**	---------------------*/PUBLIC int strcasecomp ARGS2(	CONST char*,	a,	CONST char *,	b){    CONST char *p = a;    CONST char *q = b;    for ( ; *p && *q; p++, q++) {	int diff = TOLOWER(*p) - TOLOWER(*q);	if (diff) return diff;    }    if (*p)	return 1;	/* p was longer than q */    if (*q)	return -1;	/* p was shorter than q */    return 0;		/* Exact match */}/*	With count limit**	----------------*/PUBLIC int strncasecomp ARGS3(	CONST char*,	a,	CONST char *,	b,	int,		n){    CONST char *p = a;    CONST char *q = b;    for ( ; ; p++, q++) {	int diff;	if (p == (a+n))	    return 0;	/*   Match up to n characters */	if (!(*p && *q))	    return (*p - *q);	diff = TOLOWER(*p) - TOLOWER(*q);	if (diff)	    return diff;    }    /*NOTREACHED*/}#endif	/* SH_EX */#endif /* VM */#ifdef NOT_ASCII/*	Case-insensitive with ASCII collating sequence**	----------------*/PUBLIC int AS_casecomp ARGS2(	CONST char*,	p,	CONST char*,	q){    int diff;    for ( ; ; p++, q++) {	if (!(*p && *q))	    return (UCH(*p)  - UCH(*q));	diff = TOASCII(TOLOWER(*p))	     - TOASCII(TOLOWER(*q));	if (diff)	    return diff;    }    /*NOTREACHED*/}/*	With count limit and ASCII collating sequence**	----------------**	AS_cmp uses n == -1 to compare indefinite length.*/PUBLIC int AS_ncmp ARGS3(	CONST char *,	p,	CONST char *,	q,	unsigned int,	n){    CONST char *a = p;    int diff;    for ( ; (p-a) < n; p++, q++) {	if (!(*p && *q))	    return (UCH(*p) - UCH(*q));	diff = TOASCII(*p)	     - TOASCII(*q);	if (diff)	    return diff;    }    return 0;	/*   Match up to n characters */}/*	With ASCII collating sequence**	----------------*/PUBLIC int AS_cmp ARGS2(	CONST char *,	p,	CONST char *,	q){    return( AS_ncmp( p, q, -1 ) );}#endif /* NOT_ASCII *//*	Allocate a new copy of a string, and returns it*/PUBLIC char * HTSACopy ARGS2(	char **,	dest,	CONST char *,	src){    if (src != 0) {	if (src != *dest) {	    FREE(*dest);	    *dest = (char *) malloc (strlen(src) + 1);	    if (*dest == NULL)		outofmem(__FILE__, "HTSACopy");	    strcpy (*dest, src);	}    } else {	FREE(*dest);    }    return *dest;}/*	String Allocate and Concatenate*/PUBLIC char * HTSACat ARGS2(	char **,	dest,	CONST char *,	src){    if (src && *src && (src != *dest)) {	if (*dest) {	    int length = strlen(*dest);	    *dest = (char *)realloc(*dest, length + strlen(src) + 1);	    if (*dest == NULL)		outofmem(__FILE__, "HTSACat");	    strcpy (*dest + length, src);	} else {	    *dest = (char *)malloc(strlen(src) + 1);	    if (*dest == NULL)		outofmem(__FILE__, "HTSACat");	    strcpy (*dest, src);	}    }    return *dest;}/*	Find next Field**	---------------**** On entry,**	*pstr	points to a string containig white space separated**		field, optionlly quoted.**** On exit,**	*pstr	has been moved to the first delimiter past the**		field**		THE STRING HAS BEEN MUTILATED by a 0 terminator****	returns a pointer to the first field*/PUBLIC char * HTNextField ARGS1(	char **,	pstr){    char * p = *pstr;    char * start;			/* start of field */    while (*p && WHITE(*p))	p++;				/* Strip white space */    if (!*p) {	*pstr = p;	return NULL;		/* No first field */    }    if (*p == '"') {			/* quoted field */	p++;	start = p;	for (; *p && *p!='"'; p++) {	    if (*p == '\\' && p[1])		p++;			/* Skip escaped chars */	}    } else {	start = p;	while (*p && !WHITE(*p))	    p++;			/* Skip first field */    }    if (*p)	*p++ = '\0';    *pstr = p;    return start;}/*	Find next Token**	---------------**	Finds the next token in a string**	On entry,**	*pstr	points to a string to be parsed.**	delims	lists characters to be recognized as delimiters.**		If NULL, default is white space "," ";" or "=".**		The word can optionally be quoted or enclosed with**		chars from bracks.**		Comments surrrounded by '(' ')' are filtered out**		unless they are specifically reqested by including**		' ' or '(' in delims or bracks.**	bracks	lists bracketing chars.  Some are recognized as**		special, for those give the opening char.**		If NULL, defaults to <"> and "<" ">".**	found	points to location to fill with the ending delimiter**		found, or is NULL.****	On exit,**	*pstr	has been moved to the first delimiter past the**		field**		THE STRING HAS BEEN MUTILATED by a 0 terminator**	found	points to the delimiter found unless it was NULL.**	Returns a pointer to the first word or NULL on error*/PUBLIC char * HTNextTok ARGS4(	char **,	pstr,	CONST char *,	delims,	CONST char *,	bracks,	char *,		found){    char * p = *pstr;    char * start = NULL;    BOOL get_blanks, skip_comments;    BOOL get_comments;    BOOL get_closing_char_too = FALSE;    char closer;    if (!pstr || !*pstr) return NULL;    if (!delims) delims = " ;,=" ;    if (!bracks) bracks = "<\"" ;    get_blanks = (BOOL) (!strchr(delims,' ') && !strchr(bracks,' '));    get_comments = (BOOL) (strchr(bracks,'(') != NULL);    skip_comments = (BOOL) (!get_comments && !strchr(delims,'(') && !get_blanks);#define skipWHITE(c) (!get_blanks && WHITE(c))    while (*p && skipWHITE(*p))	p++;				/* Strip white space */    if (!*p) {	*pstr = p;	if (found) *found = '\0';	return NULL;		/* No first field */    }    while (1) {	/* Strip white space and other delimiters */	while (*p && (skipWHITE(*p) || strchr(delims,*p))) p++;	if (!*p) {	    *pstr = p;	    if (found) *found = *(p-1);	    return NULL;					 /* No field */	}	if (*p == '(' && (skip_comments || get_comments)) {	  /* Comment */	    int comment_level = 0;	    if (get_comments && !start) start = p+1;	    for(;*p && (*p!=')' || --comment_level>0); p++) {		if (*p == '(') comment_level++;		else if (*p == '"') {	      /* quoted field within Comment */		    for(p++; *p && *p!='"'; p++)			if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */		    if (!*p) break; /* (invalid) end of string found, leave */		}		if (*p == '\\' && *(p+1)) p++;	       /* Skip escaped chars */	    }	    if (get_comments)		break;	    if (*p) p++;	    if (get_closing_char_too) {		if (!*p || (!strchr(bracks,*p) && strchr(delims,*p))) {		    break;		} else		    get_closing_char_too = (BOOL) (strchr(bracks,*p) != NULL);	    }	} else if (strchr(bracks,*p)) {	       /* quoted or bracketed field */	    switch (*p) {	       case '<': closer = '>'; break;	       case '[': closer = ']'; break;	       case '{': closer = '}'; break;	       case ':': closer = ';'; break;	    default:	 closer = *p;	    }	    if (!start) start = ++p;	    for(;*p && *p!=closer; p++)		if (*p == '\\' && *(p+1)) p++;	       /* Skip escaped chars */	    if (get_closing_char_too) {		p++;		if (!*p || (!strchr(bracks,*p) && strchr(delims,*p))) {		    break;		} else		    get_closing_char_too = (BOOL) (strchr(bracks,*p) != NULL);	    } else	    break;			    /* kr95-10-9: needs to stop here */	} else {					      /* Spool field */	    if (!start) start = p;	    while(*p && !skipWHITE(*p) && !strchr(bracks,*p) &&					  !strchr(delims,*p))		p++;	    if (*p && strchr(bracks,*p)) {		get_closing_char_too = TRUE;	    } else {		if (*p=='(' && skip_comments) {		    *pstr = p;		    HTNextTok(pstr, NULL, "(", found);	/*	Advance pstr */		    *p = '\0';		    if (*pstr && **pstr) (*pstr)++;		    return start;		}		    break;					   /* Got it */	    }	}    }    if (found) *found = *p;    if (*p) *p++ = '\0';    *pstr = p;    return start;}PRIVATE char *HTAlloc ARGS2(char *, ptr, size_t, length){    if (ptr != 0)	ptr = (char *)realloc(ptr, length);    else	ptr = (char *)malloc(length);    if (ptr == 0)	outofmem(__FILE__, "HTAlloc");    return ptr;}/* * If SAVE_TIME_NOT_SPACE is defined, StrAllocVsprintf will hang on to * its temporary string buffers instead of allocating and freeing them * in each invocation.  They only grow and never shrink, and won't be * cleaned up on exit. - kw */#if defined(_REENTRANT) || defined(_THREAD_SAFE) || defined(LY_FIND_LEAKS)#undef SAVE_TIME_NOT_SPACE#endif/* * Replacement for sprintf, allocates buffer on the fly according to what's needed * for its arguments.  Unlike sprintf, this always concatenates to the destination * buffer, so we do not have to provide both flavors. */typedef enum { Flags, Width, Prec, Type, Format } PRINTF;#define VA_INTGR(type) ival = va_arg((*ap), type)#define VA_FLOAT(type) fval = va_arg((*ap), type)#define VA_POINT(type) pval = (void *)va_arg((*ap), type)#define NUM_WIDTH 10	/* allow for width substituted for "*" in "%*s" */		/* also number of chars assumed to be needed in addition		   to a given precision in floating point formats */#define GROW_EXPR(n) (((n) * 3) / 2)#define GROW_SIZE 256PUBLIC_IF_FIND_LEAKS char * StrAllocVsprintf ARGS4(	char **,	pstr,	size_t,		dst_len,	CONST char *,	fmt,	va_list *,	ap){#ifdef SAVE_TIME_NOT_SPACE    static size_t tmp_len = 0;    static size_t fmt_len = 0;    static char *tmp_ptr = NULL;    static char *fmt_ptr = NULL;#else    size_t tmp_len = GROW_SIZE;    char *tmp_ptr = 0;    char *fmt_ptr;#endif /* SAVE_TIME_NOT_SPACE */    size_t have, need;    char *dst_ptr = *pstr;    CONST char *format = fmt;    if (fmt == 0 || *fmt == '\0')	return 0;#ifdef USE_VASPRINTF    if (pstr && !dst_len) {	if (*pstr)	    FREE(*pstr);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -