As of now, everything except the code imported from FreeBSD is proprietary. Of course, it won't be like this for long, only until we have decided which license we like to use. The rationale is that releasing everything under a copyleft license later is always easier than doing so immediately and then changing it afterwards. Naturally, any changes made before this commit are still subject to the terms of the CNPL.
119 lines
3.7 KiB
C
119 lines
3.7 KiB
C
/* See the end of this file for copyright and license terms. */
|
|
|
|
#include <gay/types.h>
|
|
|
|
#include <limits.h>
|
|
#include <string.h>
|
|
|
|
/*
|
|
* Portable strlen() for 32-bit and 64-bit systems.
|
|
*
|
|
* The expression:
|
|
*
|
|
* ((x - 0x01....01) & ~x & 0x80....80)
|
|
*
|
|
* would evaluate to a non-zero value if any of the bytes in the
|
|
* original word is zero.
|
|
*
|
|
* The algorithm above is found on "Hacker's Delight" by
|
|
* Henry S. Warren, Jr.
|
|
*
|
|
* Note: this leaves performance on the table and each architecture
|
|
* would be best served with a tailor made routine instead, even if
|
|
* using the same trick.
|
|
*/
|
|
|
|
/* Magic numbers for the algorithm */
|
|
#if LONG_BIT == 32
|
|
static const unsigned long mask01 = 0x01010101;
|
|
static const unsigned long mask80 = 0x80808080;
|
|
#elif LONG_BIT == 64
|
|
static const unsigned long mask01 = 0x0101010101010101;
|
|
static const unsigned long mask80 = 0x8080808080808080;
|
|
#else
|
|
#error "Unsupported word size"
|
|
#endif
|
|
|
|
#define LONGPTR_MASK (sizeof(unsigned long) - 1)
|
|
|
|
usize strlen(const char *str)
|
|
{
|
|
const char *p;
|
|
const unsigned long *lp;
|
|
unsigned long va, vb;
|
|
|
|
/*
|
|
* Before trying the hard (unaligned byte-by-byte access) way
|
|
* to figure out whether there is a nul character, try to see
|
|
* if there is a nul character is within this accessible word
|
|
* first.
|
|
*
|
|
* p and (p & ~LONGPTR_MASK) must be equally accessible since
|
|
* they always fall in the same memory page, as long as page
|
|
* boundaries is integral multiple of word size.
|
|
*/
|
|
lp = (const unsigned long *)((uintptr_t)str & ~LONGPTR_MASK);
|
|
va = *lp - mask01;
|
|
vb = (~*lp) & mask80;
|
|
lp++;
|
|
if (va & vb) {
|
|
/* Check if we have \0 in the first part */
|
|
for (p = str; p < (const char *)lp; p++) {
|
|
if (*p == '\0')
|
|
return p - str;
|
|
}
|
|
}
|
|
|
|
/* Scan the rest of the string using word sized operation */
|
|
for (; ; lp++) {
|
|
va = *lp - mask01;
|
|
vb = (~*lp) & mask80;
|
|
if (va & vb) {
|
|
/*
|
|
* The original version from FreeBSD uses 4 (or 8) if
|
|
* branches querying every byte sequentially here.
|
|
* I was bored and rewrote it branchless, but that
|
|
* probably doesn't help in terms of performance
|
|
* because clang's optimizer is better anyway.
|
|
*/
|
|
p = (const char *)lp;
|
|
unsigned long l = *lp;
|
|
unsigned long add = 1;
|
|
#pragma clang loop unroll(full)
|
|
for (int i = 0; i < sizeof(l); i++) {
|
|
add &= (l & 0xffu) != 0;
|
|
p += add;
|
|
l >>= 8;
|
|
}
|
|
return p - str;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Copyright (c) 2021 fef <owo@fef.moe>
|
|
* Copyright (c) 2009, 2010 Xin LI <delphij@FreeBSD.org>
|
|
*
|
|
* 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$
|
|
*/
|