1*c9945492SAndroid Build Coastguard Worker #include <string.h>
2*c9945492SAndroid Build Coastguard Worker #include <stdint.h>
3*c9945492SAndroid Build Coastguard Worker
twobyte_strstr(const unsigned char * h,const unsigned char * n)4*c9945492SAndroid Build Coastguard Worker static char *twobyte_strstr(const unsigned char *h, const unsigned char *n)
5*c9945492SAndroid Build Coastguard Worker {
6*c9945492SAndroid Build Coastguard Worker uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
7*c9945492SAndroid Build Coastguard Worker for (h++; *h && hw != nw; hw = hw<<8 | *++h);
8*c9945492SAndroid Build Coastguard Worker return *h ? (char *)h-1 : 0;
9*c9945492SAndroid Build Coastguard Worker }
10*c9945492SAndroid Build Coastguard Worker
threebyte_strstr(const unsigned char * h,const unsigned char * n)11*c9945492SAndroid Build Coastguard Worker static char *threebyte_strstr(const unsigned char *h, const unsigned char *n)
12*c9945492SAndroid Build Coastguard Worker {
13*c9945492SAndroid Build Coastguard Worker uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8;
14*c9945492SAndroid Build Coastguard Worker uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8;
15*c9945492SAndroid Build Coastguard Worker for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8);
16*c9945492SAndroid Build Coastguard Worker return *h ? (char *)h-2 : 0;
17*c9945492SAndroid Build Coastguard Worker }
18*c9945492SAndroid Build Coastguard Worker
fourbyte_strstr(const unsigned char * h,const unsigned char * n)19*c9945492SAndroid Build Coastguard Worker static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n)
20*c9945492SAndroid Build Coastguard Worker {
21*c9945492SAndroid Build Coastguard Worker uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
22*c9945492SAndroid Build Coastguard Worker uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
23*c9945492SAndroid Build Coastguard Worker for (h+=3; *h && hw != nw; hw = hw<<8 | *++h);
24*c9945492SAndroid Build Coastguard Worker return *h ? (char *)h-3 : 0;
25*c9945492SAndroid Build Coastguard Worker }
26*c9945492SAndroid Build Coastguard Worker
27*c9945492SAndroid Build Coastguard Worker #define MAX(a,b) ((a)>(b)?(a):(b))
28*c9945492SAndroid Build Coastguard Worker #define MIN(a,b) ((a)<(b)?(a):(b))
29*c9945492SAndroid Build Coastguard Worker
30*c9945492SAndroid Build Coastguard Worker #define BITOP(a,b,op) \
31*c9945492SAndroid Build Coastguard Worker ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
32*c9945492SAndroid Build Coastguard Worker
twoway_strstr(const unsigned char * h,const unsigned char * n)33*c9945492SAndroid Build Coastguard Worker static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
34*c9945492SAndroid Build Coastguard Worker {
35*c9945492SAndroid Build Coastguard Worker const unsigned char *z;
36*c9945492SAndroid Build Coastguard Worker size_t l, ip, jp, k, p, ms, p0, mem, mem0;
37*c9945492SAndroid Build Coastguard Worker size_t byteset[32 / sizeof(size_t)] = { 0 };
38*c9945492SAndroid Build Coastguard Worker size_t shift[256];
39*c9945492SAndroid Build Coastguard Worker
40*c9945492SAndroid Build Coastguard Worker /* Computing length of needle and fill shift table */
41*c9945492SAndroid Build Coastguard Worker for (l=0; n[l] && h[l]; l++)
42*c9945492SAndroid Build Coastguard Worker BITOP(byteset, n[l], |=), shift[n[l]] = l+1;
43*c9945492SAndroid Build Coastguard Worker if (n[l]) return 0; /* hit the end of h */
44*c9945492SAndroid Build Coastguard Worker
45*c9945492SAndroid Build Coastguard Worker /* Compute maximal suffix */
46*c9945492SAndroid Build Coastguard Worker ip = -1; jp = 0; k = p = 1;
47*c9945492SAndroid Build Coastguard Worker while (jp+k<l) {
48*c9945492SAndroid Build Coastguard Worker if (n[ip+k] == n[jp+k]) {
49*c9945492SAndroid Build Coastguard Worker if (k == p) {
50*c9945492SAndroid Build Coastguard Worker jp += p;
51*c9945492SAndroid Build Coastguard Worker k = 1;
52*c9945492SAndroid Build Coastguard Worker } else k++;
53*c9945492SAndroid Build Coastguard Worker } else if (n[ip+k] > n[jp+k]) {
54*c9945492SAndroid Build Coastguard Worker jp += k;
55*c9945492SAndroid Build Coastguard Worker k = 1;
56*c9945492SAndroid Build Coastguard Worker p = jp - ip;
57*c9945492SAndroid Build Coastguard Worker } else {
58*c9945492SAndroid Build Coastguard Worker ip = jp++;
59*c9945492SAndroid Build Coastguard Worker k = p = 1;
60*c9945492SAndroid Build Coastguard Worker }
61*c9945492SAndroid Build Coastguard Worker }
62*c9945492SAndroid Build Coastguard Worker ms = ip;
63*c9945492SAndroid Build Coastguard Worker p0 = p;
64*c9945492SAndroid Build Coastguard Worker
65*c9945492SAndroid Build Coastguard Worker /* And with the opposite comparison */
66*c9945492SAndroid Build Coastguard Worker ip = -1; jp = 0; k = p = 1;
67*c9945492SAndroid Build Coastguard Worker while (jp+k<l) {
68*c9945492SAndroid Build Coastguard Worker if (n[ip+k] == n[jp+k]) {
69*c9945492SAndroid Build Coastguard Worker if (k == p) {
70*c9945492SAndroid Build Coastguard Worker jp += p;
71*c9945492SAndroid Build Coastguard Worker k = 1;
72*c9945492SAndroid Build Coastguard Worker } else k++;
73*c9945492SAndroid Build Coastguard Worker } else if (n[ip+k] < n[jp+k]) {
74*c9945492SAndroid Build Coastguard Worker jp += k;
75*c9945492SAndroid Build Coastguard Worker k = 1;
76*c9945492SAndroid Build Coastguard Worker p = jp - ip;
77*c9945492SAndroid Build Coastguard Worker } else {
78*c9945492SAndroid Build Coastguard Worker ip = jp++;
79*c9945492SAndroid Build Coastguard Worker k = p = 1;
80*c9945492SAndroid Build Coastguard Worker }
81*c9945492SAndroid Build Coastguard Worker }
82*c9945492SAndroid Build Coastguard Worker if (ip+1 > ms+1) ms = ip;
83*c9945492SAndroid Build Coastguard Worker else p = p0;
84*c9945492SAndroid Build Coastguard Worker
85*c9945492SAndroid Build Coastguard Worker /* Periodic needle? */
86*c9945492SAndroid Build Coastguard Worker if (memcmp(n, n+p, ms+1)) {
87*c9945492SAndroid Build Coastguard Worker mem0 = 0;
88*c9945492SAndroid Build Coastguard Worker p = MAX(ms, l-ms-1) + 1;
89*c9945492SAndroid Build Coastguard Worker } else mem0 = l-p;
90*c9945492SAndroid Build Coastguard Worker mem = 0;
91*c9945492SAndroid Build Coastguard Worker
92*c9945492SAndroid Build Coastguard Worker /* Initialize incremental end-of-haystack pointer */
93*c9945492SAndroid Build Coastguard Worker z = h;
94*c9945492SAndroid Build Coastguard Worker
95*c9945492SAndroid Build Coastguard Worker /* Search loop */
96*c9945492SAndroid Build Coastguard Worker for (;;) {
97*c9945492SAndroid Build Coastguard Worker /* Update incremental end-of-haystack pointer */
98*c9945492SAndroid Build Coastguard Worker if (z-h < l) {
99*c9945492SAndroid Build Coastguard Worker /* Fast estimate for MAX(l,63) */
100*c9945492SAndroid Build Coastguard Worker size_t grow = l | 63;
101*c9945492SAndroid Build Coastguard Worker const unsigned char *z2 = memchr(z, 0, grow);
102*c9945492SAndroid Build Coastguard Worker if (z2) {
103*c9945492SAndroid Build Coastguard Worker z = z2;
104*c9945492SAndroid Build Coastguard Worker if (z-h < l) return 0;
105*c9945492SAndroid Build Coastguard Worker } else z += grow;
106*c9945492SAndroid Build Coastguard Worker }
107*c9945492SAndroid Build Coastguard Worker
108*c9945492SAndroid Build Coastguard Worker /* Check last byte first; advance by shift on mismatch */
109*c9945492SAndroid Build Coastguard Worker if (BITOP(byteset, h[l-1], &)) {
110*c9945492SAndroid Build Coastguard Worker k = l-shift[h[l-1]];
111*c9945492SAndroid Build Coastguard Worker if (k) {
112*c9945492SAndroid Build Coastguard Worker if (k < mem) k = mem;
113*c9945492SAndroid Build Coastguard Worker h += k;
114*c9945492SAndroid Build Coastguard Worker mem = 0;
115*c9945492SAndroid Build Coastguard Worker continue;
116*c9945492SAndroid Build Coastguard Worker }
117*c9945492SAndroid Build Coastguard Worker } else {
118*c9945492SAndroid Build Coastguard Worker h += l;
119*c9945492SAndroid Build Coastguard Worker mem = 0;
120*c9945492SAndroid Build Coastguard Worker continue;
121*c9945492SAndroid Build Coastguard Worker }
122*c9945492SAndroid Build Coastguard Worker
123*c9945492SAndroid Build Coastguard Worker /* Compare right half */
124*c9945492SAndroid Build Coastguard Worker for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
125*c9945492SAndroid Build Coastguard Worker if (n[k]) {
126*c9945492SAndroid Build Coastguard Worker h += k-ms;
127*c9945492SAndroid Build Coastguard Worker mem = 0;
128*c9945492SAndroid Build Coastguard Worker continue;
129*c9945492SAndroid Build Coastguard Worker }
130*c9945492SAndroid Build Coastguard Worker /* Compare left half */
131*c9945492SAndroid Build Coastguard Worker for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
132*c9945492SAndroid Build Coastguard Worker if (k <= mem) return (char *)h;
133*c9945492SAndroid Build Coastguard Worker h += p;
134*c9945492SAndroid Build Coastguard Worker mem = mem0;
135*c9945492SAndroid Build Coastguard Worker }
136*c9945492SAndroid Build Coastguard Worker }
137*c9945492SAndroid Build Coastguard Worker
strstr(const char * h,const char * n)138*c9945492SAndroid Build Coastguard Worker char *strstr(const char *h, const char *n)
139*c9945492SAndroid Build Coastguard Worker {
140*c9945492SAndroid Build Coastguard Worker /* Return immediately on empty needle */
141*c9945492SAndroid Build Coastguard Worker if (!n[0]) return (char *)h;
142*c9945492SAndroid Build Coastguard Worker
143*c9945492SAndroid Build Coastguard Worker /* Use faster algorithms for short needles */
144*c9945492SAndroid Build Coastguard Worker h = strchr(h, *n);
145*c9945492SAndroid Build Coastguard Worker if (!h || !n[1]) return (char *)h;
146*c9945492SAndroid Build Coastguard Worker if (!h[1]) return 0;
147*c9945492SAndroid Build Coastguard Worker if (!n[2]) return twobyte_strstr((void *)h, (void *)n);
148*c9945492SAndroid Build Coastguard Worker if (!h[2]) return 0;
149*c9945492SAndroid Build Coastguard Worker if (!n[3]) return threebyte_strstr((void *)h, (void *)n);
150*c9945492SAndroid Build Coastguard Worker if (!h[3]) return 0;
151*c9945492SAndroid Build Coastguard Worker if (!n[4]) return fourbyte_strstr((void *)h, (void *)n);
152*c9945492SAndroid Build Coastguard Worker
153*c9945492SAndroid Build Coastguard Worker return twoway_strstr((void *)h, (void *)n);
154*c9945492SAndroid Build Coastguard Worker }
155