summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/bmhsrch.c
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/CONTRIB/SNIP/bmhsrch.c')
-rwxr-xr-xreference/C/CONTRIB/SNIP/bmhsrch.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/SNIP/bmhsrch.c b/reference/C/CONTRIB/SNIP/bmhsrch.c
new file mode 100755
index 0000000..37aa98a
--- /dev/null
+++ b/reference/C/CONTRIB/SNIP/bmhsrch.c
@@ -0,0 +1,68 @@
+/*
+** Case-sensitive Boyer-Moore-Horspool pattern match
+**
+** public domain by Raymond Gardner 7/92
+**
+** limitation: pattern length + string length must be less than 32767
+**
+** 10/21/93 rdg Fixed bug found by Jeff Dunlop
+*/
+#include <limits.h> /* rdg 10/93 */
+#include <stddef.h>
+#include <string.h>
+
+typedef unsigned char uchar;
+
+#define LARGE 32767
+
+static int patlen;
+static int skip[UCHAR_MAX+1]; /* rdg 10/93 */
+static int skip2;
+static uchar *pat;
+
+void bmh_init(const char *pattern)
+{
+ int i, lastpatchar;
+
+ pat = (uchar *)pattern;
+ patlen = strlen(pattern);
+ for (i = 0; i <= UCHAR_MAX; ++i) /* rdg 10/93 */
+ skip[i] = patlen;
+ for (i = 0; i < patlen; ++i)
+ skip[pat[i]] = patlen - i - 1;
+ lastpatchar = pat[patlen - 1];
+ skip[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 *bmh_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 && 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 */
+ }
+}