summaryrefslogtreecommitdiff
path: root/sysdeps/generic/strstr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/generic/strstr.c')
-rw-r--r--sysdeps/generic/strstr.c119
1 files changed, 90 insertions, 29 deletions
diff --git a/sysdeps/generic/strstr.c b/sysdeps/generic/strstr.c
index 06681de931..9c0e8183b5 100644
--- a/sysdeps/generic/strstr.c
+++ b/sysdeps/generic/strstr.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1994 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -16,41 +16,102 @@ License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
-#include <ansidecl.h>
-#include <stddef.h>
+/*
+ * My personal strstr() implementation that beats most other algorithms.
+ * Until someone tells me otherwise, I assume that this is the
+ * fastest implementation of strstr() in C.
+ * I deliberately chose not to comment it. You should have at least
+ * as much fun trying to understand it, as I had to write it :-).
+ *
+ * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
+
#include <string.h>
+#include <sys/types.h>
+
+typedef unsigned chartype;
-/* Return the first ocurrence of NEEDLE in HAYSTACK. */
char *
-DEFUN(strstr, (haystack, needle),
- CONST char *CONST haystack AND
- CONST char *CONST needle)
+strstr (phaystack, pneedle)
+ const char *phaystack;
+ const char *pneedle;
{
- register CONST char *CONST needle_end = strchr(needle, '\0');
- register CONST char *CONST haystack_end = strchr(haystack, '\0');
- register CONST size_t needle_len = needle_end - needle;
- register CONST size_t needle_last = needle_len - 1;
- register CONST char *begin;
-
- if (needle_len == 0)
- return (char *) haystack; /* ANSI 4.11.5.7, line 25. */
- if ((size_t) (haystack_end - haystack) < needle_len)
- return NULL;
-
- for (begin = &haystack[needle_last]; begin < haystack_end; ++begin)
- {
- register CONST char *n = &needle[needle_last];
- register CONST char *h = begin;
+ register const unsigned char *haystack, *needle;
+ register chartype b, c;
+
+ haystack = (const unsigned char *) phaystack;
+ needle = (const unsigned char *) pneedle;
+ b = *needle;
+ if (b != '\0')
+ {
+ haystack--; /* possible ANSI violation */
do
- if (*h != *n)
- goto loop; /* continue for loop */
- while (--n >= needle && --h >= haystack);
+ {
+ c = *++haystack;
+ if (c == '\0')
+ goto ret0;
+ }
+ while (c != b);
- return (char *) h;
+ c = *++needle;
+ if (c == '\0')
+ goto foundneedle;
+ ++needle;
+ goto jin;
- loop:;
- }
+ for (;;)
+ {
+ register chartype a;
+ register const unsigned char *rhaystack, *rneedle;
+
+ do
+ {
+ a = *++haystack;
+ if (a == '\0')
+ goto ret0;
+ if (a == b)
+ break;
+ a = *++haystack;
+ if (a == '\0')
+ goto ret0;
+shloop: }
+ while (a != b);
- return NULL;
+jin: a = *++haystack;
+ if (a == '\0')
+ goto ret0;
+
+ if (a != c)
+ goto shloop;
+
+ rhaystack = haystack-- + 1;
+ rneedle = needle;
+ a = *rneedle;
+
+ if (*rhaystack == a)
+ do
+ {
+ if (a == '\0')
+ goto foundneedle;
+ ++rhaystack;
+ a = *++needle;
+ if (*rhaystack != a)
+ break;
+ if (a == '\0')
+ goto foundneedle;
+ ++rhaystack;
+ a = *++needle;
+ }
+ while (*rhaystack == a);
+
+ needle = rneedle; /* took the register-poor aproach */
+
+ if (a == '\0')
+ break;
+ }
+ }
+foundneedle:
+ return (char*) haystack;
+ret0:
+ return 0;
}