1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-28 00:21:52 +03:00

Detect EOL on-the-fly in strstr, strcasestr and memmem.

This commit is contained in:
Maxim Kuvyrkov
2012-05-28 22:50:15 -07:00
parent 20a71f2c8a
commit 400726deef
7 changed files with 108 additions and 15 deletions

View File

@ -75,6 +75,16 @@
# define CMP_FUNC memcmp
#endif
#ifndef AVAILABLE1
# define AVAILABLE1(h, h_l, j, n_l) AVAILABLE (h, h_l, j, n_l)
#endif
#ifndef AVAILABLE2
# define AVAILABLE2(h, h_l, j, n_l) (1)
#endif
#ifndef RET0_IF_0
# define RET0_IF_0(a) /* nothing */
#endif
/* Perform a critical factorization of NEEDLE, of length NEEDLE_LEN.
Return the index of the first byte in the right half, and set
*PERIOD to the global period of the right half.
@ -266,37 +276,58 @@ two_way_short_needle (const unsigned char *haystack, size_t haystack_len,
required, and any mismatch results in a maximal shift. */
period = MAX (suffix, needle_len - suffix) + 1;
j = 0;
while (AVAILABLE (haystack, haystack_len, j, needle_len))
while (AVAILABLE1 (haystack, haystack_len, j, needle_len))
{
unsigned char haystack_char;
/* TODO: The first-character loop can be sped up by adapting
longword-at-a-time implementation of memchr/strchr. */
if (needle_suffix
!= CANON_ELEMENT (haystack[suffix + j]))
!= (haystack_char = CANON_ELEMENT (haystack[suffix + j])))
{
RET0_IF_0 (haystack_char);
++j;
continue;
}
/* Scan for matches in right half. */
i = suffix + 1;
while (i < needle_len && (CANON_ELEMENT (needle[i])
== CANON_ELEMENT (haystack[i + j])))
++i;
while (i < needle_len)
{
if (CANON_ELEMENT (needle[i])
!= (haystack_char = CANON_ELEMENT (haystack[i + j])))
{
RET0_IF_0 (haystack_char);
break;
}
++i;
}
if (needle_len <= i)
{
/* Scan for matches in left half. */
i = suffix - 1;
while (i != SIZE_MAX && (CANON_ELEMENT (needle[i])
== CANON_ELEMENT (haystack[i + j])))
--i;
while (i != SIZE_MAX)
{
if (CANON_ELEMENT (needle[i])
!= (haystack_char = CANON_ELEMENT (haystack[i + j])))
{
RET0_IF_0 (haystack_char);
break;
}
--i;
}
if (i == SIZE_MAX)
return (RETURN_TYPE) (haystack + j);
j += period;
}
else
j += i - suffix + 1;
if (!AVAILABLE2 (haystack, haystack_len, j, needle_len))
break;
}
}
ret0: __attribute__ ((unused))
return NULL;
}
@ -433,6 +464,9 @@ two_way_long_needle (const unsigned char *haystack, size_t haystack_len,
}
#undef AVAILABLE
#undef AVAILABLE1
#undef AVAILABLE2
#undef CANON_ELEMENT
#undef CMP_FUNC
#undef RET0_IF_0
#undef RETURN_TYPE