libkern - Add memcchr(9).
authorAntonio Huete Jimenez <tuxillo@quantumachine.net>
Sun, 8 Jul 2012 12:37:50 +0000 (14:37 +0200)
committerAntonio Huete Jimenez <tuxillo@quantumachine.net>
Sun, 8 Jul 2012 12:37:50 +0000 (14:37 +0200)
* It can be used for filesystem bitmap operations.
* FreeBSD introduced it to replace calls to skpc().
* It does compare entire words instead of single bytes.

Taken from: FreeBSD-SVN 229198

share/man/man9/Makefile
share/man/man9/memcchr.9 [new file with mode: 0644]
sys/conf/files
sys/libkern/memcchr.c [new file with mode: 0644]
sys/sys/libkern.h

index a795c07..c2baead 100644 (file)
@@ -115,6 +115,7 @@ MAN=        accept_filter.9 \
        make_dev.9 \
        mbuf.9 \
        MD5.9 \
+       memcchr.9 \
        memory.9 \
        microseq.9 \
        microtime.9 \
diff --git a/share/man/man9/memcchr.9 b/share/man/man9/memcchr.9
new file mode 100644 (file)
index 0000000..840f563
--- /dev/null
@@ -0,0 +1,59 @@
+.\" Copyright (c) 2012 Ed Schouten <ed@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/share/man/man9/memcchr.9,v 1.1 2012/01/01 20:59:42 ed Exp $
+.\"
+.Dd January 1, 2012
+.Dt MEMCCHR 9
+.Os
+.Sh NAME
+.Nm memcchr
+.Nd locate the complement of a byte in byte string
+.Sh SYNOPSIS
+.In sys/libkern.h
+.Ft void *
+.Fn memcchr "const void *b" "int c" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn memcchr
+function locates the first occurrence of a byte unequal to
+.Fa c
+(converted to an
+.Vt "unsigned char" )
+in string
+.Fa b .
+.Sh RETURN VALUES
+The
+.Fn memcchr
+function returns a pointer to the byte located, or NULL if no such byte
+exists within
+.Fa len
+bytes.
+.Sh SEE ALSO
+.Xr memchr 3
+.Sh HISTORY
+The
+.Fn memcchr
+function first appeared in
+.Fx 10.0 .
index 2ac11dc..d351b85 100644 (file)
@@ -1822,6 +1822,7 @@ libkern/index.c                           standard
 libkern/inet_ntoa.c                    standard
 libkern/mcount.c                       optional        profiling-routine
 libkern/memmove.c                      standard
+libkern/memcchr.c                      standard
 libkern/qsort.c                                standard
 libkern/random.c                       standard
 libkern/rindex.c                       standard
diff --git a/sys/libkern/memcchr.c b/sys/libkern/memcchr.c
new file mode 100644 (file)
index 0000000..f4d2425
--- /dev/null
@@ -0,0 +1,117 @@
+/*-
+ * Copyright (c) 2012 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/libkern/memcchr.c,v 1.1 2012/01/01 20:26:11 ed Exp $
+ *
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/libkern.h>
+#include <sys/limits.h>
+#include <sys/param.h>
+
+/*
+ * memcchr(): find first character in buffer not matching `c'.
+ *
+ * This function performs the complement of memchr().  To provide decent
+ * performance, this function compares data from the buffer one word at
+ * a time.
+ *
+ * This code is inspired by libc's strlen(), written by Xin Li.
+ */
+
+#if LONG_BIT != 32 && LONG_BIT != 64
+#error Unsupported word size
+#endif
+
+#define        LONGPTR_MASK (sizeof(long) - 1)
+
+#define        TESTBYTE                                \
+       do {                                    \
+               if (*p != (unsigned char)c)     \
+                       goto done;              \
+               p++;                            \
+       } while (0)
+
+void *
+memcchr(const void *begin, int c, size_t n)
+{
+       const unsigned long *lp;
+       const unsigned char *p, *end;
+       unsigned long word;
+
+       /* Four or eight repetitions of `c'. */
+       word = (unsigned char)c;
+       word |= word << 8;
+       word |= word << 16;
+#if LONG_BIT >= 64
+       word |= word << 32;
+#endif
+
+       /* Don't perform memory I/O when passing a zero-length buffer. */
+       if (n == 0)
+               return (NULL);
+
+       /*
+        * First determine whether there is a character unequal to `c'
+        * in the first word.  As this word may contain bytes before
+        * `begin', we may execute this loop spuriously.
+        */
+       lp = (const unsigned long *)((uintptr_t)begin & ~LONGPTR_MASK);
+       end = (const unsigned char *)begin + n;
+       if (*lp++ != word)
+               for (p = begin; p < (const unsigned char *)lp;)
+                       TESTBYTE;
+
+       /* Now compare the data one word at a time. */
+       for (; (const unsigned char *)lp < end; lp++) {
+               if (*lp != word) {
+                       p = (const unsigned char *)lp;
+                       TESTBYTE;
+                       TESTBYTE;
+                       TESTBYTE;
+#if LONG_BIT >= 64
+                       TESTBYTE;
+                       TESTBYTE;
+                       TESTBYTE;
+                       TESTBYTE;
+#endif
+                       goto done;
+               }
+       }
+
+       return (NULL);
+
+done:
+       /*
+        * If the end of the buffer is not word aligned, the previous
+        * loops may obtain an address that's beyond the end of the
+        * buffer.
+        */
+       if (p < end)
+               return (__DECONST(void *, p));
+       return (NULL);
+}
index ccd1a58..a44d0f2 100644 (file)
@@ -124,6 +124,7 @@ int  strncasecmp (const char *, const char *, size_t);
 char   *strncpy (char * __restrict, const char * __restrict, size_t);
 char   *strsep(char **, const char *);
 int    _kfnmatch(const char *, const char *, int, int);
+void * memcchr(const void *, int, size_t);
 
 /*
  * memset can't be an inline, it is used by gcc-4.x directly.