about summary refs log tree commit diff
path: root/string/strpbrk.c
diff options
context:
space:
mode:
Diffstat (limited to 'string/strpbrk.c')
-rw-r--r--string/strpbrk.c120
1 files changed, 109 insertions, 11 deletions
diff --git a/string/strpbrk.c b/string/strpbrk.c
index 4f1d9b72bb..01cd55afdf 100644
--- a/string/strpbrk.c
+++ b/string/strpbrk.c
@@ -16,26 +16,124 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <string.h>
-
+#include <stdint.h>
 #undef strpbrk
+#undef strcspn
+
+
+#ifdef AS_STRCSPN
+# ifndef STRPBRK
+#  define STRPBRK strcspn
+# endif
+# define RETURN_TYPE size_t
+# define RETURN(c) return c
+#else
+# define RETURN_TYPE char *
+# define RETURN(c) return (char *) (s[c] != '\0' ? s + c : NULL)
+#endif
 
 #ifndef STRPBRK
 #define STRPBRK strpbrk
 #endif
 
+
 /* Find the first occurrence in S of any character in ACCEPT.  */
-char *
-STRPBRK (const char *s, const char *accept)
+RETURN_TYPE
+STRPBRK (const char *_s, const char *_accept)
 {
-  while (*s != '\0')
+  unsigned char *s = (unsigned char *) _s;
+  unsigned char *a = (unsigned char *) _accept;
+
+#ifndef LATE_CHECK
+  /* We need to align s to 4 bytes. We do check now to avoid expensive table
+     construction.  */
+  do
+    {
+      if (s[0] == *a)
+        RETURN(0);
+    }
+  while (*a++);
+  a = (unsigned char *) _accept;
+
+  /* We couldn't do these checks in one loop as gcc
+     messes up register allocation.  */
+  do
+    {
+      if (s[1] == *a)
+        RETURN(1);
+    }
+  while (*a++);
+  a = (unsigned char *) _accept;
+
+  do
+    {
+      if (s[2] == *a)
+        RETURN(2);
+    }
+  while (*a++);
+  a = (unsigned char *) _accept;
+
+  do
+    {
+      if (s[3] == *a)
+        RETURN(3);
+    }
+  while (*a++);
+  a = (unsigned char *) _accept;
+
+#endif
+
+  unsigned char table[256];
+  memset (table, 0, 256);
+  do
     {
-      const char *a = accept;
-      while (*a != '\0')
-	if (*a++ == *s)
-	  return (char *) s;
-      ++s;
+      table[*a] = 1;
     }
+  while (*a++);
+  unsigned char s0, s1, s2, s3;
+  size_t count = 0;
+#ifdef LATE_CHECK
+  s0 = s[count + 0];
+  s1 = s[count + 1];
+  s2 = s[count + 2];
+  s3 = s[count + 3];
+  if (table[s0])
+    goto ret0;
+  if (table[s1])
+    goto ret1;
+  if (table[s2])
+    goto ret2;
+  if (table[s3])
+    goto ret3;
 
-  return NULL;
+#endif
+
+  count = 4 - ((uintptr_t) s) % 4;
+
+  while (1)
+    {
+      s0 = s[count + 0];
+      s1 = s[count + 1];
+      s2 = s[count + 2];
+      s3 = s[count + 3];
+      if (table[s0])
+        goto ret0;
+      if (table[s1])
+        goto ret1;
+      if (table[s2])
+        goto ret2;
+      if (table[s3])
+        goto ret3;
+      count += 4;
+    }
+  ret3:
+  count++;
+  ret2:
+  count++;
+  ret1:
+  count++;
+  ret0:
+  RETURN(count);
 }
-libc_hidden_builtin_def (strpbrk)
+
+libc_hidden_builtin_def (STRPBRK)