Module Name:    src
Committed By:   dsl
Date:           Thu Jul 30 21:42:06 UTC 2009

Modified Files:
        src/lib/libc/string: strcspn.c strspn.c

Log Message:
Use a 'register only' str[c]spn() on 64 bit systems.


To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/lib/libc/string/strcspn.c \
    src/lib/libc/string/strspn.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libc/string/strcspn.c
diff -u src/lib/libc/string/strcspn.c:1.16 src/lib/libc/string/strcspn.c:1.17
--- src/lib/libc/string/strcspn.c:1.16	Wed Jul 30 16:13:59 2008
+++ src/lib/libc/string/strcspn.c	Thu Jul 30 21:42:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: strcspn.c,v 1.16 2008/07/30 16:13:59 joerg Exp $	*/
+/*	$NetBSD: strcspn.c,v 1.17 2009/07/30 21:42:06 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2008 Joerg Sonnenberger
@@ -26,12 +26,16 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: strcspn.c,v 1.16 2008/07/30 16:13:59 joerg Exp $");
+__RCSID("$NetBSD: strcspn.c,v 1.17 2009/07/30 21:42:06 dsl Exp $");
 
 #include <assert.h>
 #include <inttypes.h>
+#include <limits.h>
 #include <string.h>
 
+/* 64bit version is in strspn.c */
+#if ULONG_MAX != 0xffffffffffffffffull
+
 size_t
 strcspn(const char *s, const char *charset)
 {
@@ -62,3 +66,5 @@
 			break;
 	return t - s;
 }
+
+#endif
Index: src/lib/libc/string/strspn.c
diff -u src/lib/libc/string/strspn.c:1.16 src/lib/libc/string/strspn.c:1.17
--- src/lib/libc/string/strspn.c:1.16	Wed Jul 30 16:13:59 2008
+++ src/lib/libc/string/strspn.c	Thu Jul 30 21:42:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: strspn.c,v 1.16 2008/07/30 16:13:59 joerg Exp $	*/
+/*	$NetBSD: strspn.c,v 1.17 2009/07/30 21:42:06 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2008 Joerg Sonnenberger
@@ -26,13 +26,15 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: strspn.c,v 1.16 2008/07/30 16:13:59 joerg Exp $");
+__RCSID("$NetBSD: strspn.c,v 1.17 2009/07/30 21:42:06 dsl Exp $");
 
 #include <assert.h>
 #include <inttypes.h>
 #include <limits.h>
 #include <string.h>
 
+#if ULONG_MAX != 0xffffffffffffffffull
+
 size_t
 strspn(const char *s, const char *charset)
 {
@@ -64,3 +66,86 @@
 			break;
 	return t - s;
 }
+
+#else
+
+/* 64 bit system, use four 64 bits registers for bitmask */
+
+static size_t
+strspn_x(const char *s_s, const char *charset_s, unsigned long invert)
+{
+	const unsigned char *s = (const unsigned char *)s_s;
+	const unsigned char *charset = (const unsigned char *)charset_s;
+	unsigned long m_0, m_4, m_8, m_c;
+	unsigned char ch, next_ch;
+	unsigned long bit;
+	unsigned long check;
+	size_t count;
+
+	/* Four 64bit registers have one bit for each character value */
+	m_0 = 0;
+	m_4 = 0;
+	m_8 = 0;
+	m_c = 0;
+
+	for (ch = *charset; ch != 0; ch = next_ch) {
+		next_ch = *++charset;
+		bit = 1ul << (ch & 0x3f);
+		if (__predict_true(ch < 0x80)) {
+			if (ch < 0x40)
+				m_0 |= bit;
+			else
+				m_4 |= bit;
+		} else {
+			if (ch < 0xc0)
+				m_8 |= bit;
+			else
+				m_c |= bit;
+		}
+	}
+
+	/* For strcspn() we just invert the validity set */
+	m_0 ^= invert;
+	m_4 ^= invert;
+	m_8 ^= invert;
+	m_c ^= invert;
+
+	/*
+	 * We could do remove the lsb from m_0 to terminate at the
+	 * end of the input string.
+	 * However prefetching the next char is benifitial and we must
+	 * not read the byte after the \0 - as it might fault!
+	 * So we take the 'hit' of the compare against 0.
+	 */
+
+	ch = *s++;
+	for (count = 0; ch != 0; ch = next_ch) {
+		next_ch = s[count];
+		if (__predict_true(ch < 0x80)) {
+			check = m_0;
+			if (ch >= 0x40)
+				check = m_4;
+		} else {
+			check = m_8;
+			if (ch >= 0xc0)
+				check = m_c;
+		}
+		if (!((check >> (ch & 0x3f)) & 1))
+			break;
+		count++;
+	}
+	return count;
+}
+
+size_t
+strspn(const char *s, const char *charset)
+{
+	return strspn_x(s, charset, 0);
+}
+
+size_t
+strcspn(const char *s, const char *charset)
+{
+	return strspn_x(s, charset, ~0ul);
+}
+#endif

Reply via email to