summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--benchtests/bench-strtok.c34
-rw-r--r--string/bits/string2.h39
-rw-r--r--string/string-inlines.c30
-rw-r--r--string/strtok.c38
-rw-r--r--string/strtok_r.c31
6 files changed, 88 insertions, 92 deletions
diff --git a/ChangeLog b/ChangeLog
index e9f41247b6..f7128edc44 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2015-12-14  Wilco Dijkstra  <wdijkstr@arm.com>
+
+	* benchtests/bench-strtok.c (oldstrtok): Add old implementation.
+	* string/strtok.c (strtok): Change to tailcall __strtok_r.
+	* string/strtok_r.c (__strtok_r): Optimize for performance.
+	* string/string-inlines.c (__old_strtok_r_1c): New function.
+	* string/bits/string2.h (__strtok_r): Move to string-inlines.c.
+
 2016-12-14  Gabriel F. T. Gomes  <gftg@linux.vnet.ibm.com>
 
 	* math/Makefile (gen-libm-calls): Add w_log1pF.
diff --git a/benchtests/bench-strtok.c b/benchtests/bench-strtok.c
index eeb798f015..41e0e45db8 100644
--- a/benchtests/bench-strtok.c
+++ b/benchtests/bench-strtok.c
@@ -20,13 +20,41 @@
 #define TEST_NAME "strtok"
 #include "bench-string.h"
 
-#define STRTOK strtok_string
-#include <string/strtok.c>
+char *
+oldstrtok (char *s, const char *delim)
+{
+  static char *olds;
+  char *token;
+
+  if (s == NULL)
+    s = olds;
+
+  /* Scan leading delimiters.  */
+  s += strspn (s, delim);
+  if (*s == '\0')
+    {
+      olds = s;
+      return NULL;
+    }
 
+  /* Find the end of the token.  */
+  token = s;
+  s = strpbrk (token, delim);
+  if (s == NULL)
+    /* This token finishes the string.  */
+    olds = __rawmemchr (token, '\0');
+  else
+    {
+      /* Terminate the token and make OLDS point past it.  */
+      *s = '\0';
+      olds = s + 1;
+    }
+  return token;
+}
 
 typedef char *(*proto_t) (const char *, const char *);
 
-IMPL (strtok_string, 0)
+IMPL (oldstrtok, 0)
 IMPL (strtok, 1)
 
 static void
diff --git a/string/bits/string2.h b/string/bits/string2.h
index ca1eda9bd1..e39d4f1a85 100644
--- a/string/bits/string2.h
+++ b/string/bits/string2.h
@@ -180,45 +180,6 @@ extern void *__rawmemchr (const void *__s, int __c);
 #endif
 
 
-#if !defined _HAVE_STRING_ARCH_strtok_r || defined _FORCE_INLINES
-# ifndef _HAVE_STRING_ARCH_strtok_r
-#  define __strtok_r(s, sep, nextp) \
-  (__extension__ (__builtin_constant_p (sep) && __string2_1bptr_p (sep)	      \
-		  && ((const char *) (sep))[0] != '\0'			      \
-		  && ((const char *) (sep))[1] == '\0'			      \
-		  ? __strtok_r_1c (s, ((const char *) (sep))[0], nextp)       \
-		  : __strtok_r (s, sep, nextp)))
-# endif
-
-__STRING_INLINE char *__strtok_r_1c (char *__s, char __sep, char **__nextp);
-__STRING_INLINE char *
-__strtok_r_1c (char *__s, char __sep, char **__nextp)
-{
-  char *__result;
-  if (__s == NULL)
-    __s = *__nextp;
-  while (*__s == __sep)
-    ++__s;
-  __result = NULL;
-  if (*__s != '\0')
-    {
-      __result = __s++;
-      while (*__s != '\0')
-	if (*__s++ == __sep)
-	  {
-	    __s[-1] = '\0';
-	    break;
-	  }
-    }
-  *__nextp = __s;
-  return __result;
-}
-# ifdef __USE_POSIX
-#  define strtok_r(s, sep, nextp) __strtok_r (s, sep, nextp)
-# endif
-#endif
-
-
 #if !defined _HAVE_STRING_ARCH_strsep || defined _FORCE_INLINES
 # ifndef _HAVE_STRING_ARCH_strsep
 
diff --git a/string/string-inlines.c b/string/string-inlines.c
index 1091468519..d43e5897c3 100644
--- a/string/string-inlines.c
+++ b/string/string-inlines.c
@@ -35,6 +35,36 @@
 
 #include "shlib-compat.h"
 
+#if SHLIB_COMPAT (libc, GLIBC_2_1_1, GLIBC_2_25)
+/* The inline functions are not used from GLIBC 2.25 and forward, however
+   they are required to provide the symbols through string-inlines.c
+   (if inlining is not possible for compatibility reasons).  */
+
+char *
+__old_strtok_r_1c (char *__s, char __sep, char **__nextp)
+{
+  char *__result;
+  if (__s == NULL)
+    __s = *__nextp;
+  while (*__s == __sep)
+    ++__s;
+  __result = NULL;
+  if (*__s != '\0')
+    {
+      __result = __s++;
+      while (*__s != '\0')
+	if (*__s++ == __sep)
+	  {
+	    __s[-1] = '\0';
+	    break;
+	  }
+    }
+  *__nextp = __s;
+  return __result;
+}
+compat_symbol (libc, __old_strtok_r_1c, __strtok_r_1c, GLIBC_2_1_1);
+#endif
+
 #if SHLIB_COMPAT (libc, GLIBC_2_1_1, GLIBC_2_24)
 /* The inline functions are not used from GLIBC 2.24 and forward, however
    they are required to provide the symbols through string-inlines.c
diff --git a/string/strtok.c b/string/strtok.c
index 7a4574db5c..482cdc1da4 100644
--- a/string/strtok.c
+++ b/string/strtok.c
@@ -18,14 +18,6 @@
 #include <string.h>
 
 
-static char *olds;
-
-#undef strtok
-
-#ifndef STRTOK
-# define STRTOK strtok
-#endif
-
 /* Parse S into tokens separated by characters in DELIM.
    If S is NULL, the last string strtok() was called with is
    used.  For example:
@@ -36,32 +28,8 @@ static char *olds;
 		// s = "abc\0=-def\0"
 */
 char *
-STRTOK (char *s, const char *delim)
+strtok (char *s, const char *delim)
 {
-  char *token;
-
-  if (s == NULL)
-    s = olds;
-
-  /* Scan leading delimiters.  */
-  s += strspn (s, delim);
-  if (*s == '\0')
-    {
-      olds = s;
-      return NULL;
-    }
-
-  /* Find the end of the token.  */
-  token = s;
-  s = strpbrk (token, delim);
-  if (s == NULL)
-    /* This token finishes the string.  */
-    olds = __rawmemchr (token, '\0');
-  else
-    {
-      /* Terminate the token and make OLDS point past it.  */
-      *s = '\0';
-      olds = s + 1;
-    }
-  return token;
+  static char *olds;
+  return __strtok_r (s, delim, &olds);
 }
diff --git a/string/strtok_r.c b/string/strtok_r.c
index f351304766..2d251f90d7 100644
--- a/string/strtok_r.c
+++ b/string/strtok_r.c
@@ -22,14 +22,10 @@
 
 #include <string.h>
 
-#undef strtok_r
-#undef __strtok_r
-
 #ifndef _LIBC
 /* Get specification.  */
 # include "strtok_r.h"
 # define __strtok_r strtok_r
-# define __rawmemchr strchr
 #endif
 
 /* Parse S into tokens separated by characters in DELIM.
@@ -45,11 +41,17 @@
 char *
 __strtok_r (char *s, const char *delim, char **save_ptr)
 {
-  char *token;
+  char *end;
 
   if (s == NULL)
     s = *save_ptr;
 
+  if (*s == '\0')
+    {
+      *save_ptr = s;
+      return NULL;
+    }
+
   /* Scan leading delimiters.  */
   s += strspn (s, delim);
   if (*s == '\0')
@@ -59,18 +61,17 @@ __strtok_r (char *s, const char *delim, char **save_ptr)
     }
 
   /* Find the end of the token.  */
-  token = s;
-  s = strpbrk (token, delim);
-  if (s == NULL)
-    /* This token finishes the string.  */
-    *save_ptr = __rawmemchr (token, '\0');
-  else
+  end = s + strcspn (s, delim);
+  if (*end == '\0')
     {
-      /* Terminate the token and make *SAVE_PTR point past it.  */
-      *s = '\0';
-      *save_ptr = s + 1;
+      *save_ptr = end;
+      return s;
     }
-  return token;
+
+  /* Terminate the token and make *SAVE_PTR point past it.  */
+  *end = '\0';
+  *save_ptr = end + 1;
+  return s;
 }
 #ifdef weak_alias
 libc_hidden_def (__strtok_r)