mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 23:08:31 +00:00
finish intellisense support and sync with upstream
This commit is contained in:
commit
ec9bfd8c56
221 changed files with 2360 additions and 1439 deletions
31
libc/str/index.c
Normal file
31
libc/str/index.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns pointer to first instance of character, the BSD way.
|
||||
*
|
||||
* @param s is a NUL-terminated string
|
||||
* @param is masked with 255 as byte to search for
|
||||
* @return is pointer to first instance of c or NULL if not found,
|
||||
* noting that c being NUL will return a pointer to terminator
|
||||
*/
|
||||
char *index(const char *s, int c) {
|
||||
return strchr(s, c);
|
||||
}
|
|
@ -18,8 +18,14 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static inline noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
|
||||
return (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies at most 𝑛 bytes from 𝑠 to 𝑑 until 𝑐 is encountered.
|
||||
* Copies at most N bytes from SRC to DST until 𝑐 is encountered.
|
||||
*
|
||||
* This is little-known C Standard Library approach, dating back to the
|
||||
* Fourth Edition of System Five, for copying a C strings to fixed-width
|
||||
|
@ -39,17 +45,46 @@
|
|||
* char cstrbuf[16];
|
||||
* snprintf(cstrbuf, sizeof(cstrbuf), "%s", CSTR);
|
||||
*
|
||||
* @return 𝑑 + idx(𝑐) + 1, or NULL if 𝑐 ∉ 𝑠₀․․ₙ₋₁
|
||||
* @note 𝑑 and 𝑠 can't overlap
|
||||
* @param c is search character and is masked with 255
|
||||
* @return DST + idx(c) + 1, or NULL if 𝑐 ∉ 𝑠₀․․ₙ₋₁
|
||||
* @note DST and SRC can't overlap
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
void *memccpy(void *d, const void *s, int c, size_t n) {
|
||||
const char *p, *pe;
|
||||
p = s;
|
||||
if ((pe = memchr(p, c, n))) {
|
||||
return mempcpy(d, s, pe - p + 1);
|
||||
} else {
|
||||
memcpy(d, s, n);
|
||||
return NULL;
|
||||
void *memccpy(void *dst, const void *src, int c, size_t n) {
|
||||
size_t i;
|
||||
uint64_t v, w;
|
||||
unsigned char *d;
|
||||
unsigned char *pd;
|
||||
const unsigned char *s;
|
||||
i = 0;
|
||||
d = dst;
|
||||
s = src;
|
||||
c &= 255;
|
||||
v = 0x0101010101010101 * c;
|
||||
for (; (uintptr_t)(s + i) & 7; ++i) {
|
||||
if (i == n) return NULL;
|
||||
if ((d[i] = s[i]) == c) return d + i + 1;
|
||||
}
|
||||
for (; i + 8 <= n; i += 8) {
|
||||
w = UncheckedAlignedRead64(s + i);
|
||||
if (~(w ^ v) & ((w ^ v) - 0x0101010101010101) & 0x8080808080808080) {
|
||||
break;
|
||||
} else {
|
||||
pd = d + i;
|
||||
pd[0] = (w >> 000) & 255;
|
||||
pd[1] = (w >> 010) & 255;
|
||||
pd[2] = (w >> 020) & 255;
|
||||
pd[3] = (w >> 030) & 255;
|
||||
pd[4] = (w >> 040) & 255;
|
||||
pd[5] = (w >> 050) & 255;
|
||||
pd[6] = (w >> 060) & 255;
|
||||
pd[7] = (w >> 070) & 255;
|
||||
}
|
||||
}
|
||||
for (; i < n; ++i) {
|
||||
if ((d[i] = s[i]) == c) {
|
||||
return d + i + 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
47
libc/str/memchr.c
Normal file
47
libc/str/memchr.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns pointer to first instance of character.
|
||||
*
|
||||
* @param m is memory to search
|
||||
* @param c is search byte which is masked with 255
|
||||
* @param n is byte length of p
|
||||
* @return is pointer to first instance of c or NULL if not found
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
void *memchr(const void *m, int c, size_t n) {
|
||||
uint64_t v, w;
|
||||
const unsigned char *p, *pe;
|
||||
c &= 255;
|
||||
v = 0x0101010101010101 * c;
|
||||
for (p = (const unsigned char *)m, pe = p + n; p + 8 <= pe; p += 8) {
|
||||
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
if ((w = ~(w ^ v) & ((w ^ v) - 0x0101010101010101) & 0x8080808080808080)) {
|
||||
return p + ((unsigned)__builtin_ctzll(w) >> 3);
|
||||
}
|
||||
}
|
||||
for (; p < pe; ++p) {
|
||||
if (*p == c) return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
160
libc/str/memmove-pure.c
Normal file
160
libc/str/memmove-pure.c
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
typedef long long xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
|
||||
|
||||
/**
|
||||
* Copies memory.
|
||||
*
|
||||
* DST and SRC may overlap.
|
||||
*
|
||||
* @param dst is destination
|
||||
* @param src is memory to copy
|
||||
* @param n is number of bytes to copy
|
||||
* @return dst
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
void *memmove$pure(void *dst, const void *src, size_t n) {
|
||||
size_t i;
|
||||
xmm_t v, w;
|
||||
char *d, *r;
|
||||
const char *s;
|
||||
uint64_t a, b;
|
||||
d = dst;
|
||||
s = src;
|
||||
switch (n) {
|
||||
case 9 ... 15:
|
||||
__builtin_memcpy(&a, s, 8);
|
||||
__builtin_memcpy(&b, s + n - 8, 8);
|
||||
__builtin_memcpy(d, &a, 8);
|
||||
__builtin_memcpy(d + n - 8, &b, 8);
|
||||
return d;
|
||||
case 5 ... 7:
|
||||
__builtin_memcpy(&a, s, 4);
|
||||
__builtin_memcpy(&b, s + n - 4, 4);
|
||||
__builtin_memcpy(d, &a, 4);
|
||||
__builtin_memcpy(d + n - 4, &b, 4);
|
||||
return d;
|
||||
case 17 ... 32:
|
||||
__builtin_memcpy(&v, s, 16);
|
||||
__builtin_memcpy(&w, s + n - 16, 16);
|
||||
__builtin_memcpy(d, &v, 16);
|
||||
__builtin_memcpy(d + n - 16, &w, 16);
|
||||
return d;
|
||||
case 16:
|
||||
__builtin_memcpy(&v, s, 16);
|
||||
__builtin_memcpy(d, &v, 16);
|
||||
return d;
|
||||
case 0:
|
||||
return d;
|
||||
case 1:
|
||||
*d = *s;
|
||||
return d;
|
||||
case 8:
|
||||
__builtin_memcpy(&a, s, 8);
|
||||
__builtin_memcpy(d, &a, 8);
|
||||
return d;
|
||||
case 4:
|
||||
__builtin_memcpy(&a, s, 4);
|
||||
__builtin_memcpy(d, &a, 4);
|
||||
return d;
|
||||
case 2:
|
||||
__builtin_memcpy(&a, s, 2);
|
||||
__builtin_memcpy(d, &a, 2);
|
||||
return d;
|
||||
case 3:
|
||||
__builtin_memcpy(&a, s, 2);
|
||||
__builtin_memcpy(&b, s + 1, 2);
|
||||
__builtin_memcpy(d, &a, 2);
|
||||
__builtin_memcpy(d + 1, &b, 2);
|
||||
return d;
|
||||
default:
|
||||
r = d;
|
||||
if (d > s) {
|
||||
do {
|
||||
n -= 32;
|
||||
__builtin_memcpy(&v, s + n, 16);
|
||||
__builtin_memcpy(&w, s + n + 16, 16);
|
||||
__builtin_memcpy(d + n, &v, 16);
|
||||
__builtin_memcpy(d + n + 16, &w, 16);
|
||||
} while (n >= 32);
|
||||
} else {
|
||||
i = 0;
|
||||
do {
|
||||
__builtin_memcpy(&v, s + i, 16);
|
||||
__builtin_memcpy(&w, s + i + 16, 16);
|
||||
__builtin_memcpy(d + i, &v, 16);
|
||||
__builtin_memcpy(d + i + 16, &w, 16);
|
||||
} while ((i += 32) + 32 <= n);
|
||||
d += i;
|
||||
s += i;
|
||||
n -= i;
|
||||
}
|
||||
switch (n) {
|
||||
case 0:
|
||||
return r;
|
||||
case 17 ... 31:
|
||||
__builtin_memcpy(&v, s, 16);
|
||||
__builtin_memcpy(&w, s + n - 16, 16);
|
||||
__builtin_memcpy(d, &v, 16);
|
||||
__builtin_memcpy(d + n - 16, &w, 16);
|
||||
return r;
|
||||
case 9 ... 15:
|
||||
__builtin_memcpy(&a, s, 8);
|
||||
__builtin_memcpy(&b, s + n - 8, 8);
|
||||
__builtin_memcpy(d, &a, 8);
|
||||
__builtin_memcpy(d + n - 8, &b, 8);
|
||||
return r;
|
||||
case 5 ... 7:
|
||||
__builtin_memcpy(&a, s, 4);
|
||||
__builtin_memcpy(&b, s + n - 4, 4);
|
||||
__builtin_memcpy(d, &a, 4);
|
||||
__builtin_memcpy(d + n - 4, &b, 4);
|
||||
return r;
|
||||
case 16:
|
||||
__builtin_memcpy(&v, s, 16);
|
||||
__builtin_memcpy(d, &v, 16);
|
||||
return r;
|
||||
case 8:
|
||||
__builtin_memcpy(&a, s, 8);
|
||||
__builtin_memcpy(d, &a, 8);
|
||||
return r;
|
||||
case 4:
|
||||
__builtin_memcpy(&a, s, 4);
|
||||
__builtin_memcpy(d, &a, 4);
|
||||
return r;
|
||||
case 1:
|
||||
*d = *s;
|
||||
return r;
|
||||
case 2:
|
||||
__builtin_memcpy(&a, s, 2);
|
||||
__builtin_memcpy(d, &a, 2);
|
||||
return r;
|
||||
case 3:
|
||||
__builtin_memcpy(&a, s, 2);
|
||||
__builtin_memcpy(&b, s + 1, 2);
|
||||
__builtin_memcpy(d, &a, 2);
|
||||
__builtin_memcpy(d + 1, &b, 2);
|
||||
return r;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
}
|
100
libc/str/memset-pure.c
Normal file
100
libc/str/memset-pure.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Sets memory.
|
||||
*
|
||||
* @param p is memory address
|
||||
* @param c is masked with 255 and used as repeated byte
|
||||
* @param n is byte length
|
||||
* @return p
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
void *memset$pure(void *p, int c, size_t n) {
|
||||
char *b;
|
||||
uint64_t x;
|
||||
b = p;
|
||||
x = 0x0101010101010101 * (c & 0xff);
|
||||
switch (n) {
|
||||
case 0:
|
||||
return p;
|
||||
case 1:
|
||||
__builtin_memcpy(b, &x, 1);
|
||||
return p;
|
||||
case 2:
|
||||
__builtin_memcpy(b, &x, 2);
|
||||
return p;
|
||||
case 3:
|
||||
__builtin_memcpy(b, &x, 2);
|
||||
__builtin_memcpy(b + 1, &x, 2);
|
||||
return p;
|
||||
case 4:
|
||||
__builtin_memcpy(b, &x, 4);
|
||||
return p;
|
||||
case 5 ... 7:
|
||||
__builtin_memcpy(b, &x, 4);
|
||||
__builtin_memcpy(b + n - 4, &x, 4);
|
||||
return p;
|
||||
case 8:
|
||||
__builtin_memcpy(b, &x, 8);
|
||||
return p;
|
||||
case 9 ... 16:
|
||||
__builtin_memcpy(b, &x, 8);
|
||||
__builtin_memcpy(b + n - 8, &x, 8);
|
||||
return p;
|
||||
default:
|
||||
do {
|
||||
n -= 16;
|
||||
__builtin_memcpy(b + n, &x, 8);
|
||||
asm volatile("" ::: "memory");
|
||||
__builtin_memcpy(b + n + 8, &x, 8);
|
||||
} while (n >= 16);
|
||||
switch (n) {
|
||||
case 0:
|
||||
return p;
|
||||
case 1:
|
||||
__builtin_memcpy(b, &x, 1);
|
||||
return p;
|
||||
case 2:
|
||||
__builtin_memcpy(b, &x, 2);
|
||||
return p;
|
||||
case 3:
|
||||
__builtin_memcpy(b, &x, 2);
|
||||
__builtin_memcpy(b + 1, &x, 2);
|
||||
return p;
|
||||
case 4:
|
||||
__builtin_memcpy(b, &x, 4);
|
||||
return p;
|
||||
case 5 ... 7:
|
||||
__builtin_memcpy(b, &x, 4);
|
||||
__builtin_memcpy(b + n - 4, &x, 4);
|
||||
return p;
|
||||
case 8:
|
||||
__builtin_memcpy(b, &x, 8);
|
||||
return p;
|
||||
case 9 ... 15:
|
||||
__builtin_memcpy(b, &x, 8);
|
||||
__builtin_memcpy(b + n - 8, &x, 8);
|
||||
return p;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,8 @@
|
|||
#include "libc/str/oldutf16.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/* TODO(jart): DELETE */
|
||||
|
||||
/**
|
||||
* Encodes character to string as UTF-16.
|
||||
*
|
||||
|
|
53
libc/str/rawmemchr.c
Normal file
53
libc/str/rawmemchr.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static inline noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
|
||||
return (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pointer to first instance of character.
|
||||
*
|
||||
* @param m is memory to search
|
||||
* @param c is search byte which is masked with 255
|
||||
* @return is pointer to first instance of c
|
||||
*/
|
||||
void *rawmemchr(const void *m, int c) {
|
||||
uint64_t v, w;
|
||||
const unsigned char *s;
|
||||
s = m;
|
||||
c &= 255;
|
||||
v = 0x0101010101010101 * c;
|
||||
for (; (uintptr_t)s & 7; ++s) {
|
||||
if (*s == c) return s;
|
||||
}
|
||||
for (;; s += 8) {
|
||||
w = UncheckedAlignedRead64(s);
|
||||
if ((w = ~(w ^ v) & ((w ^ v) - 0x0101010101010101) & 0x8080808080808080)) {
|
||||
s += (unsigned)__builtin_ctzll(w) >> 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(*s == c);
|
||||
return s;
|
||||
}
|
|
@ -90,7 +90,6 @@ void *memeqmask(void *, const void *, const void *, size_t) memcpyesque;
|
|||
size_t strlen(const char *) strlenesque;
|
||||
size_t strnlen(const char *, size_t) strlenesque;
|
||||
size_t strnlen_s(const char *, size_t);
|
||||
size_t strlen$pure(const char *) strlenesque;
|
||||
char *strchr(const char *, int) strlenesque;
|
||||
char *index(const char *, int) strlenesque;
|
||||
void *memchr(const void *, int, size_t) strlenesque;
|
||||
|
@ -188,7 +187,6 @@ char16_t *tinystrstr16(const char16_t *, const char16_t *) strlenesque;
|
|||
void *tinymemmem(const void *, size_t, const void *, size_t) strlenesque;
|
||||
void *tinymemccpy(void *, const void *, int, size_t) memcpyesque;
|
||||
|
||||
void *memtolower(void *, size_t);
|
||||
char *strntolower(char *, size_t);
|
||||
char *strtolower(char *) paramsnonnull();
|
||||
char *strntoupper(char *, size_t);
|
||||
|
@ -246,8 +244,8 @@ char *strsignal(int) returnsnonnull libcesque;
|
|||
│ cosmopolitan § strings » optimizations ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define __memcpy_isgoodsize(SIZE) \
|
||||
(__builtin_constant_p(SIZE) && ((SIZE) <= __BIGGEST_ALIGNMENT__ * 2 && \
|
||||
#define __memcpy_isgoodsize(SIZE) \
|
||||
(__builtin_constant_p(SIZE) && ((SIZE) <= __BIGGEST_ALIGNMENT__ && \
|
||||
__builtin_popcountl((unsigned)(SIZE)) == 1))
|
||||
|
||||
#define __memset_isgoodsize(SIZE) \
|
||||
|
@ -361,15 +359,44 @@ char *strsignal(int) returnsnonnull libcesque;
|
|||
})
|
||||
|
||||
#endif /* hosted/sse2/unbloat */
|
||||
#ifdef __FSANITIZE_ADDRESS__
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » address sanitizer ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
void *memset$pure(void *, int, size_t) memcpyesque;
|
||||
void *memmove$pure(void *, const void *, size_t) memcpyesque;
|
||||
size_t strlen$pure(const char *) strlenesque;
|
||||
size_t strcspn$pure(const char *, const char *) strlenesque;
|
||||
#if defined(__FSANITIZE_ADDRESS__)
|
||||
|
||||
#define strcspn(STR, REJECT) strcspn$pure(STR, REJECT)
|
||||
|
||||
#ifdef strlen
|
||||
#undef strlen
|
||||
#endif
|
||||
#define strlen(s) strlen$pure(s)
|
||||
#define strlen(STR) \
|
||||
(__builtin_constant_p(STR) ? __builtin_strlen(STR) : strlen$pure(STR))
|
||||
|
||||
#undef memset
|
||||
#define memset(DST, CHAR, SIZE) \
|
||||
(__memcpy_isgoodsize(SIZE) ? __builtin_memset(DST, CHAR, SIZE) \
|
||||
: memset$pure(DST, CHAR, SIZE))
|
||||
|
||||
#undef memmove
|
||||
#define memmove(DST, SRC, SIZE) \
|
||||
(__memcpy_isgoodsize(SIZE) ? __builtin_memmove(DST, SRC, SIZE) \
|
||||
: memmove$pure(DST, SRC, SIZE))
|
||||
|
||||
#undef memcpy
|
||||
#define memcpy(DST, SRC, SIZE) \
|
||||
(__memcpy_isgoodsize(SIZE) ? __builtin_memcpy(DST, SRC, SIZE) \
|
||||
: memmove$pure(DST, SRC, SIZE))
|
||||
|
||||
#undef mempcpy
|
||||
#define mempcpy(DST, SRC, SIZE) \
|
||||
(__memcpy_isgoodsize(SIZE) ? __builtin_mempcpy(DST, SRC, SIZE) : ({ \
|
||||
void *DsT = (DST); \
|
||||
size_t SiZe = (SIZE); \
|
||||
memmove$pure(DsT, SRC, SiZe); \
|
||||
(void *)((char *)DsT + SiZe); \
|
||||
}))
|
||||
|
||||
#endif /* __FSANITIZE_ADDRESS__ */
|
||||
#endif /* __GNUC__ && !__STRICT_ANSI__ */
|
||||
|
|
|
@ -8,6 +8,7 @@ LIBC_STR = $(LIBC_STR_A_DEPS) $(LIBC_STR_A)
|
|||
LIBC_STR_A = o/$(MODE)/libc/str/str.a
|
||||
LIBC_STR_A_FILES := $(wildcard libc/str/*)
|
||||
LIBC_STR_A_HDRS = $(filter %.h,$(LIBC_STR_A_FILES))
|
||||
LIBC_STR_A_INCS = $(filter %.inc,$(LIBC_STR_A_FILES))
|
||||
LIBC_STR_A_SRCS_A = $(filter %.s,$(LIBC_STR_A_FILES))
|
||||
LIBC_STR_A_SRCS_S = $(filter %.S,$(LIBC_STR_A_FILES))
|
||||
LIBC_STR_A_SRCS_C = $(filter %.c,$(LIBC_STR_A_FILES))
|
||||
|
@ -49,6 +50,7 @@ o/$(MODE)/libc/str/memmem.o: \
|
|||
LIBC_STR_LIBS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)))
|
||||
LIBC_STR_SRCS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_STR_HDRS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_STR_INCS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_INCS))
|
||||
LIBC_STR_BINS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_BINS))
|
||||
LIBC_STR_CHECKS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_STR_OBJS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_OBJS))
|
||||
|
|
69
libc/str/strchr.c
Normal file
69
libc/str/strchr.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
noasan static const unsigned char *strchr$x64(const unsigned char *p,
|
||||
uint64_t c) {
|
||||
unsigned a, b;
|
||||
uint64_t w, x, y;
|
||||
for (c *= 0x0101010101010101;; p += 8) {
|
||||
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
if ((x = ~(w ^ c) & ((w ^ c) - 0x0101010101010101) & 0x8080808080808080) |
|
||||
(y = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) {
|
||||
if (x) {
|
||||
a = __builtin_ctzll(x);
|
||||
if (y) {
|
||||
b = __builtin_ctzll(y);
|
||||
if (a <= b) {
|
||||
return p + (a >> 3);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
return p + (a >> 3);
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pointer to first instance of character.
|
||||
*
|
||||
* @param s is a NUL-terminated string
|
||||
* @param c is masked with 255 as byte to search for
|
||||
* @return pointer to first instance of c or NULL if not found
|
||||
* noting that if c is NUL we return pointer to terminator
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *strchr(const char *s, int c) {
|
||||
char *r;
|
||||
for (c &= 0xff; (uintptr_t)s & 7; ++s) {
|
||||
if ((*s & 0xff) == c) return s;
|
||||
if (!*s) return NULL;
|
||||
}
|
||||
r = (char *)strchr$x64((const unsigned char *)s, c);
|
||||
assert(!r || *r || !c);
|
||||
return r;
|
||||
}
|
69
libc/str/strchrnul.c
Normal file
69
libc/str/strchrnul.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
noasan static const unsigned char *strchrnul$x64(const unsigned char *p,
|
||||
uint64_t c) {
|
||||
unsigned a, b;
|
||||
uint64_t w, x, y;
|
||||
for (c *= 0x0101010101010101;; p += 8) {
|
||||
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
if ((x = ~(w ^ c) & ((w ^ c) - 0x0101010101010101) & 0x8080808080808080) |
|
||||
(y = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) {
|
||||
if (x) {
|
||||
a = __builtin_ctzll(x);
|
||||
if (y) {
|
||||
b = __builtin_ctzll(y);
|
||||
if (a <= b) {
|
||||
return p + (a >> 3);
|
||||
} else {
|
||||
return p + (b >> 3);
|
||||
}
|
||||
} else {
|
||||
return p + (a >> 3);
|
||||
}
|
||||
} else {
|
||||
b = __builtin_ctzll(y);
|
||||
return p + (b >> 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pointer to first instance of character.
|
||||
*
|
||||
* @param s is a NUL-terminated string
|
||||
* @param c is masked with 255 as byte to search for
|
||||
* @return pointer to first instance of c, or pointer to
|
||||
* NUL terminator if c is not found
|
||||
*/
|
||||
char *strchrnul(const char *s, int c) {
|
||||
char *r;
|
||||
for (c &= 0xff; (uintptr_t)s & 7; ++s) {
|
||||
if ((*s & 0xff) == c) return s;
|
||||
if (!*s) return s;
|
||||
}
|
||||
r = (char *)strchrnul$x64((const unsigned char *)s, c);
|
||||
assert((*r & 0xff) == c || !*r);
|
||||
return r;
|
||||
}
|
|
@ -18,6 +18,12 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static inline noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
|
||||
return (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares NUL-terminated strings.
|
||||
*
|
||||
|
@ -28,7 +34,25 @@
|
|||
*/
|
||||
int strcmp(const char *a, const char *b) {
|
||||
size_t i = 0;
|
||||
uint64_t v, w, d;
|
||||
if (a == b) return 0;
|
||||
while (a[i] == b[i] && b[i]) ++i;
|
||||
return (a[i] & 0xff) - (b[i] & 0xff);
|
||||
if (((uintptr_t)a & 7) == ((uintptr_t)b & 7)) {
|
||||
for (; (uintptr_t)a & 7; ++i) {
|
||||
if (a[i] != b[i] || !b[i]) {
|
||||
return (a[i] & 0xff) - (b[i] & 0xff);
|
||||
}
|
||||
}
|
||||
for (;; i += 8) {
|
||||
v = UncheckedAlignedRead64(a + i);
|
||||
w = UncheckedAlignedRead64(b + i);
|
||||
w = (v ^ w) | (~v & (v - 0x0101010101010101) & 0x8080808080808080);
|
||||
if (w) {
|
||||
i += (unsigned)__builtin_ctzll(w) >> 3;
|
||||
return (a[i] & 0xff) - (b[i] & 0xff);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (a[i] == b[i] && b[i]) ++i;
|
||||
return (a[i] & 0xff) - (b[i] & 0xff);
|
||||
}
|
||||
}
|
||||
|
|
62
libc/str/strcspn-pure.c
Normal file
62
libc/str/strcspn-pure.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/pcmpeqb.h"
|
||||
#include "libc/intrin/pmovmskb.h"
|
||||
#include "libc/intrin/pshufd.h"
|
||||
#include "libc/intrin/punpcklbw.h"
|
||||
#include "libc/intrin/punpcklwd.h"
|
||||
#include "libc/nexgen32e/hascharacter.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#define V(p) (void *)(p)
|
||||
|
||||
/**
|
||||
* Returns prefix length, consisting of chars not in reject.
|
||||
* a.k.a. Return index of first byte that's in charset.
|
||||
*
|
||||
* @param reject is nul-terminated character set
|
||||
* @see strspn(), strtok_r()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
size_t strcspn$pure(const char *s, const char *reject) {
|
||||
size_t i, n;
|
||||
unsigned m;
|
||||
char cv[16], sv[16];
|
||||
if ((n = strlen(reject)) < 16) {
|
||||
memset(sv, 0, 16);
|
||||
memcpy(sv, reject, n);
|
||||
for (i = 0;; ++i) {
|
||||
cv[0] = s[i];
|
||||
punpcklbw(V(cv), V(cv), V(cv));
|
||||
punpcklwd(V(cv), V(cv), V(cv));
|
||||
pshufd(V(cv), V(cv), 0);
|
||||
pcmpeqb(V(cv), V(cv), V(sv));
|
||||
if ((m = pmovmskb(V(cv)))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
for (i = 0; s[i]; ++i) {
|
||||
if (HasCharacter(s[i], reject)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
|
@ -16,35 +16,35 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
noasan static const char *strlen$pure$x64(const char *p) {
|
||||
static noasan size_t strlen$pure$x64(const char *s, size_t i) {
|
||||
uint64_t w;
|
||||
const unsigned char *p;
|
||||
for (;;) {
|
||||
w = *(uint64_t *)p;
|
||||
if (~w & (w - 0x0101010101010101) & 0x8080808080808080) {
|
||||
break;
|
||||
p = (const unsigned char *)s + i;
|
||||
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
if ((w = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) {
|
||||
return i + ((unsigned)__builtin_ctzll(w) >> 3);
|
||||
} else {
|
||||
p += 8;
|
||||
i += 8;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns length of NUL-terminated string.
|
||||
*/
|
||||
size_t strlen$pure(const char *s) {
|
||||
const char *p;
|
||||
p = s;
|
||||
while ((uintptr_t)p & 7) {
|
||||
if (*p) {
|
||||
++p;
|
||||
} else {
|
||||
return p - s;
|
||||
}
|
||||
size_t i;
|
||||
for (i = 0; (uintptr_t)(s + i) & 7; ++i) {
|
||||
if (!s[i]) return i;
|
||||
}
|
||||
p = strlen$pure$x64(p);
|
||||
while (*p) ++p;
|
||||
return p - s;
|
||||
i = strlen$pure$x64(s, i);
|
||||
assert(!i || s[0]);
|
||||
assert(!s[i]);
|
||||
return i;
|
||||
}
|
||||
|
|
57
libc/str/strnlen.c
Normal file
57
libc/str/strnlen.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static noasan size_t strnlen$x64(const char *s, size_t n, size_t i) {
|
||||
uint64_t w;
|
||||
const unsigned char *p;
|
||||
for (; i + 8 < n; i += 8) {
|
||||
p = (const unsigned char *)s + i;
|
||||
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
if ((w = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) {
|
||||
i += (unsigned)__builtin_ctzll(w) >> 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns length of NUL-terminated string w/ limit.
|
||||
*
|
||||
* @param s is string
|
||||
* @param n is max length
|
||||
* @return byte length
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
size_t strnlen(const char *s, size_t n) {
|
||||
size_t i;
|
||||
for (i = 0; (uintptr_t)(s + i) & 7; ++i) {
|
||||
if (i == n || !s[i]) return i;
|
||||
}
|
||||
i = strnlen$x64(s, n, i);
|
||||
for (;; ++i) {
|
||||
if (i == n || !s[i]) break;
|
||||
}
|
||||
assert(i == n || (i < n && !s[i]));
|
||||
return i;
|
||||
}
|
|
@ -18,16 +18,18 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Mutates string to ASCII uppercase w/ limit.
|
||||
*
|
||||
* @praam s is string
|
||||
* @praam n is max bytes to consider
|
||||
* @return string
|
||||
*/
|
||||
char *strntoupper(char *s, size_t n) {
|
||||
unsigned char *p = (unsigned char *)s;
|
||||
for (;;) {
|
||||
if (n-- && *p) {
|
||||
if ('a' <= *p && *p <= 'z') {
|
||||
*p -= 'a' - 'A';
|
||||
}
|
||||
++p;
|
||||
} else {
|
||||
break;
|
||||
size_t i;
|
||||
for (i = 0; s[i] && i < n; ++i) {
|
||||
if ('a' <= s[i] && s[i] <= 'z') {
|
||||
s[i] -= 'a' - 'A';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
|
|
|
@ -18,12 +18,18 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
void *tinymemccpy(void *dst, const void *src, int termchar, size_t limit) {
|
||||
/**
|
||||
* Mutates string to ASCII lowercase.
|
||||
*
|
||||
* @praam s is string
|
||||
* @return string
|
||||
*/
|
||||
char *strtolower(char *s) {
|
||||
size_t i;
|
||||
unsigned char *d;
|
||||
const unsigned char *s;
|
||||
for (termchar &= 0xff, d = dst, s = src, i = 0; i < limit; ++i) {
|
||||
if ((d[i] = s[i]) == termchar) return d + i + 1;
|
||||
for (i = 0; s[i]; ++i) {
|
||||
if ('A' <= s[i] && s[i] <= 'Z') {
|
||||
s[i] += 'a' - 'A';
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return s;
|
||||
}
|
|
@ -16,9 +16,20 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
bool ctz(double x, double y) {
|
||||
return __builtin_islessgreater(x, y);
|
||||
/**
|
||||
* Mutates string to ASCII uppercase.
|
||||
*
|
||||
* @praam s is string
|
||||
* @return string
|
||||
*/
|
||||
char *strtoupper(char *s) {
|
||||
size_t i;
|
||||
for (i = 0; s[i]; ++i) {
|
||||
if ('a' <= s[i] && s[i] <= 'z') {
|
||||
s[i] -= 'a' - 'A';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
|
@ -17,15 +17,21 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tinymemmem.internal.h"
|
||||
|
||||
/**
|
||||
* Naïve substring search implementation.
|
||||
* @see libc/alg/memmem.c
|
||||
*/
|
||||
void *tinymemmem(const void *haystk, size_t haystksize, const void *needle,
|
||||
void *tinymemmem(const void *haystack, size_t haystacksize, const void *needle,
|
||||
size_t needlesize) {
|
||||
return (/*unconst*/ void *)tinymemmemi(
|
||||
(const unsigned char *)haystk, haystksize, (const unsigned char *)needle,
|
||||
needlesize);
|
||||
size_t i;
|
||||
const char *p, *pe;
|
||||
for (p = haystack, pe = p + haystacksize; p < pe;) {
|
||||
for (++p, i = 0;;) {
|
||||
if (++i > needlesize) return p - 1;
|
||||
if (p == pe) break;
|
||||
if (((const char *)needle)[i - 1] != (p - 1)[i - 1]) break;
|
||||
}
|
||||
}
|
||||
return !haystacksize && !needlesize ? haystack : NULL;
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_
|
||||
#ifndef __STRICT_ANSI__
|
||||
#include "libc/str/str.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
forceinline void *tinymemmemi(const void *haystk, size_t haystksize,
|
||||
const void *needle, size_t needlesize) {
|
||||
const char *p = (const char *)haystk;
|
||||
const char *pe = (const char *)haystk + haystksize;
|
||||
while (p < pe) {
|
||||
size_t i = 0;
|
||||
++p;
|
||||
for (;;) {
|
||||
++i;
|
||||
if (i > needlesize) return (/*unconst*/ char *)(p - 1);
|
||||
if (p == pe) break;
|
||||
if (((const char *)needle)[i - 1] != (p - 1)[i - 1]) break;
|
||||
}
|
||||
}
|
||||
return (/*unconst*/ char *)(!haystksize && !needlesize ? haystk : NULL);
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* !ANSI */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_TINYMEMMEM_H_ */
|
|
@ -17,13 +17,22 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/tinystrstr.internal.h"
|
||||
|
||||
/**
|
||||
* Naïve substring search implementation.
|
||||
* @see libc/str/strstr.c
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *(tinystrstr)(const char *haystack, const char *needle) {
|
||||
return (/*unconst*/ char *)tinystrstr(haystack, needle);
|
||||
char *tinystrstr(const char *haystack, const char *needle) {
|
||||
size_t i;
|
||||
for (;;) {
|
||||
for (i = 0;;) {
|
||||
if (!needle[i]) return (/*unconst*/ char *)haystack;
|
||||
if (!haystack[i]) break;
|
||||
if (needle[i] != haystack[i]) break;
|
||||
++i;
|
||||
}
|
||||
if (!*haystack++) break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_
|
||||
#include "libc/str/str.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#ifndef tinystrstr
|
||||
#define tinystrstr(HAYSTACK, NEEDLE) \
|
||||
({ \
|
||||
autotype(HAYSTACK) Haystack = (HAYSTACK); \
|
||||
typeof(Haystack) Needle = (NEEDLE); \
|
||||
for (;;) { \
|
||||
size_t i = 0; \
|
||||
for (;;) { \
|
||||
if (!Needle[i]) goto Found; \
|
||||
if (!Haystack[i]) break; \
|
||||
if (Needle[i] != Haystack[i]) break; \
|
||||
++i; \
|
||||
} \
|
||||
if (!*Haystack++) break; \
|
||||
} \
|
||||
Haystack = NULL; \
|
||||
Found: \
|
||||
Haystack; \
|
||||
})
|
||||
#endif /* tinystrstr */
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_ */
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/tinystrstr.internal.h"
|
||||
|
||||
/**
|
||||
* Naïve substring search implementation.
|
||||
|
@ -25,5 +24,15 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
char16_t *tinystrstr16(const char16_t *haystack, const char16_t *needle) {
|
||||
return (/*unconst*/ char16_t *)tinystrstr(haystack, needle);
|
||||
size_t i;
|
||||
for (;;) {
|
||||
for (i = 0;;) {
|
||||
if (!needle[i]) return (/*unconst*/ char16_t *)haystack;
|
||||
if (!haystack[i]) break;
|
||||
if (needle[i] != haystack[i]) break;
|
||||
++i;
|
||||
}
|
||||
if (!*haystack++) break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "libc/str/tpdecode.internal.h"
|
||||
#include "libc/str/tpdecodecb.internal.h"
|
||||
|
||||
/* TODO(jart): DELETE */
|
||||
|
||||
forceinline int getbyte(void *arg, uint32_t i) {
|
||||
return ((const unsigned char *)arg)[i];
|
||||
}
|
||||
|
|
|
@ -6,19 +6,14 @@ COSMOPOLITAN_C_START_
|
|||
uint64_t tpenc(int32_t) pureconst;
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define tpenc(CODE) \
|
||||
({ \
|
||||
long Buf; \
|
||||
int32_t Code = (CODE); \
|
||||
if (0 <= Code && Code <= 127) { \
|
||||
Buf = Code; \
|
||||
} else { \
|
||||
asm("call\ttpenc" \
|
||||
: "=a"(Buf), "+D"(Code) \
|
||||
: /* inputs */ \
|
||||
: "rcx", "rdx", "cc"); \
|
||||
} \
|
||||
Buf; \
|
||||
#define tpenc(CODE) \
|
||||
({ \
|
||||
long Edi, Buf; \
|
||||
asm("call\ttpenc" \
|
||||
: "=a"(Buf), "=D"(Edi) \
|
||||
: "1"(CODE) \
|
||||
: "rcx", "rdx", "cc"); \
|
||||
Buf; \
|
||||
})
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue