Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
4.9 KiB

  1. /*-----------------------------------------------------------------------------
  2. Program Specification
  3. in: search space s, pattern p
  4. out: a pointer where p is exactly matched at s[i], NULL indicates fail
  5. why: Boyer-Moore algorithm is best for general text search. On
  6. "average" it takes length(s)/length(p) steps to match p in s.
  7. ref: I recommend the following references:
  8. "Algorithms". Robert Sedgewick. Addison Wesley Publishing Company.
  9. 1988. 2nd addition. p286. QA76.6.S435 1983
  10. "Faster String Searches". Doctor Dobb's Journal. Volume 14
  11. Issue 7 July 1989. Costas Menico. p74.
  12. usage: e.g. to find a pattern "tiger" in a text in RAM starting at
  13. pointer "txtp" with a length of 1, 000,000 characters,
  14. program like this:
  15. LPSTR matchp;
  16. SetFindPattern( "tiger" );
  17. matchp = Find( txtp, 1000000L );
  18. if (matchp != NULL)
  19. // found
  20. else
  21. // not found
  22. matchp = FindBackward( txtp + 1000000L - 1, 1000000L);
  23. if (matchp != NULL)
  24. // found
  25. else
  26. // not found
  27. Q: Can I use Find() with a GlobalLock() pointer in Windows?
  28. A: Yes.
  29. Q: Must I delcare my pointer as HPSTR (huge pointer) ?
  30. A: Not necessary. Find() and FindBackward() will convert your
  31. LPSTR as HPSTR. However, in your own code you must aware
  32. that you are holding a LPSTR and take care of the pointer
  33. arithmetic and conversion. (see demo.c for example)
  34. Q: What is the limit of the memory space I can search?
  35. A: To the limit of huge pointer implementation and your hardware.
  36. -----------------------------------------------------------------------------*/
  37. #include "pch.hpp"
  38. /*-----------------------------------------------------------------------------
  39. func: SetFindPattern
  40. desc: initialize the pattern to be matched and generate skip table
  41. pass: lpszPattern = pattern string
  42. rtrn: HFIND - the find handle for further text search
  43. -----------------------------------------------------------------------------*/
  44. HFIND SetFindPattern( LPSTR lpszPattern )
  45. {
  46. register unsigned int j;
  47. register CHAR c;
  48. HFIND hfind;
  49. hfind = (HFIND)MyAlloc(sizeof(FINDSTRUCT));
  50. hfind->plen = lstrlenA( lpszPattern );
  51. if (hfind->plen > MAXPAT)
  52. hfind->plen = MAXPAT;
  53. lstrcpyA( (LPSTR)(hfind->p), lpszPattern );
  54. for (j=0; j<256; j++)
  55. {
  56. hfind->skip[j] = hfind->plen;
  57. }
  58. for (j=0; j<hfind->plen; j++)
  59. {
  60. c = lpszPattern[j];
  61. hfind->skip[c] = hfind->plen - (j +1);
  62. }
  63. return (hfind);
  64. }
  65. /*-----------------------------------------------------------------------------
  66. func: FreeFindPattern
  67. desc: free the memory occupied by SetFindPattern
  68. pass: hfind - the find handle
  69. rtrn: nothing
  70. -----------------------------------------------------------------------------*/
  71. void FreeFindPattern( HFIND hfind )
  72. {
  73. MyFree((LPSTR)hfind);
  74. }
  75. /*-----------------------------------------------------------------------------
  76. func: Find
  77. desc: match a pattern defined in SetFindPattern against string s
  78. pass: hfind = the find handle created by SetFindPattern
  79. s = start of search space, slen = length of s
  80. rtrn: NULL = match fail
  81. else = a LPSTR to p[0] in s matches p
  82. -----------------------------------------------------------------------------*/
  83. LPSTR Find( HFIND hfind, LPSTR s, long slen )
  84. {
  85. register int i;
  86. unsigned int n, j;
  87. register unsigned char c;
  88. LPSTR lpresult;
  89. i = hfind->plen;
  90. j = hfind->plen;
  91. do
  92. {
  93. c = *(s + (i - 1));
  94. if (c == hfind->p[j - 1])
  95. {
  96. i--;
  97. j--;
  98. }
  99. else
  100. {
  101. n = hfind->plen - j + 1;
  102. if (n > hfind->skip[c] )
  103. {
  104. i += n;
  105. }
  106. else
  107. {
  108. i += hfind->skip[c];
  109. }
  110. j = hfind->plen;
  111. }
  112. }
  113. while ((j >= 1) && (i <= slen));
  114. /* match fails */
  115. if (i >= slen)
  116. {
  117. lpresult = (LPSTR)NULL;
  118. }
  119. /* match successful */
  120. else
  121. {
  122. lpresult = s + i;
  123. }
  124. return (lpresult);
  125. }
  126. #ifdef TEST_MAIN
  127. #pragma message("Building with TEST_MAIN")
  128. #include <stdio.h>
  129. CHAR test_buffer[]=L"___________12191919191919This is string for testing our find ___________12191919191919function 12abE Is it in here somehwere ?";
  130. CHAR test_pattern[]=L"___________12191919191919";
  131. void main(void)
  132. {
  133. HFIND hFind;
  134. CHAR *tmp;
  135. hFind=SetFindPattern(test_pattern);
  136. tmp=Find(hFind, test_buffer, strlen(test_buffer));
  137. if (tmp!=NULL) wsprintf(L"Found pattern at offset %u, %s", tmp-test_buffer,tmp);
  138. FreeFindPattern(hFind);
  139. }
  140. #endif