wcsstr.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #include <wchar.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <stdint.h>
  5. static wchar_t *naive_wcsstr(const wchar_t *h, const wchar_t *n)
  6. {
  7. size_t i;
  8. for (i=0; n[i] && h[i]; i++)
  9. for ( ; n[i] != h[i]; h++, i=0);
  10. return n[i] ? 0 : (wchar_t *)h;
  11. }
  12. #define MAX(a,b) ((a)>(b)?(a):(b))
  13. #define MIN(a,b) ((a)<(b)?(a):(b))
  14. static wchar_t *twoway_wcsstr(const wchar_t *h, const wchar_t *n)
  15. {
  16. const wchar_t *z;
  17. size_t l, ip, jp, k, p, ms, p0, mem, mem0;
  18. /* Computing length of needle */
  19. for (l=0; n[l] && h[l]; l++);
  20. if (n[l]) return 0; /* hit the end of h */
  21. /* Compute maximal suffix */
  22. ip = -1; jp = 0; k = p = 1;
  23. while (jp+k<l) {
  24. if (n[ip+k] == n[jp+k]) {
  25. if (k == p) {
  26. jp += p;
  27. k = 1;
  28. } else k++;
  29. } else if (n[ip+k] > n[jp+k]) {
  30. jp += k;
  31. k = 1;
  32. p = jp - ip;
  33. } else {
  34. ip = jp++;
  35. k = p = 1;
  36. }
  37. }
  38. ms = ip;
  39. p0 = p;
  40. /* And with the opposite comparison */
  41. ip = -1; jp = 0; k = p = 1;
  42. while (jp+k<l) {
  43. if (n[ip+k] == n[jp+k]) {
  44. if (k == p) {
  45. jp += p;
  46. k = 1;
  47. } else k++;
  48. } else if (n[ip+k] < n[jp+k]) {
  49. jp += k;
  50. k = 1;
  51. p = jp - ip;
  52. } else {
  53. ip = jp++;
  54. k = p = 1;
  55. }
  56. }
  57. if (ip+1 > ms+1) ms = ip;
  58. else p = p0;
  59. /* Periodic needle? */
  60. if (wmemcmp(n, n+p, ms+1)) {
  61. mem0 = 0;
  62. p = MAX(ms, l-ms-1) + 1;
  63. } else mem0 = l-p;
  64. mem = 0;
  65. /* Initialize incremental end-of-haystack pointer */
  66. z = h;
  67. /* Search loop */
  68. for (;;) {
  69. /* Update incremental end-of-haystack pointer */
  70. if (z-h < l) {
  71. /* Fast estimate for MIN(l,63) */
  72. size_t grow = l | 63;
  73. const wchar_t *z2 = wmemchr(z, 0, grow);
  74. if (z2) {
  75. z = z2;
  76. if (z-h < l) return 0;
  77. } else z += grow;
  78. }
  79. /* Compare right half */
  80. for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
  81. if (n[k]) {
  82. h += k-ms;
  83. mem = 0;
  84. continue;
  85. }
  86. /* Compare left half */
  87. for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
  88. if (k == mem) return (wchar_t *)h;
  89. h += p;
  90. mem = mem0;
  91. }
  92. }
  93. wchar_t *wcsstr(const wchar_t *h, const wchar_t *n)
  94. {
  95. /* Return immediately on empty needle or haystack */
  96. if (!n[0]) return (wchar_t *)h;
  97. if (!h[0]) return 0;
  98. /* Use faster algorithms for short needles */
  99. h = wcschr(h, *n);
  100. if (!h || !n[1]) return (wchar_t *)h;
  101. if (!h[1]) return 0;
  102. if (!n[2] || !n[3] || !n[4]) return naive_wcsstr(h, n);
  103. return twoway_wcsstr(h, n);
  104. }