libroot: Import some more string functions from musl.

Also enable some optimizations on newer GCC.

Change-Id: Ideb92aae85e6f8f502af61145046ea1b4a514e8a
This commit is contained in:
Augustin Cavalier
2025-01-29 20:54:19 -05:00
parent f294fe2a39
commit e33dbdc1a3
18 changed files with 410 additions and 209 deletions
+5 -5
View File
@@ -52,8 +52,13 @@ local muslSources =
rand.c
rand_r.c
memmem.c
stpcpy.c
strchrnul.c
strcspn.c
strpbrk.c
strspn.c
strstr.c
;
SourceHdrs $(muslSources) :
@@ -117,7 +122,6 @@ KernelMergeObject kernel_lib_posix.o :
# string
memchr.c
memcmp.c
memmem.c
memmove.c
strcasecmp.c
strcasestr.c
@@ -135,13 +139,9 @@ KernelMergeObject kernel_lib_posix.o :
strncpy.cpp
strndup.cpp
strnlen.cpp
strpbrk.c
strrchr.c
strspn.c
strstr.c
strtok.c
strupr.c
stpcpy.c
$(muslSources)
: $(TARGET_KERNEL_PIC_CCFLAGS)
@@ -9,10 +9,16 @@ for architectureObject in [ MultiArchSubDirSetup ] {
local architecture = $(TARGET_PACKAGING_ARCH) ;
MergeObject <$(architecture)>posix_musl_string.o :
memccpy.c
memmem.c
memrchr.c
stpcpy.c
stpncpy.c
strchrnul.c
strcspn.c
strpbrk.c
strspn.c
strstr.c
swab.c
;
}
@@ -0,0 +1,34 @@
#include <string.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)
void *memccpy(void *dest, const void *src, int c, size_t n)
{
unsigned char *d = dest;
const unsigned char *s = src;
c = (unsigned char)c;
#if defined(__GNUC__) && __GNUC__ >= 4
typedef size_t __attribute__((__may_alias__)) word;
word *wd;
const word *ws;
if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
for (; ((uintptr_t)s & ALIGN) && n && (*d=*s)!=c; n--, s++, d++);
if ((uintptr_t)s & ALIGN) goto tail;
size_t k = ONES * c;
wd=(void *)d; ws=(const void *)s;
for (; n>=sizeof(size_t) && !HASZERO(*ws^k);
n-=sizeof(size_t), ws++, wd++) *wd = *ws;
d=(void *)wd; s=(const void *)ws;
}
#endif
for (; n && (*d=*s)!=c; n--, s++, d++);
tail:
if (n) return d+1;
return 0;
}
@@ -0,0 +1,149 @@
#define _GNU_SOURCE
#include <string.h>
#include <stdint.h>
static char *twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
{
uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
for (h+=2, k-=2; k; k--, hw = hw<<8 | *h++)
if (hw == nw) return (char *)h-2;
return hw == nw ? (char *)h-2 : 0;
}
static char *threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
{
uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8;
uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8;
for (h+=3, k-=3; k; k--, hw = (hw|*h++)<<8)
if (hw == nw) return (char *)h-3;
return hw == nw ? (char *)h-3 : 0;
}
static char *fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
{
uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
for (h+=4, k-=4; k; k--, hw = hw<<8 | *h++)
if (hw == nw) return (char *)h-4;
return hw == nw ? (char *)h-4 : 0;
}
#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define BITOP(a,b,op) \
((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
static char *twoway_memmem(const unsigned char *h, const unsigned char *z, const unsigned char *n, size_t l)
{
size_t i, ip, jp, k, p, ms, p0, mem, mem0;
size_t byteset[32 / sizeof(size_t)] = { 0 };
size_t shift[256];
/* Computing length of needle and fill shift table */
for (i=0; i<l; i++)
BITOP(byteset, n[i], |=), shift[n[i]] = i+1;
/* Compute maximal suffix */
ip = -1; jp = 0; k = p = 1;
while (jp+k<l) {
if (n[ip+k] == n[jp+k]) {
if (k == p) {
jp += p;
k = 1;
} else k++;
} else if (n[ip+k] > n[jp+k]) {
jp += k;
k = 1;
p = jp - ip;
} else {
ip = jp++;
k = p = 1;
}
}
ms = ip;
p0 = p;
/* And with the opposite comparison */
ip = -1; jp = 0; k = p = 1;
while (jp+k<l) {
if (n[ip+k] == n[jp+k]) {
if (k == p) {
jp += p;
k = 1;
} else k++;
} else if (n[ip+k] < n[jp+k]) {
jp += k;
k = 1;
p = jp - ip;
} else {
ip = jp++;
k = p = 1;
}
}
if (ip+1 > ms+1) ms = ip;
else p = p0;
/* Periodic needle? */
if (memcmp(n, n+p, ms+1)) {
mem0 = 0;
p = MAX(ms, l-ms-1) + 1;
} else mem0 = l-p;
mem = 0;
/* Search loop */
for (;;) {
/* If remainder of haystack is shorter than needle, done */
if ((uintptr_t)(z-h) < l) return 0;
/* Check last byte first; advance by shift on mismatch */
if (BITOP(byteset, h[l-1], &)) {
k = l-shift[h[l-1]];
if (k) {
if (k < mem) k = mem;
h += k;
mem = 0;
continue;
}
} else {
h += l;
mem = 0;
continue;
}
/* Compare right half */
for (k=MAX(ms+1,mem); k<l && n[k] == h[k]; k++);
if (k < l) {
h += k-ms;
mem = 0;
continue;
}
/* Compare left half */
for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
if (k <= mem) return (char *)h;
h += p;
mem = mem0;
}
}
void *memmem(const void *h0, size_t k, const void *n0, size_t l)
{
const unsigned char *h = h0, *n = n0;
/* Return immediately on empty needle */
if (!l) return (void *)h;
/* Return immediately when needle is longer than haystack */
if (k<l) return 0;
/* Use faster algorithms for short needles */
h = memchr(h0, *n, k);
if (!h || l==1) return (void *)h;
k -= h - (const unsigned char *)h0;
if (k<l) return 0;
if (l==2) return twobyte_memmem(h, k, n);
if (l==3) return threebyte_memmem(h, k, n);
if (l==4) return fourbyte_memmem(h, k, n);
return twoway_memmem(h, h+k, n, l);
}
@@ -0,0 +1,27 @@
#include <string.h>
#include <stdint.h>
#include <limits.h>
#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 *stpcpy(char *d, const char *s)
{
#if defined(__GNUC__) && __GNUC__ >= 4
typedef size_t __attribute__((__may_alias__)) word;
word *wd;
const word *ws;
if ((uintptr_t)s % ALIGN == (uintptr_t)d % ALIGN) {
for (; (uintptr_t)s % ALIGN; s++, d++)
if (!(*d=*s)) return d;
wd=(void *)d; ws=(const void *)s;
for (; !HASZERO(*ws); *wd++ = *ws++);
d=(void *)wd; s=(const void *)ws;
}
#endif
for (; (*d=*s); s++, d++);
return d;
}
@@ -6,11 +6,11 @@
#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)
#define HASZERO(x) (((x)-ONES) & ~(x) & HIGHS)
char *__stpncpy(char *d, const char *s, size_t n)
char *stpncpy(char *d, const char *s, size_t n)
{
#if 0
#if defined(__GNUC__) && __GNUC__ >= 4
typedef size_t __attribute__((__may_alias__)) word;
word *wd;
const word *ws;
@@ -28,6 +28,3 @@ tail:
memset(d, 0, n);
return d;
}
weak_alias(__stpncpy, stpncpy);
@@ -6,14 +6,14 @@
#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)
#define HASZERO(x) (((x)-ONES) & ~(x) & HIGHS)
char *strchrnul(const char *s, int c)
{
c = (unsigned char)c;
if (!c) return (char *)s + strlen(s);
#if 0
#if defined(__GNUC__) && __GNUC__ >= 4
typedef size_t __attribute__((__may_alias__)) word;
const word *w;
for (; (uintptr_t)s % ALIGN; s++)
@@ -0,0 +1,7 @@
#include <string.h>
char *strpbrk(const char *s, const char *b)
{
s += strcspn(s, b);
return *s ? (char *)s : 0;
}
@@ -0,0 +1,20 @@
#include <string.h>
#define BITOP(a,b,op) \
((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
size_t strspn(const char *s, const char *c)
{
const char *a = s;
size_t byteset[32/sizeof(size_t)] = { 0 };
if (!c[0]) return 0;
if (!c[1]) {
for (; *s == *c; s++);
return s-a;
}
for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);
for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++);
return s-a;
}
@@ -0,0 +1,154 @@
#include <string.h>
#include <stdint.h>
static char *twobyte_strstr(const unsigned char *h, const unsigned char *n)
{
uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
for (h++; *h && hw != nw; hw = hw<<8 | *++h);
return *h ? (char *)h-1 : 0;
}
static char *threebyte_strstr(const unsigned char *h, const unsigned char *n)
{
uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8;
uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8;
for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8);
return *h ? (char *)h-2 : 0;
}
static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n)
{
uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
for (h+=3; *h && hw != nw; hw = hw<<8 | *++h);
return *h ? (char *)h-3 : 0;
}
#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define BITOP(a,b,op) \
((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
{
const unsigned char *z;
size_t l, ip, jp, k, p, ms, p0, mem, mem0;
size_t byteset[32 / sizeof(size_t)] = { 0 };
size_t shift[256];
/* Computing length of needle and fill shift table */
for (l=0; n[l] && h[l]; l++)
BITOP(byteset, n[l], |=), shift[n[l]] = l+1;
if (n[l]) return 0; /* hit the end of h */
/* Compute maximal suffix */
ip = -1; jp = 0; k = p = 1;
while (jp+k<l) {
if (n[ip+k] == n[jp+k]) {
if (k == p) {
jp += p;
k = 1;
} else k++;
} else if (n[ip+k] > n[jp+k]) {
jp += k;
k = 1;
p = jp - ip;
} else {
ip = jp++;
k = p = 1;
}
}
ms = ip;
p0 = p;
/* And with the opposite comparison */
ip = -1; jp = 0; k = p = 1;
while (jp+k<l) {
if (n[ip+k] == n[jp+k]) {
if (k == p) {
jp += p;
k = 1;
} else k++;
} else if (n[ip+k] < n[jp+k]) {
jp += k;
k = 1;
p = jp - ip;
} else {
ip = jp++;
k = p = 1;
}
}
if (ip+1 > ms+1) ms = ip;
else p = p0;
/* Periodic needle? */
if (memcmp(n, n+p, ms+1)) {
mem0 = 0;
p = MAX(ms, l-ms-1) + 1;
} else mem0 = l-p;
mem = 0;
/* Initialize incremental end-of-haystack pointer */
z = h;
/* Search loop */
for (;;) {
/* Update incremental end-of-haystack pointer */
if ((uintptr_t)(z-h) < l) {
/* Fast estimate for MAX(l,63) */
size_t grow = l | 63;
const unsigned char *z2 = memchr(z, 0, grow);
if (z2) {
z = z2;
if ((uintptr_t)(z-h) < l) return 0;
} else z += grow;
}
/* Check last byte first; advance by shift on mismatch */
if (BITOP(byteset, h[l-1], &)) {
k = l-shift[h[l-1]];
if (k) {
if (k < mem) k = mem;
h += k;
mem = 0;
continue;
}
} else {
h += l;
mem = 0;
continue;
}
/* Compare right half */
for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
if (n[k]) {
h += k-ms;
mem = 0;
continue;
}
/* Compare left half */
for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
if (k <= mem) return (char *)h;
h += p;
mem = mem0;
}
}
char *strstr(const char *h, const char *n)
{
/* Return immediately on empty needle */
if (!n[0]) return (char *)h;
/* Use faster algorithms for short needles */
h = strchr(h, *n);
if (!h || !n[1]) return (char *)h;
if (!h[1]) return 0;
if (!n[2]) return twobyte_strstr((void *)h, (void *)n);
if (!h[2]) return 0;
if (!n[3]) return threebyte_strstr((void *)h, (void *)n);
if (!h[3]) return 0;
if (!n[4]) return fourbyte_strstr((void *)h, (void *)n);
return twoway_strstr((void *)h, (void *)n);
}
-6
View File
@@ -20,12 +20,9 @@ for architectureObject in [ MultiArchSubDirSetup ] {
bcmp.c
bcopy.c
bzero.c
memccpy.c
memchr.c
memcmp.c
memmem.c
memmove.c
stpcpy.c
strcasecmp.c
strcasestr.c
strcat.c
@@ -44,10 +41,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
strncpy.cpp
strndup.cpp
strnlen.cpp
strpbrk.c
strrchr.c
strspn.c
strstr.c
strtok.c
strupr.c
strxfrm.cpp
-27
View File
@@ -1,27 +0,0 @@
/*
* Copyright 2005, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT license.
*/
#include <SupportDefs.h>
#include <string.h>
void *
memccpy(void *_dest, const void *_source, int stopByte, size_t length)
{
if (length) {
const uint8 *source = (const uint8 *)_source;
uint8 *dest = (uint8 *)_dest;
do {
if ((*dest++ = *source++) == (uint8)stopByte)
return dest;
} while (--length != 0);
}
return NULL;
}
-64
View File
@@ -1,64 +0,0 @@
/* $OpenBSD: memmem.c,v 1.4 2015/08/31 02:53:57 guenther Exp $ */
/*-
* Copyright (c) 2005 Pascal Gloor <[email protected]>
*
* 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.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* 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.
*/
#define _DEFAULT_SOURCE
#include <string.h>
/*
* Find the first occurrence of the byte string s in byte string l.
*/
void *
memmem(const void *l, size_t l_len, const void *s, size_t s_len)
{
const char *cur, *last;
const char *cl = l;
const char *cs = s;
/* a zero length needle should just return the haystack */
if (s_len == 0)
return (void *)cl;
/* "s" must be smaller or equal to "l" */
if (l_len < s_len)
return NULL;
/* special case where s_len == 1 */
if (s_len == 1)
return memchr(l, *cs, l_len);
/* the last position where its possible to find "s" in "l" */
last = cl + l_len - s_len;
for (cur = cl; cur <= last; cur++)
if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
return (void *)cur;
return NULL;
}
-21
View File
@@ -1,21 +0,0 @@
/*
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
** Distributed under the terms of the MIT License.
*/
#include <sys/types.h>
#include <string.h>
/* This is not a POSIX function, but since BeOS exports it, we need to, as well. */
char *
stpcpy(char *dest, char const *src)
{
while ((*dest++ = *src++) != '\0')
;
return dest - 1;
}
-24
View File
@@ -1,24 +0,0 @@
/*
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <sys/types.h>
#include <string.h>
char *
strpbrk(char const *cs, char const *ct)
{
const char *sc1;
const char *sc2;
for (sc1 = cs; *sc1 != '\0'; ++sc1) {
for (sc2 = ct; *sc2 != '\0'; ++sc2) {
if (*sc1 == *sc2)
return (char *)sc1;
}
}
return NULL;
}
-28
View File
@@ -1,28 +0,0 @@
/*
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <sys/types.h>
#include <string.h>
size_t
strspn(char const *s, char const *accept)
{
const char *p;
const char *a;
size_t count = 0;
for (p = s; *p != '\0'; ++p) {
for (a = accept; *a != '\0'; ++a) {
if (*p == *a)
break;
}
if (*a == '\0')
return count;
++count;
}
return count;
}
-23
View File
@@ -1,23 +0,0 @@
/*
* Taken from Wikipedia, which declared it as "public domain".
*/
#include <sys/types.h>
#include <string.h>
char *
strstr(const char *s1, const char *s2)
{
size_t s2len;
/* Check for the null s2 case. */
if (*s2 == '\0')
return (char *) s1;
s2len = strlen(s2);
for (; (s1 = strchr(s1, *s2)) != NULL; s1++) {
if (strncmp(s1, s2, s2len) == 0)
return (char *)s1;
}
return NULL;
}
+3 -3
View File
@@ -54,6 +54,9 @@ for architectureObject in [ MultiArchSubDirSetup ] {
<src!system!libroot!posix!musl!string!$(architecture)>strchrnul.o
<src!system!libroot!posix!musl!string!$(architecture)>strcspn.o
<src!system!libroot!posix!musl!string!$(architecture)>strpbrk.o
<src!system!libroot!posix!musl!string!$(architecture)>strspn.o
<src!system!libroot!posix!musl!string!$(architecture)>strstr.o
<src!system!libroot!posix!string!$(architecture)>memchr.o
<src!system!libroot!posix!string!$(architecture)>memcmp.o
@@ -70,10 +73,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
<src!system!libroot!posix!string!$(architecture)>strlen.o
<src!system!libroot!posix!string!$(architecture)>strncmp.o
<src!system!libroot!posix!string!$(architecture)>strnlen.o
<src!system!libroot!posix!string!$(architecture)>strpbrk.o
<src!system!libroot!posix!string!$(architecture)>strrchr.o
<src!system!libroot!posix!string!$(architecture)>strspn.o
<src!system!libroot!posix!string!$(architecture)>strstr.o
;
SEARCH on [ FGristFiles kernel_cpp.cpp ]