4 static char *twobyte_strstr(const unsigned char *h
, const unsigned char *n
)
6 uint16_t nw
= n
[0]<<8 | n
[1], hw
= h
[0]<<8 | h
[1];
7 for (h
++; *h
&& hw
!= nw
; hw
= hw
<<8 | *++h
);
8 return *h
? (char *)h
-1 : 0;
11 static char *threebyte_strstr(const unsigned char *h
, const unsigned char *n
)
13 uint32_t nw
= n
[0]<<24 | n
[1]<<16 | n
[2]<<8;
14 uint32_t hw
= h
[0]<<24 | h
[1]<<16 | h
[2]<<8;
15 for (h
+=2; *h
&& hw
!= nw
; hw
= (hw
|*++h
)<<8);
16 return *h
? (char *)h
-2 : 0;
19 static char *fourbyte_strstr(const unsigned char *h
, const unsigned char *n
)
21 uint32_t nw
= n
[0]<<24 | n
[1]<<16 | n
[2]<<8 | n
[3];
22 uint32_t hw
= h
[0]<<24 | h
[1]<<16 | h
[2]<<8 | h
[3];
23 for (h
+=3; *h
&& hw
!= nw
; hw
= hw
<<8 | *++h
);
24 return *h
? (char *)h
-3 : 0;
27 #define MAX(a,b) ((a)>(b)?(a):(b))
28 #define MIN(a,b) ((a)<(b)?(a):(b))
30 #define BITOP(a,b,op) \
31 ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
33 static char *twoway_strstr(const unsigned char *h
, const unsigned char *n
)
35 const unsigned char *z
;
36 size_t l
, ip
, jp
, k
, p
, ms
, p0
, mem
, mem0
;
37 size_t byteset
[32 / sizeof(size_t)] = { 0 };
40 /* Computing length of needle and fill shift table */
41 for (l
=0; n
[l
] && h
[l
]; l
++)
42 BITOP(byteset
, n
[l
], |=), shift
[n
[l
]] = l
+1;
43 if (n
[l
]) return 0; /* hit the end of h */
45 /* Compute maximal suffix */
46 ip
= -1; jp
= 0; k
= p
= 1;
48 if (n
[ip
+k
] == n
[jp
+k
]) {
53 } else if (n
[ip
+k
] > n
[jp
+k
]) {
65 /* And with the opposite comparison */
66 ip
= -1; jp
= 0; k
= p
= 1;
68 if (n
[ip
+k
] == n
[jp
+k
]) {
73 } else if (n
[ip
+k
] < n
[jp
+k
]) {
82 if (ip
+1 > ms
+1) ms
= ip
;
85 /* Periodic needle? */
86 if (memcmp(n
, n
+p
, ms
+1)) {
88 p
= MAX(ms
, l
-ms
-1) + 1;
92 /* Initialize incremental end-of-haystack pointer */
97 /* Update incremental end-of-haystack pointer */
99 /* Fast estimate for MIN(l,63) */
100 size_t grow
= l
| 63;
101 const unsigned char *z2
= memchr(z
, 0, grow
);
104 if (z
-h
< l
) return 0;
108 /* Check last byte first; advance by shift on mismatch */
109 if (BITOP(byteset
, h
[l
-1], &)) {
111 //printf("adv by %zu (on %c) at [%s] (%zu;l=%zu)\n", k, h[l-1], h, shift[h[l-1]], l);
113 if (mem0
&& mem
&& k
< p
) k
= l
-p
;
124 /* Compare right half */
125 for (k
=MAX(ms
+1,mem
); n
[k
] && n
[k
] == h
[k
]; k
++);
131 /* Compare left half */
132 for (k
=ms
+1; k
>mem
&& n
[k
-1] == h
[k
-1]; k
--);
133 if (k
<= mem
) return (char *)h
;
139 char *strstr(const char *h
, const char *n
)
141 /* Return immediately on empty needle */
142 if (!n
[0]) return (char *)h
;
144 /* Use faster algorithms for short needles */
146 if (!h
|| !n
[1]) return (char *)h
;
148 if (!n
[2]) return twobyte_strstr((void *)h
, (void *)n
);
150 if (!n
[3]) return threebyte_strstr((void *)h
, (void *)n
);
152 if (!n
[4]) return fourbyte_strstr((void *)h
, (void *)n
);
154 return twoway_strstr((void *)h
, (void *)n
);