Advertisement
Guest User

TOTO

a guest
Oct 17th, 2019
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.70 KB | None | 0 0
  1. #include <string.h>
  2. #include <limits.h>
  3.  
  4. static inline ssize_t max(ssize_t a, ssize_t b) { return a > b ? a : b; }
  5.  
  6. /* This helper function checks, whether the last "portion" bytes
  7. * of "needle" (which is "nlen" bytes long) exist within the "needle"
  8. * at offset "offset" (counted from the end of the string),
  9. * and whether the character preceding "offset" is not a match.
  10. * Notice that the range being checked may reach beyond the
  11. * beginning of the string. Such range is ignored.
  12. */
  13. static inline int boyermoore_needlematch(
  14. const unsigned char* needle, size_t nlen,
  15. size_t portion, size_t offset)
  16. {
  17. ssize_t virtual_begin = nlen - offset - portion;
  18. ssize_t ignore = 0;
  19.  
  20. if (virtual_begin < 0) {
  21. ignore = -virtual_begin;
  22. virtual_begin = 0;
  23. }
  24. if (virtual_begin > 0 && needle[virtual_begin - 1] == needle[nlen-portion - 1])
  25. return 0;
  26. return memcmp(
  27. needle + nlen - portion + ignore,
  28. needle + virtual_begin,
  29. portion - ignore) == 0;
  30. }
  31.  
  32. /* Returns a pointer to the first occurrence of "needle"
  33. * within "haystack", or NULL if not found.
  34. */
  35. const unsigned char* memmem_boyermoore(
  36. const unsigned char* haystack, size_t hlen,
  37. const unsigned char* needle, size_t nlen)
  38. {
  39. size_t *skip; /* Array of shifts with self-substring match check */
  40. size_t a, hpos;
  41. ssize_t occ[UCHAR_MAX + 1]; /* Array of last occurrence of each character */
  42.  
  43. if (nlen > hlen || nlen <= 0 || !haystack || !needle)
  44. return NULL;
  45.  
  46. /* Preprocess #1: init occ[] */
  47. /* Initialize the table to default value */
  48. for (a = UCHAR_MAX + 1; --a >= 0)
  49. occ[a] = -1;
  50. /* Then populate it with the analysis of the needle */
  51. /* But ignoring the last letter */
  52. for (a = 0 ; a < nlen - 1 ; a++)
  53. occ[needle[a]] = a;
  54.  
  55. /* Preprocess #2: init skip[] */
  56. /* Note: This step could be made a lot faster.
  57. * A simple implementation is shown here. */
  58. skip = (size_t *) malloc(nlen * sizeof(size_t));
  59. /* We should check here if skip is NULL (allocation failed) ! */
  60. for (a = 0; a < nlen; ++a) {
  61. size_t value = 0;
  62. while (value < nlen && !boyermoore_needlematch(needle, nlen, a, value))
  63. ++value;
  64. skip[nlen - a - 1] = value;
  65. }
  66.  
  67. /* Search */
  68. for (hpos = 0; hpos <= hlen - nlen; ) {
  69. size_t npos = nlen - 1;
  70. while (needle[npos] == haystack[npos + hpos]) {
  71. if (npos == 0) {
  72. free(skip);
  73. return haystack + hpos;
  74. }
  75. --npos;
  76. }
  77. hpos += max(skip[npos], npos - occ[haystack[npos + hpos]]);
  78. }
  79. free(skip);
  80. return NULL;
  81. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement