/* ** Case-Insensitive Boyer-Moore-Horspool pattern match ** ** Public Domain version by Thad Smith 7/21/1992, ** based on a 7/92 public domain BMH version by Raymond Gardner. ** ** This program is written in ANSI C and inherits the compilers ** ability (or lack thereof) to support non-"C" locales by use of ** toupper() and tolower() to perform case conversions. ** Limitation: pattern length + string length must be less than 32767. ** ** 10/21/93 rdg Fixed bugs found by Jeff Dunlop */ #include #include #include #include typedef unsigned char uchar; #define LARGE 32767 /* flag for last character match */ static int patlen; /* # chars in pattern */ static int skip[UCHAR_MAX+1]; /* skip-ahead count for test chars */ static int skip2; /* skip-ahead after non-match with ** matching final character */ static uchar *pat = NULL; /* uppercase copy of pattern */ /* ** bmhi_init() is called prior to bmhi_search() to calculate the ** skip array for the given pattern. ** Error: exit(1) is called if no memory is available. */ void bmhi_init(const char *pattern) { int i, lastpatchar; patlen = strlen(pattern); /* Make uppercase copy of pattern */ pat = realloc ((void*)pat, patlen); if (!pat) exit(1); for (i=0; i < patlen; i++) pat[i] = toupper(pattern[i]); /* initialize skip array */ for ( i = 0; i <= UCHAR_MAX; ++i ) /* rdg 10/93 */ skip[i] = patlen; for ( i = 0; i < patlen - 1; ++i ) { skip[ pat[i] ] = patlen - i - 1; skip[tolower(pat[i])] = patlen - i - 1; } lastpatchar = pat[patlen - 1]; skip[ lastpatchar ] = LARGE; skip[tolower(lastpatchar)] = LARGE; skip2 = patlen; /* Horspool's fixed second shift */ for (i = 0; i < patlen - 1; ++i) { if ( pat[i] == lastpatchar ) skip2 = patlen - i - 1; } } char *bmhi_search(const char *string, const int stringlen) { int i, j; char *s; i = patlen - 1 - stringlen; if (i >= 0) return NULL; string += stringlen; for ( ;; ) { while ( (i += skip[((uchar *)string)[i]]) < 0 ) ; /* mighty fast inner loop */ if (i < (LARGE - stringlen)) return NULL; i -= LARGE; j = patlen - 1; s = (char *)string + (i - j); while ( --j >= 0 && toupper(s[j]) == pat[j] ) ; if ( j < 0 ) /* rdg 10/93 */ return s; /* rdg 10/93 */ if ( (i += skip2) >= 0 ) /* rdg 10/93 */ return NULL; /* rdg 10/93 */ } }