home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************\
- strstuff.c: a set of string functions,
- more powerful than those from the standard library in <string.h>
- \*************************************************************************/
-
- #include <stddef.h>
- #include <stdio.h>
- #include "strstuff.h"
-
- UBYTE to_upper[256]; /* conversion table */
- int is_space[256]; /* lookup table */
- int bordermode, case_sense;
-
- void str_setup(int bm, int cs)
- /* Set up a conversion table that can convert all national characters from
- * the ISO 8859-1/ECMA 94 charset to uppercase, not only 'a'-'z'.
- * Depending on the global variable <case_sense> this table may just as
- * well do nothing at all. Similarly, the is_space[] table which is built
- * here, too, may call anything but alphanumerics a 'space', depending on
- * the setting of <bordermode>.
- */
- {
- int c,d;
-
- bordermode = bm; case_sense = cs; /* set global variables */
- for (c=0; c<256; c++) {
- to_upper[c] = c;
- is_space[c] = (bordermode<2 || (c & 0x7f)<=' ');
- }
- for (c='a'; c<='z'; c++) {
- d = c + 'A'-'a'; to_upper[c] = d;
- is_space[c] = 0; is_space[d] = 0;
- }
- for (c='0'; c<='9'; c++) {
- is_space[c] = 0;
- }
- for (c=224; c<256; c++)
- if (c != 247) { /* 247 is the division sign -:- */
- d = c - 32;
- is_space[c] = 0; is_space[d] = 0;
- if (c != 255) /* and don't convert '"y' to 'ss' :) */
- to_upper[c] = d;
- }
- if (case_sense) /* destroy the to_upper[] table again */
- for (c=0; c<256; c++)
- to_upper[c] = c;
- is_space[0] = 0; /* important, will be taken advantage of! */
- }
-
-
- int str_cmp(UBYTE *s, UBYTE *t)
- /* Will work like strcmp(), if (case_sense && bordermode == 3), but can
- * change its behaviour depending on those variables.
- * Will also indicate by special (but legal) return values if <s> was an
- * abbreviation of <t> or vice versa.
- */
- {
- if (bordermode<3) { /* modes where number of 'spaces' doesn't count */
- while (is_space[*s]) s++; /* advance to first word */
- while (is_space[*t]) t++;
- while (to_upper[*s] == to_upper[*t]) {
- if (*s == '\0') return 0;
- s++; t++;
- if (!bordermode || is_space[*s] && is_space[*t]) {
- /* both at the end of a word OR in sloppy bordermode */
- while (is_space[*s]) s++; /* skip the spaces */
- while (is_space[*t]) t++;
- }
- }
- } else {
- while (to_upper[*s] == to_upper[*t]) {
- if (*s == '\0') return 0;
- s++; t++;
- }
- }
- if (*s=='\0')
- return STR_SHORTER;
- else if (*t=='\0')
- return STR_LONGER;
- else
- return (to_upper[*s] - to_upper[*t]);
- }
-
-
- int strn_cmp(UBYTE *s, UBYTE *t, size_t n)
- /* The same as str_cmp, but will only compare up to <n> characters.
- * (Only two lines of code are different.)
- */
- {
- if (bordermode<3) {
- while (is_space[*s]) s++;
- while (is_space[*t]) t++;
- while (to_upper[*s] == to_upper[*t]) {
- if (--n == 0 || *s == '\0') return 0; /* that's the difference */
- s++; t++;
- if (!bordermode || is_space[*s] && is_space[*t]) {
- while (is_space[*s]) s++;
- while (is_space[*t]) t++;
- }
- }
- } else {
- while (to_upper[*s] == to_upper[*t]) {
- if (--n == 0 || *s == '\0') return 0; /* and here once more */
- s++; t++;
- }
- }
- if (*s=='\0')
- return STR_SHORTER;
- else if (*t=='\0')
- return STR_LONGER;
- else
- return (to_upper[*s] - to_upper[*t]);
- }
-
-
- UBYTE *str_str(UBYTE *s, UBYTE *t)
- /* find a copy of t in s, like strstr() does */
- {
- int c;
-
- while (*s) {
- c = str_cmp(s, t);
- if (c == 0 || c == STR_LONGER)
- return s;
- s++;
- }
- return NULL;
- }
-
-
- void print_strstat(void)
- /* some user info printed to <stdout> */
- {
- printf("string processing:\n");
- printf(" upper-/lowercase: ");
- if (case_sense) printf("fussy\n"); else printf("'ABC'='abc'\n");
- printf(" word delimiters: ");
- switch (bordermode) {
- case 0: printf("'a,b c'='abc'\n"); break;
- case 1: printf("'a, b, c'='a,b c'\n"); break;
- case 2: printf("'a b c'='a b c'\n"); break;
- case 3: printf("fussy\n"); break;
- }
- }
-