bmhsrch.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. /* +++Date last modified: 05-Jul-1997 */
  2. /*
  3. ** Case-sensitive Boyer-Moore-Horspool pattern match
  4. **
  5. ** public domain by Raymond Gardner 7/92
  6. **
  7. ** limitation: pattern length + string length must be less than 32767
  8. **
  9. ** 10/21/93 rdg Fixed bug found by Jeff Dunlop
  10. */
  11. #include <limits.h> /* rdg 10/93 */
  12. #include <stddef.h>
  13. #include <string.h>
  14. typedef unsigned char uchar;
  15. #define LARGE 32767
  16. static int patlen;
  17. static int skip[UCHAR_MAX+1]; /* rdg 10/93 */
  18. static int skip2;
  19. static uchar *pat;
  20. void bmh_init(const char *pattern)
  21. {
  22. int i, lastpatchar;
  23. pat = (uchar *)pattern;
  24. patlen = strlen(pattern);
  25. for (i = 0; i <= UCHAR_MAX; ++i) /* rdg 10/93 */
  26. skip[i] = patlen;
  27. for (i = 0; i < patlen; ++i)
  28. skip[pat[i]] = patlen - i - 1;
  29. lastpatchar = pat[patlen - 1];
  30. skip[lastpatchar] = LARGE;
  31. skip2 = patlen; /* Horspool's fixed second shift */
  32. for (i = 0; i < patlen - 1; ++i)
  33. {
  34. if (pat[i] == lastpatchar)
  35. skip2 = patlen - i - 1;
  36. }
  37. }
  38. char *bmh_search(const char *string, const int stringlen)
  39. {
  40. int i, j;
  41. char *s;
  42. i = patlen - 1 - stringlen;
  43. if (i >= 0)
  44. return NULL;
  45. string += stringlen;
  46. for ( ;; )
  47. {
  48. while ( (i += skip[((uchar *)string)[i]]) < 0 )
  49. ; /* mighty fast inner loop */
  50. if (i < (LARGE - stringlen))
  51. return NULL;
  52. i -= LARGE;
  53. j = patlen - 1;
  54. s = (char *)string + (i - j);
  55. while (--j >= 0 && s[j] == pat[j])
  56. ;
  57. if ( j < 0 ) /* rdg 10/93 */
  58. return s; /* rdg 10/93 */
  59. if ( (i += skip2) >= 0 ) /* rdg 10/93 */
  60. return NULL; /* rdg 10/93 */
  61. }
  62. }