Quellcode durchsuchen

optimize strchrnul/strcspn not to scan string twice on no-match

when strchr fails, and important piece of information already
computed, the string length, is thrown away. have strchrnul (with
namespace protection) be the underlying function so this information
can be kept, and let strchr be a wrapper for it. this also allows
strcspn to be considerably faster in the case where the match set has
a single element that's not matched.
Rich Felker vor 12 Jahren
Ursprung
Commit
68dbd05039
3 geänderte Dateien mit 29 neuen und 25 gelöschten Zeilen
  1. 3 20
      src/string/strchr.c
  2. 23 3
      src/string/strchrnul.c
  3. 3 2
      src/string/strcspn.c

+ 3 - 20
src/string/strchr.c

@@ -1,26 +1,9 @@
 #include <string.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <limits.h>
 
-#define ALIGN (sizeof(size_t)-1)
-#define ONES ((size_t)-1/UCHAR_MAX)
-#define HIGHS (ONES * (UCHAR_MAX/2+1))
-#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+char *__strchrnul(const char *, int);
 
 char *strchr(const char *s, int c)
 {
-	size_t *w, k;
-
-	c = (unsigned char)c;
-	if (!c) return (char *)s + strlen(s);
-
-	for (; ((uintptr_t)s & ALIGN); s++)
-		if (*(unsigned char *)s == c) return (char *)s;
-		else if (!*s) return 0;
-	k = ONES * c;
-	for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++);
-	for (s = (void *)w; *s; s++)
-		if (*(unsigned char *)s == c) return (char *)s;
-	return 0;
+	char *r = __strchrnul(s, c);
+	return *(unsigned char *)r == (unsigned char)c ? r : 0;
 }

+ 23 - 3
src/string/strchrnul.c

@@ -1,7 +1,27 @@
 #include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include "libc.h"
 
-char *strchrnul(const char *s, int c)
+#define ALIGN (sizeof(size_t))
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+char *__strchrnul(const char *s, int c)
 {
-	char *p = strchr(s, c);
-	return p ? p : (char *)s + strlen(s);
+	size_t *w, k;
+
+	c = (unsigned char)c;
+	if (!c) return (char *)s + strlen(s);
+
+	for (; (uintptr_t)s % ALIGN; s++)
+		if (!*s || *(unsigned char *)s == c) return (char *)s;
+	k = ONES * c;
+	for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++);
+	for (s = (void *)w; *s && *(unsigned char *)s != c; s++);
+	return (char *)s;
 }
+
+weak_alias(__strchrnul, strchrnul);

+ 3 - 2
src/string/strcspn.c

@@ -3,13 +3,14 @@
 #define BITOP(a,b,op) \
  ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
 
+char *__strchrnul(const char *, int);
+
 size_t strcspn(const char *s, const char *c)
 {
 	const char *a = s;
 	size_t byteset[32/sizeof(size_t)];
 
-	if (!c[0]) return strlen(s);
-	if (!c[1]) return (s=strchr(s, *c)) ? s-a : strlen(a);
+	if (!c[0] || !c[1]) return __strchrnul(s, *c)-a;
 
 	memset(byteset, 0, sizeof byteset);
 	for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);