summaryrefslogtreecommitdiff
path: root/lib/libc/string
diff options
context:
space:
mode:
authordsl <dsl@NetBSD.org>2009-07-30 21:42:06 +0000
committerdsl <dsl@NetBSD.org>2009-07-30 21:42:06 +0000
commit027bacee22b48e8d5dca129724040a55ac19cd48 (patch)
treeceff5a8e27d735d404cf8e1631669d20da411645 /lib/libc/string
parentf0a25cf095fc0c68627223c9df05168734861f47 (diff)
Use a 'register only' str[c]spn() on 64 bit systems.
Diffstat (limited to 'lib/libc/string')
-rw-r--r--lib/libc/string/strcspn.c10
-rw-r--r--lib/libc/string/strspn.c89
2 files changed, 95 insertions, 4 deletions
diff --git a/lib/libc/string/strcspn.c b/lib/libc/string/strcspn.c
index d5cce2ccda3..cc40093c113 100644
--- a/lib/libc/string/strcspn.c
+++ b/lib/libc/string/strcspn.c
@@ -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 @@ strcspn(const char *s, const char *charset)
break;
return t - s;
}
+
+#endif
diff --git a/lib/libc/string/strspn.c b/lib/libc/string/strspn.c
index 2d6ca16afba..9526cde8bfc 100644
--- a/lib/libc/string/strspn.c
+++ b/lib/libc/string/strspn.c
@@ -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 @@ strspn(const char *s, const char *charset)
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