📄 htstring.c
字号:
/* 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) { size_t size = strlen(src) + 1; FREE(*dest); *dest = (char *) malloc(size); if (*dest == NULL) outofmem(__FILE__, "HTSACopy"); memcpy(*dest, src, size); } } 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) { size_t 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;}/* optimized for heavily realloc'd strings, store length inside */#define EXTRA_TYPE size_t /* type we use for length */#define EXTRA_SIZE sizeof(void *) /* alignment >= sizeof(EXTRA_TYPE) */PUBLIC void HTSAFree_extra ARGS1( char *, s){ free(s - EXTRA_SIZE);}/* never shrink */PUBLIC char * HTSACopy_extra ARGS2( char **, dest, CONST char *, src){ if (src != 0) { size_t srcsize = strlen(src) + 1; EXTRA_TYPE size = 0; if (*dest != 0) { size = *(EXTRA_TYPE *)((*dest) - EXTRA_SIZE); } if (size < srcsize) { FREE_extra(*dest); size = srcsize * 2; /* x2 step */ *dest = (char *) malloc(size + EXTRA_SIZE); if (*dest == NULL) outofmem(__FILE__, "HTSACopy_extra"); *(EXTRA_TYPE *)(*dest) = size; *dest += EXTRA_SIZE; } memcpy(*dest, src, srcsize); } else { Clear_extra(*dest); } 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 (isEmpty(pstr)) return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -