mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 06:48:31 +00:00
Initial import
This commit is contained in:
commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
11
libc/str/appendchar.h
Normal file
11
libc/str/appendchar.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_APPENDCHAR_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_APPENDCHAR_H_
|
||||
#include "libc/str/str.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
forceinline void AppendChar(char **p, char *pe, wint_t c) {
|
||||
if (*p < pe) *p += tpencode(*p, pe - *p, c, false);
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_APPENDCHAR_H_ */
|
31
libc/str/chomp.c
Normal file
31
libc/str/chomp.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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Mutates line to remove line-ending characters.
|
||||
*
|
||||
* @param line is NULL-propagating
|
||||
* @see getline
|
||||
*/
|
||||
char *(chomp)(char *line) {
|
||||
if (line) line[strcspn(line, "\r\n")] = '\0';
|
||||
return line;
|
||||
}
|
31
libc/str/chomp16.c
Normal file
31
libc/str/chomp16.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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Mutates line to remove line-ending characters.
|
||||
*
|
||||
* @param line is NULL-propagating
|
||||
* @see getline
|
||||
*/
|
||||
char16_t *chomp16(char16_t *line) {
|
||||
if (line) line[strcspn(line, u"\r\n")] = '\0';
|
||||
return line;
|
||||
}
|
35
libc/str/endswith.c
Normal file
35
libc/str/endswith.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns true if s has suffix.
|
||||
*
|
||||
* @param s is a NUL-terminated string
|
||||
* @param suffix is also NUL-terminated
|
||||
*/
|
||||
bool(endswith)(const char *s, const char *suffix) {
|
||||
size_t l1, l2;
|
||||
if (s == suffix) return true;
|
||||
l1 = strlen(s);
|
||||
l2 = strnlen(suffix, l1);
|
||||
if (l2 > l1) return false;
|
||||
return memcmp(s + (l1 - l2) * sizeof(char), suffix, l2 * sizeof(char)) == 0;
|
||||
}
|
32
libc/str/endswith16.c
Normal file
32
libc/str/endswith16.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#undef char
|
||||
#undef endswith
|
||||
#undef strlen
|
||||
#undef strnlen
|
||||
|
||||
#define char char16_t
|
||||
#define endswith endswith16
|
||||
#define strlen strlen16
|
||||
#define strnlen strnlen16
|
||||
|
||||
#include "libc/str/endswith.c"
|
33
libc/str/getkvlin.c
Normal file
33
libc/str/getkvlin.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- mode:c; indent-tabs-mode:nil; tab-width:2; coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
int getkvlin(const char *name, const char *const unsorted[]) {
|
||||
if (unsorted) {
|
||||
unsigned namelen = strlen(name);
|
||||
for (int i = 0; unsorted[i]; ++i) {
|
||||
if (strncmp(unsorted[i], name, namelen) == 0 &&
|
||||
unsorted[i][namelen] == '=') {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
45
libc/str/getutf16.ncabi.c
Normal file
45
libc/str/getutf16.ncabi.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Decodes UTF-16 character.
|
||||
*
|
||||
* @param s is a NUL-terminated string
|
||||
* @return number of bytes (NUL counts as 1) or -1 w/ errno
|
||||
* @note synchronization is performed to skip leading continuations;
|
||||
* canonicalization and validation are performed to some extent
|
||||
*/
|
||||
unsigned(getutf16)(const char16_t *p, wint_t *wc) {
|
||||
unsigned skip = 0;
|
||||
while ((p[skip] & UTF16_MASK) == UTF16_CONT) skip++;
|
||||
if ((p[skip] & UTF16_MASK) != UTF16_MOAR) {
|
||||
*wc = p[skip];
|
||||
return skip + 1;
|
||||
} else if ((p[skip + 1] & UTF16_MASK) != UTF16_CONT) {
|
||||
*wc = INVALID_CODEPOINT;
|
||||
return -1;
|
||||
} else {
|
||||
*wc = 0x10000 + ((((unsigned)p[skip + 0] - 0xd800) << 10) +
|
||||
((unsigned)p[skip + 1] - 0xdc00));
|
||||
return skip + 2;
|
||||
}
|
||||
}
|
29
libc/str/indexdoublenulstring.c
Normal file
29
libc/str/indexdoublenulstring.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
const char *indexdoublenulstring(const char *p, unsigned i) {
|
||||
while (i--) {
|
||||
const char *p2 = rawmemchr(p, '\0');
|
||||
if (p2 == p) return NULL;
|
||||
p = p2 + 1;
|
||||
}
|
||||
return p;
|
||||
}
|
63
libc/str/internal.h
Normal file
63
libc/str/internal.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef COSMOPOLITAN_LIBC_STR_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_INTERNAL_H_
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
hidden extern const uint32_t kSha256Tab[64];
|
||||
|
||||
extern const struct TpEncode {
|
||||
uint8_t mark;
|
||||
uint8_t len;
|
||||
} kTpDecoderRing[32];
|
||||
|
||||
forceinline struct TpEncode UseTpDecoderRing(wint_t c) {
|
||||
unsigned msb;
|
||||
if (c) {
|
||||
asm("bsr\t%1,%0" : "=r"(msb) : "rm"(c) : "cc");
|
||||
} else {
|
||||
msb = 0;
|
||||
}
|
||||
return kTpDecoderRing[msb];
|
||||
}
|
||||
|
||||
nodebuginfo forceinline bool32 ismoar(wint_t c) {
|
||||
return (c & 0b11000000) == 0b11000000;
|
||||
}
|
||||
|
||||
nodebuginfo forceinline bool32 iscont(wint_t c) {
|
||||
return (c & 0b11000000) == 0b10000000;
|
||||
}
|
||||
|
||||
extern const uint32_t kCrc32Tab[256];
|
||||
|
||||
char *strstr$sse42(const char *, const char *) strlenesque hidden;
|
||||
char16_t *strstr16$sse42(const char16_t *, const char16_t *) strlenesque hidden;
|
||||
void *memmem$sse42(const void *, size_t, const void *,
|
||||
size_t) strlenesque hidden;
|
||||
uint32_t crc32c$sse42(uint32_t, const void *, size_t) strlenesque hidden;
|
||||
uint32_t crc32$pclmul(uint32_t, const void *, size_t) hidden;
|
||||
void sha256$x86(uint32_t[hasatleast 8], const uint8_t[hasatleast 64],
|
||||
uint32_t) hidden;
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_INTERNAL_H_ */
|
64
libc/str/isnotplaintext.c
Normal file
64
libc/str/isnotplaintext.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
|
||||
/**
|
||||
* Checks if memory address contains non-plain text.
|
||||
*
|
||||
* @param data points to memory that's interpreted as char
|
||||
* @param size is usually strlen(data) and provided by caller
|
||||
* @return NULL if plain text, or pointer to first non-text datum
|
||||
* @type char may be 6/7/8/16/32/64-bit signed/unsigned single/multi
|
||||
* @author Justine Alexandra Roberts Tunney <jtunney@gmail.com>
|
||||
* @see ASA X3.4, ISO/IEC 646, ITU T.50, ANSI X3.64-1979
|
||||
* @perf 27gBps on i7-6700 w/ -O3 -mavx2
|
||||
* @cost 143 bytes of code w/ -Os
|
||||
*/
|
||||
void *isnotplaintext(const void *data, size_t size) {
|
||||
/*
|
||||
* ASCII, EBCDIC, UNICODE, ISO IR-67, etc. all agree upon the
|
||||
* encoding of the NUL, SOH, STX, and ETX characters due to a
|
||||
* longstanding human tradition of using them for the purpose
|
||||
* of delimiting text from non-text, b/c fixed width integers
|
||||
* makes their presence in binary formats nearly unavoidable.
|
||||
*/
|
||||
#define isnotplain(C) (0 <= (C) && (C) < 4)
|
||||
char no;
|
||||
unsigned i;
|
||||
const char *p, *pe;
|
||||
if (CHAR_BIT > 6) {
|
||||
p = (const char *)data;
|
||||
pe = (const char *)(p + size);
|
||||
for (; ((intptr_t)p & 31) && p < pe; ++p) {
|
||||
if (isnotplain(*p)) return p;
|
||||
}
|
||||
for (; p + 64 < pe; p += 64) {
|
||||
no = 0;
|
||||
for (i = 0; i < 64; ++i) {
|
||||
no |= isnotplain(p[i]);
|
||||
}
|
||||
if (no & 1) break;
|
||||
}
|
||||
for (; p < pe; ++p) {
|
||||
if (isnotplain(*p)) return p;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#undef isnotplain
|
||||
}
|
52
libc/str/iswctype.c
Normal file
52
libc/str/iswctype.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static const struct WcTypes {
|
||||
char name[8];
|
||||
wctype_t type;
|
||||
} wctypes[] = {{"alnum", 0x006}, {"alpha", 0x002}, {"blank", 0x080},
|
||||
{"cntrl", 0x100}, {"digit", 0x004}, {"graph", 0x200},
|
||||
{"lower", 0x020}, {"print", 0x010}, {"punct", 0x300},
|
||||
{"space", 0x001}, {"upper", 0x040}, {"xdigit", 0x008}};
|
||||
|
||||
wctype_t wctype(const char *s) {
|
||||
char name[8];
|
||||
strncpy(name, s, sizeof(name));
|
||||
for (unsigned i = 0; i < ARRAYLEN(wctypes); ++i) {
|
||||
if (memcmp(name, wctypes[i].name, sizeof(name)) == 0) {
|
||||
return wctypes[i].type;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iswctype(wint_t c, wctype_t type) {
|
||||
if (c < 128) {
|
||||
if (!(type & ~0xff)) {
|
||||
return kCtype[(unsigned char)type];
|
||||
}
|
||||
if (type == 0x100) return iscntrl((unsigned char)c);
|
||||
if (type == 0x200) return isgraph((unsigned char)c);
|
||||
if (type == 0x300) return ispunct((unsigned char)c);
|
||||
}
|
||||
return 0;
|
||||
}
|
26
libc/str/knuthmultiplicativehash.h
Normal file
26
libc/str/knuthmultiplicativehash.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_KNUTHMULTIPLICATIVEHASH_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_KNUTHMULTIPLICATIVEHASH_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
forceinline uint32_t KnuthMultiplicativeHash32(const void *buf, size_t size) {
|
||||
/* frozen due to presence in sqlite & promise in libc/getuid.c */
|
||||
const unsigned char *const p = (const unsigned char *)buf;
|
||||
uint32_t hash = 0, kPhiPrime = 0x9e3779b1;
|
||||
size_t i;
|
||||
for (i = 0; i < size; i++) hash = (p[i] + hash) * kPhiPrime;
|
||||
return hash;
|
||||
}
|
||||
|
||||
forceinline uint64_t KnuthMultiplicativeHash(const void *buf, size_t size) {
|
||||
/* TODO(jart): verify w/ primary source */
|
||||
const unsigned char *const p = (const unsigned char *)buf;
|
||||
uint64_t hash = 0, kPhiPrime = 0x9e3779b9925d4c17;
|
||||
size_t i;
|
||||
for (i = 0; i < size; i++) hash = (p[i] + hash) * kPhiPrime;
|
||||
return hash;
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_KNUTHMULTIPLICATIVEHASH_H_ */
|
56
libc/str/ktpdecoderring.S
Normal file
56
libc/str/ktpdecoderring.S
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Thompson-Pike Decoder Ring.
|
||||
/
|
||||
/ The IA-32 BSR instruction can be used to turn a 32-bit
|
||||
/ number into an index for this table.
|
||||
/
|
||||
/ @see libc/str/internal.h
|
||||
.rodata
|
||||
.align 2
|
||||
kTpDecoderRing:
|
||||
.rept 7 # MSB≤6 (0x7F)
|
||||
.byte 0b00000000,1 # mark,len
|
||||
/ 0b11000000 # mask
|
||||
.endr
|
||||
.rept 4 # MSB≤10 (0x7FF)
|
||||
.byte 0b11000000,2 # mark,len
|
||||
/ 0b11100000 # mask
|
||||
.endr
|
||||
.rept 5 # MSB≤15 (0xFFFF)
|
||||
.byte 0b11100000,3 # mark,len
|
||||
/ 0b11110000 # mask
|
||||
.endr
|
||||
.rept 5 # MSB≤20 (0x1FFFFF)
|
||||
.byte 0b11110000,4 # mark,len
|
||||
/ 0b11111000 # mask
|
||||
.endr
|
||||
.rept 5 # MSB≤25 (0x3FFFFFF)
|
||||
.byte 0b11111000,5 # mark,len
|
||||
/ 0b11111100 # mask
|
||||
.endr
|
||||
.rept 6 # MSB≤31 (0xffffffff)
|
||||
.byte 0b11111100,6 # mark,len
|
||||
.endr
|
||||
.endobj kTpDecoderRing,globl,hidden
|
||||
.previous
|
36
libc/str/mbtowc.c
Normal file
36
libc/str/mbtowc.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
compatfn int mbtowc(wchar_t *wc, const char *s, size_t n) {
|
||||
if (!s) return 0;
|
||||
alignas(8) char alt[ROUNDUP(MB_CUR_MAX, 8)];
|
||||
if (n < MB_CUR_MAX) {
|
||||
memset(alt, 0, sizeof(alt));
|
||||
memcpy(alt, s, n);
|
||||
s = &alt[0];
|
||||
}
|
||||
wint_t wi;
|
||||
int rc = tpdecode(s, &wi);
|
||||
if (wc) *wc = (wchar_t)wi;
|
||||
return rc;
|
||||
}
|
55
libc/str/memccpy.c
Normal file
55
libc/str/memccpy.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Copies at most 𝑛 bytes from 𝑠 to 𝑑 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
|
||||
* buffers, with added generality.
|
||||
*
|
||||
* For example, strictly:
|
||||
*
|
||||
* char buf[16];
|
||||
* CHECK_NOTNULL(memccpy(buf, s, '\0', sizeof(buf)));
|
||||
*
|
||||
* Or unstrictly:
|
||||
*
|
||||
* if (!memccpy(buf, s, '\0', sizeof(buf))) strcpy(buf, "?");
|
||||
*
|
||||
* Are usually more sensible than the following:
|
||||
*
|
||||
* char cstrbuf[16];
|
||||
* snprintf(cstrbuf, sizeof(cstrbuf), "%s", CSTR);
|
||||
*
|
||||
* @return 𝑑 + idx(𝑐) + 1, or NULL if 𝑐 ∉ 𝑠₀․․ₙ₋₁
|
||||
* @note 𝑑 and 𝑠 can't overlap
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
void *memccpy(void *d, const void *s, int c, size_t n) {
|
||||
const char *p, *pe;
|
||||
if ((pe = memchr((p = s), c, n))) {
|
||||
return mempcpy(d, s, pe - p + 1);
|
||||
} else {
|
||||
memcpy(d, s, n);
|
||||
return NULL;
|
||||
}
|
||||
}
|
30
libc/str/memfrob.c
Normal file
30
libc/str/memfrob.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Memfrob implements a crypto algorithm proven to be unbreakable,
|
||||
* without meeting its requirements concerning secrecy or length.
|
||||
*/
|
||||
void *memfrob(void *buf, size_t size) {
|
||||
unsigned char *p = (unsigned char *)buf;
|
||||
for (size_t i = 0; i < size; ++i) p[i] ^= '*';
|
||||
return buf;
|
||||
}
|
57
libc/str/pututf16.ncabi.c
Normal file
57
libc/str/pututf16.ncabi.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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Encodes character to string as UTF-16.
|
||||
*
|
||||
* Implementation Details: The header macro should ensure this function
|
||||
* is only called for truly huge codepoints. Plus this function makes a
|
||||
* promise to not clobber any registers but %rax.
|
||||
*
|
||||
* @param s is what ch gets encoded to
|
||||
* @param size is the number of shorts available in s
|
||||
* @param awesome enables numbers the IETF unilaterally banned
|
||||
* @return number of shorts written or -1 w/ errno
|
||||
*/
|
||||
int(pututf16)(char16_t *s, size_t size, wint_t wc, bool awesome) {
|
||||
wint_t wc2;
|
||||
if (size) {
|
||||
if ((0 <= wc && wc < 32) && awesome && size >= 2) {
|
||||
s[0] = 0xd800;
|
||||
s[1] = 0xdc00 | wc;
|
||||
return 2;
|
||||
}
|
||||
if ((0 <= wc && wc <= 0xD7FF) || (0xE000 <= wc && wc <= 0xFFFF)) {
|
||||
s[0] = wc;
|
||||
return 1;
|
||||
} else if (0x10000 <= wc && wc <= 0x10FFFF && size >= 2) {
|
||||
wc2 = wc - 0x10000;
|
||||
s[0] = (wc2 >> 10) + 0xd800;
|
||||
s[1] = (wc2 & 1023) + 0xdc00;
|
||||
return 2;
|
||||
} else {
|
||||
s[0] = INVALID_CODEPOINT;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
29
libc/str/rindex.S
Normal file
29
libc/str/rindex.S
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Returns pointer to last instance of character the BSD way.
|
||||
/
|
||||
/ @param rdi is a non-null NUL-terminated string pointer
|
||||
/ @param esi is the search byte
|
||||
/ @return rax points to result, or NULL if not found
|
||||
rindex: jmp strrchr
|
||||
.endfn rindex,globl
|
135
libc/str/sha256.c
Normal file
135
libc/str/sha256.c
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*********************************************************************
|
||||
* Filename: sha256.c
|
||||
* Author: Brad Conte (brad AT bradconte.com)
|
||||
* Copyright:
|
||||
* Disclaimer: This code is presented "as is" without any guarantees.
|
||||
* Details: Implementation of the SHA-256 hashing algorithm.
|
||||
SHA-256 is one of the three algorithms in the SHA2
|
||||
specification. The others, SHA-384 and SHA-512, are not
|
||||
offered in this implementation.
|
||||
Algorithm specification can be found here:
|
||||
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
|
||||
This implementation uses little endian byte order.
|
||||
*********************************************************************/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#define ROTLEFT(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
|
||||
#define ROTRIGHT(a, b) (((a) >> (b)) | ((a) << (32 - (b))))
|
||||
#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
|
||||
#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
||||
#define EP0(x) (ROTRIGHT(x, 2) ^ ROTRIGHT(x, 13) ^ ROTRIGHT(x, 22))
|
||||
#define EP1(x) (ROTRIGHT(x, 6) ^ ROTRIGHT(x, 11) ^ ROTRIGHT(x, 25))
|
||||
#define SIG0(x) (ROTRIGHT(x, 7) ^ ROTRIGHT(x, 18) ^ ((x) >> 3))
|
||||
#define SIG1(x) (ROTRIGHT(x, 17) ^ ROTRIGHT(x, 19) ^ ((x) >> 10))
|
||||
|
||||
static void sha256_transform(uint32_t state[hasatleast 8],
|
||||
const uint8_t data[hasatleast 64]) {
|
||||
size_t i;
|
||||
uint32_t a, b, c, d, e, f, g, h, t1, t2, m[64];
|
||||
for (i = 0; i < 16; ++i, data += 4) {
|
||||
m[i] = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
||||
}
|
||||
for (; i < 64; ++i) {
|
||||
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
|
||||
}
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
f = state[5];
|
||||
g = state[6];
|
||||
h = state[7];
|
||||
for (i = 0; i < 64; ++i) {
|
||||
t1 = h + EP1(e) + CH(e, f, g) + kSha256Tab[i] + m[i];
|
||||
t2 = EP0(a) + MAJ(a, b, c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + t1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = t1 + t2;
|
||||
}
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
state[5] += f;
|
||||
state[6] += g;
|
||||
state[7] += h;
|
||||
}
|
||||
|
||||
void sha256_init(struct Sha256Ctx *ctx) {
|
||||
ctx->datalen = 0;
|
||||
ctx->bitlen = 0;
|
||||
ctx->state[0] = 0x6a09e667;
|
||||
ctx->state[1] = 0xbb67ae85;
|
||||
ctx->state[2] = 0x3c6ef372;
|
||||
ctx->state[3] = 0xa54ff53a;
|
||||
ctx->state[4] = 0x510e527f;
|
||||
ctx->state[5] = 0x9b05688c;
|
||||
ctx->state[6] = 0x1f83d9ab;
|
||||
ctx->state[7] = 0x5be0cd19;
|
||||
}
|
||||
|
||||
void sha256_update(struct Sha256Ctx *ctx, const uint8_t *data, size_t size) {
|
||||
size_t i;
|
||||
i = 0;
|
||||
#if 0
|
||||
if (!IsTiny() && size >= 64 &&
|
||||
(X86_HAVE(SHA) && X86_HAVE(SSE4_1) && X86_HAVE(SSSE3))) {
|
||||
sha256$x86(ctx->state, data, size);
|
||||
i += rounddown(size, 16);
|
||||
}
|
||||
#endif
|
||||
for (; i < size; ++i) {
|
||||
ctx->data[ctx->datalen] = data[i];
|
||||
ctx->datalen++;
|
||||
if (ctx->datalen == 64) {
|
||||
sha256_transform(ctx->state, ctx->data);
|
||||
ctx->bitlen += 512;
|
||||
ctx->datalen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sha256_final(struct Sha256Ctx *ctx, uint8_t *hash) {
|
||||
size_t i;
|
||||
i = ctx->datalen;
|
||||
if (ctx->datalen < 56) {
|
||||
ctx->data[i++] = 0x80;
|
||||
while (i < 56) ctx->data[i++] = 0x00;
|
||||
} else {
|
||||
ctx->data[i++] = 0x80;
|
||||
while (i < 64) ctx->data[i++] = 0x00;
|
||||
sha256_transform(ctx->state, ctx->data);
|
||||
memset(ctx->data, 0, 56);
|
||||
}
|
||||
ctx->bitlen += ctx->datalen * 8;
|
||||
ctx->data[63] = ctx->bitlen;
|
||||
ctx->data[62] = ctx->bitlen >> 8;
|
||||
ctx->data[61] = ctx->bitlen >> 16;
|
||||
ctx->data[60] = ctx->bitlen >> 24;
|
||||
ctx->data[59] = ctx->bitlen >> 32;
|
||||
ctx->data[58] = ctx->bitlen >> 40;
|
||||
ctx->data[57] = ctx->bitlen >> 48;
|
||||
ctx->data[56] = ctx->bitlen >> 56;
|
||||
sha256_transform(ctx->state, ctx->data);
|
||||
for (i = 0; i < 4; ++i) {
|
||||
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
|
||||
}
|
||||
}
|
29
libc/str/startswith.c
Normal file
29
libc/str/startswith.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns true if s has prefix.
|
||||
* @param s is a NUL-terminated string
|
||||
* @param prefix is also NUL-terminated
|
||||
*/
|
||||
bool(startswith)(const char *s, const char *prefix) {
|
||||
return strncmp(s, prefix, strlen(prefix)) == 0;
|
||||
}
|
32
libc/str/startswith16.c
Normal file
32
libc/str/startswith16.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#undef char
|
||||
#undef startswith
|
||||
#undef strlen
|
||||
#undef strncmp
|
||||
|
||||
#define char char16_t
|
||||
#define startswith startswith16
|
||||
#define strlen strlen16
|
||||
#define strncmp strncmp16
|
||||
|
||||
#include "libc/str/startswith.c"
|
29
libc/str/stpcpy.c
Normal file
29
libc/str/stpcpy.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Copies string, returning pointer to where copying ended.
|
||||
* @see strcpy(), mempcpy()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *stpcpy(char *dst, const char *src) {
|
||||
return (char *)mempcpy(dst, src, strlen(src) + 1) - 1;
|
||||
}
|
42
libc/str/stpncpy.c
Normal file
42
libc/str/stpncpy.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Prepares static search buffer.
|
||||
*
|
||||
* 1. If SRC is too long, it's truncated and *not* NUL-terminated.
|
||||
* 2. If SRC is too short, the remainder is zero-filled.
|
||||
*
|
||||
* Please note this function isn't designed to prevent untrustworthy
|
||||
* data from modifying memory without authorization. Consider trying
|
||||
* memccpy() for that purpose.
|
||||
*
|
||||
* @return dest + stride
|
||||
* @see stncpy(), memccpy()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *stpncpy(char *dest, const char *src, size_t stride) {
|
||||
char *p;
|
||||
if ((p = memccpy(dest, src, '\0', stride))) {
|
||||
memset(p, 0, dest + stride - p);
|
||||
}
|
||||
return dest + stride;
|
||||
}
|
683
libc/str/str.h
Normal file
683
libc/str/str.h
Normal file
|
@ -0,0 +1,683 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_STR_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_STR_H_
|
||||
#include "libc/bits/bits.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § characters » asa x3.4-1967 ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│─╝
|
||||
fourth age telecommunications */
|
||||
|
||||
extern const uint8_t gperf_downcase[256];
|
||||
extern const uint8_t kCtype[256];
|
||||
extern const uint8_t kToLower[256];
|
||||
extern const uint8_t kToUpper[256];
|
||||
extern const uint16_t kToLower16[256];
|
||||
extern const uint8_t kBase36[256];
|
||||
extern const char16_t kCp437[256]; /** IBM Code Page 437 */
|
||||
|
||||
int isascii(int);
|
||||
int isspace(int);
|
||||
int isalpha(int);
|
||||
int isdigit(int);
|
||||
int isalnum(int);
|
||||
int isxdigit(int);
|
||||
int isprint(int);
|
||||
int islower(int);
|
||||
int isupper(int);
|
||||
int isblank(int);
|
||||
int iscntrl(int);
|
||||
int isgraph(int);
|
||||
int tolower(int);
|
||||
int ispunct(int);
|
||||
int toupper(int);
|
||||
int hextoint(int);
|
||||
|
||||
void *isnotplaintext(const void *, size_t) nothrow nocallback nosideeffect;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § characters » thompson-pike encoding ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│─╝
|
||||
fifth age telecommunications
|
||||
|
||||
0123456789abcdef
|
||||
┌0─ ☺☻♥♦♣♠•◘○◙♂♀♪♫☼┬───Control
|
||||
└1─►◄↕‼¶§▬↨↑↓→←∟↔▲▼┘
|
||||
┌2─ !"#$%&'()*+,-./┐
|
||||
│3 0123456789:;<=>?│
|
||||
│4 @ABCDEFGHIJKLMNO├───ASA x3.4-1967
|
||||
│5 PQRSTUVWXYZ[\]^_│
|
||||
│6 `abcdefghijklmno│
|
||||
└7─pqrstuvwxyz{|}~⌂┘
|
||||
┌8─ÇüéâäàåçêëèïîìÄÅ┐
|
||||
│9 ÉæÆôöòûùÿÖÜ¢£¥€ƒ├───Thompson-Pike Continuation
|
||||
│a á¡óúñѪº¿⌐¬½¼¡«»│ (not really characters)
|
||||
└b─░▒▓│┤╡╢╖╕╣║╗╝╜╛┐┘
|
||||
┌c─└┴┬├─┼╞╟╚╔╩╦╠═╬╧┬───1 Continuation will follow
|
||||
└d─╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀┘
|
||||
─e─αßΓπΣσμτΦΘΩδ∞φε∩────2 Continuations will follow
|
||||
f─≡±≥≤⌠⌡÷≈°∙·√ⁿ²■λ
|
||||
│ ││ │││└┤
|
||||
│ ││ │└┤ └───5 Continuations follow (and is negative)
|
||||
│ │└─┬┘ └─────5 Continuations follow (note: -1=λ┐┐┐┐┐)
|
||||
└───┬──┘ └────────4 Continuations follow
|
||||
└──────────────3 Continuations follow */
|
||||
|
||||
#define INVALID_CODEPOINT 0xfffd
|
||||
#define UTF16_MASK 0b1111110000000000
|
||||
#define UTF16_MOAR 0b1101100000000000 /* 0xD800..0xDBFF */
|
||||
#define UTF16_CONT 0b1101110000000000 /* 0xDC00..0xDBFF */
|
||||
|
||||
unsigned tpencode(char *buf, size_t size, wint_t c, bool32 awesome)
|
||||
paramsnonnull() libcesque;
|
||||
int tpdecode(const char *s, wint_t *out) paramsnonnull((1)) libcesque;
|
||||
unsigned getutf16(const char16_t *p, wint_t *wc);
|
||||
int pututf16(char16_t *s, size_t size, wint_t wc, bool awesome);
|
||||
int iswalnum(wint_t);
|
||||
int iswalpha(wint_t);
|
||||
int iswblank(wint_t);
|
||||
int iswcntrl(wint_t);
|
||||
int iswdigit(wint_t);
|
||||
int iswgraph(wint_t);
|
||||
int iswlower(wint_t);
|
||||
int iswspace(wint_t);
|
||||
int iswupper(wint_t);
|
||||
int iswxdigit(wint_t);
|
||||
int iswpunct(wint_t);
|
||||
int iswprint(wint_t);
|
||||
unsigned towlower(unsigned);
|
||||
unsigned towupper(unsigned);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
void *memset(void *, int, size_t) memcpyesque;
|
||||
void *memcpy(void *restrict, const void *restrict, size_t) memcpyesque;
|
||||
void *mempcpy(void *restrict, const void *restrict, size_t) memcpyesque;
|
||||
void *memccpy(void *restrict, const void *restrict, int, size_t) memcpyesque;
|
||||
void *memmove(void *, const void *, size_t) memcpyesque;
|
||||
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);
|
||||
char *strchr(const char *, int) strlenesque;
|
||||
char *index(const char *, int) strlenesque;
|
||||
void *memchr(const void *, int, size_t) strlenesque;
|
||||
char *strchrnul(const char *, int) strlenesque returnsnonnull;
|
||||
void *rawmemchr(const void *, int) strlenesque returnsnonnull;
|
||||
void bzero(void *, size_t) paramsnonnull() libcesque;
|
||||
size_t strlen16(const char16_t *) strlenesque;
|
||||
size_t strnlen16(const char16_t *, size_t) strlenesque;
|
||||
size_t strnlen16_s(const char16_t *, size_t);
|
||||
char16_t *strchr16(const char16_t *, int) strlenesque;
|
||||
void *memchr16(const void *, int, size_t) strlenesque;
|
||||
char16_t *strchrnul16(const char16_t *, int) strlenesque returnsnonnull;
|
||||
void *rawmemchr16(const void *, int) strlenesque returnsnonnull;
|
||||
size_t wcslen(const wchar_t *) strlenesque;
|
||||
size_t wcsnlen(const wchar_t *, size_t) strlenesque;
|
||||
size_t wcsnlen_s(const wchar_t *, size_t);
|
||||
wchar_t *wcschr(const wchar_t *, wchar_t) strlenesque;
|
||||
wchar_t *wmemchr(const wchar_t *, wchar_t, size_t) strlenesque;
|
||||
wchar_t *wcschrnul(const wchar_t *, wchar_t) strlenesque returnsnonnull;
|
||||
char *strstr(const char *, const char *) strlenesque;
|
||||
char16_t *strstr16(const char16_t *, const char16_t *) strlenesque;
|
||||
wchar_t *wcsstr(const wchar_t *, const wchar_t *) strlenesque;
|
||||
void *rawwmemchr(const void *, wchar_t) strlenesque returnsnonnull;
|
||||
int memcmp(const void *, const void *, size_t) strlenesque;
|
||||
int strcmp(const char *, const char *) strlenesque;
|
||||
int strncmp(const char *, const char *, size_t) strlenesque;
|
||||
int strcmp16(const char16_t *, const char16_t *) strlenesque;
|
||||
int strncmp16(const char16_t *, const char16_t *, size_t) strlenesque;
|
||||
int wcscmp(const wchar_t *, const wchar_t *) strlenesque;
|
||||
int wcsncmp(const wchar_t *, const wchar_t *, size_t) strlenesque;
|
||||
int wmemcmp(const wchar_t *, const wchar_t *, size_t) strlenesque;
|
||||
int strcasecmp(const char *, const char *) strlenesque;
|
||||
int strcasecmp16(const char16_t *, const char16_t *) strlenesque;
|
||||
int wcscasecmp(const wchar_t *, const wchar_t *) strlenesque;
|
||||
int strncasecmp(const char *, const char *, size_t) strlenesque;
|
||||
int strncasecmp16(const char16_t *, const char16_t *, size_t) strlenesque;
|
||||
int wcsncasecmp(const wchar_t *, const wchar_t *, size_t) strlenesque;
|
||||
char *strrchr(const char *, int) strlenesque;
|
||||
void *memrchr(const void *, int, size_t) strlenesque;
|
||||
char16_t *strrchr16(const char16_t *, int) strlenesque;
|
||||
void *memrchr16(const void *, int, size_t) strlenesque;
|
||||
wchar_t *wcsrchr(const wchar_t *, int) strlenesque;
|
||||
void *wmemrchr(const void *, wchar_t, size_t) strlenesque;
|
||||
char *strpbrk(const char *, const char *) strlenesque;
|
||||
char16_t *strpbrk16(const char16_t *, const char16_t *) strlenesque;
|
||||
wchar_t *wcspbrk(const wchar_t *, const wchar_t *) strlenesque;
|
||||
size_t strspn(const char *, const char *) strlenesque;
|
||||
size_t strspn16(const char16_t *, const char16_t *) strlenesque;
|
||||
size_t wcsspn(const wchar_t *, const wchar_t *) strlenesque;
|
||||
size_t strcspn(const char *, const char *) strlenesque;
|
||||
size_t strcspn16(const char16_t *, const char16_t *) strlenesque;
|
||||
size_t wcscspn(const wchar_t *, const wchar_t *) strlenesque;
|
||||
void *memfrob(void *, size_t) memcpyesque;
|
||||
int strcoll(const char *, const char *) strlenesque;
|
||||
char *strsep(char **, const char *) paramsnonnull();
|
||||
int strcmpzbw(const uint16_t *, const char *) strlenesque;
|
||||
int strcasecmpzbw(const uint16_t *, const char *) strlenesque;
|
||||
char *stpcpy(char *, const char *) memcpyesque;
|
||||
char *stpncpy(char *, const char *, size_t) memcpyesque;
|
||||
char *strcat(char *, const char *) memcpyesque;
|
||||
size_t strlcpy(char *, const char *, size_t);
|
||||
size_t strlcat(char *, const char *, size_t);
|
||||
char *strcpy(char *, const char *) memcpyesque;
|
||||
char16_t *strcpy16(char16_t *, const char16_t *) memcpyesque;
|
||||
char *strncat(char *, const char *, size_t) memcpyesque;
|
||||
char *strncpy(char *, const char *, size_t) memcpyesque;
|
||||
char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
|
||||
char *strtok(char *, const char *) paramsnonnull((2)) libcesque;
|
||||
char *strtok_r(char *, const char *, char **) paramsnonnull((2, 3));
|
||||
uint16_t *strcpyzbw(uint16_t *, const char *) memcpyesque;
|
||||
char *wstrtrunc(uint16_t *) memcpyesque;
|
||||
char *wstrntrunc(uint16_t *, size_t) memcpyesque;
|
||||
bool startswith(const char *, const char *) strlenesque;
|
||||
bool startswith16(const char16_t *, const char16_t *) strlenesque;
|
||||
bool wcsstartswith(const wchar_t *, const wchar_t *) strlenesque;
|
||||
bool endswith(const char *, const char *) strlenesque;
|
||||
bool endswith16(const char16_t *, const char16_t *) strlenesque;
|
||||
bool wcsendswith(const wchar_t *, const wchar_t *) strlenesque;
|
||||
const char *indexdoublenulstring(const char *, unsigned) strlenesque;
|
||||
int getkvlin(const char *, const char *const[]);
|
||||
void crc32init(uint32_t[hasatleast 256], uint32_t);
|
||||
wchar_t *wmemset(wchar_t *, wchar_t, size_t) memcpyesque;
|
||||
char16_t *memset16(char16_t *, char16_t, size_t) memcpyesque;
|
||||
compatfn wchar_t *wmemcpy(wchar_t *, const wchar_t *, size_t) memcpyesque;
|
||||
compatfn wchar_t *wmempcpy(wchar_t *, const wchar_t *, size_t) memcpyesque;
|
||||
compatfn wchar_t *wmemmove(wchar_t *, const wchar_t *, size_t) memcpyesque;
|
||||
|
||||
char *tinystrstr(const char *, const char *) strlenesque;
|
||||
char16_t *tinystrstr16(const char16_t *, const char16_t *) strlenesque;
|
||||
void *tinymemmem(const void *, size_t, const void *, size_t) strlenesque;
|
||||
|
||||
void *memtolower(void *p, size_t n);
|
||||
char *strntolower(char *s, size_t n);
|
||||
char *strtolower(char *s) paramsnonnull();
|
||||
char *strntoupper(char *s, size_t n);
|
||||
char *strtoupper(char *s) paramsnonnull();
|
||||
char *chomp(char *line);
|
||||
char16_t *chomp16(char16_t *line);
|
||||
wchar_t *wchomp(wchar_t *line);
|
||||
|
||||
/* gcc -Werror=stringop-truncation misunderstands strncpy() api */
|
||||
#define strncpy(DEST, SRC, N) _strncpy(DEST, SRC, N)
|
||||
|
||||
#define explicit_bzero(STR, BYTES) \
|
||||
do { \
|
||||
void *Str; \
|
||||
size_t Bytes; \
|
||||
asm volatile("call\texplicit_bzero" \
|
||||
: "=D"(Str), "=S"(Bytes) \
|
||||
: "0"(STR), "1"(BYTES) \
|
||||
: "rax", "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", \
|
||||
"cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); \
|
||||
} while (0)
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » multibyte ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
typedef unsigned mbstate_t;
|
||||
|
||||
size_t tprecode8to16(char16_t *, size_t, const char *);
|
||||
size_t tprecode16to8(char *, size_t, const char16_t *);
|
||||
int strcmp8to16(const char *, const char16_t *) strlenesque;
|
||||
int strncmp8to16(const char *, const char16_t *, size_t) strlenesque;
|
||||
int strcasecmp8to16(const char *, const char16_t *) strlenesque;
|
||||
int strncasecmp8to16(const char *, const char16_t *, size_t) strlenesque;
|
||||
int strcmp16to8(const char16_t *, const char *) strlenesque;
|
||||
int strncmp16to8(const char16_t *, const char *, size_t) strlenesque;
|
||||
int strcasecmp16to8(const char16_t *, const char *) strlenesque;
|
||||
int strncasecmp16to8(const char16_t *, const char *, size_t) strlenesque;
|
||||
wchar_t *wcsncpy(wchar_t *, const wchar_t *, size_t);
|
||||
int mbtowc(wchar_t *, const char *, size_t);
|
||||
size_t mbrtowc(wchar_t *, const char *, size_t, mbstate_t *);
|
||||
size_t mbsrtowcs(wchar_t *, const char **, size_t, mbstate_t *);
|
||||
size_t mbstowcs(wchar_t *, const char *, size_t);
|
||||
size_t wcstombs(char *, const wchar_t *, size_t);
|
||||
size_t wcsrtombs(char *, const wchar_t **, size_t, mbstate_t *);
|
||||
size_t wcrtomb(char *, wchar_t, mbstate_t *);
|
||||
int wctomb(char *, wchar_t);
|
||||
int wctob(wint_t);
|
||||
|
||||
size_t strclen(const char *) nosideeffect;
|
||||
size_t strnclen(const char *, size_t) nosideeffect;
|
||||
size_t strclen16(const char16_t *) nosideeffect;
|
||||
size_t strnclen16(const char16_t *, size_t) nosideeffect;
|
||||
|
||||
typedef unsigned wctype_t;
|
||||
wctype_t wctype(const char *name) strlenesque;
|
||||
int iswctype(wint_t c, wctype_t type) pureconst;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » hashing ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define SHA256_BLOCK_SIZE 32
|
||||
|
||||
struct Sha256Ctx {
|
||||
uint8_t data[64];
|
||||
uint32_t datalen;
|
||||
uint64_t bitlen;
|
||||
uint32_t state[8];
|
||||
};
|
||||
|
||||
uint32_t crc32_z(uint32_t, const void *, size_t);
|
||||
extern uint32_t (*const crc32c)(uint32_t, const void *, size_t) paramsnonnull();
|
||||
|
||||
void sha256_init(struct Sha256Ctx *);
|
||||
void sha256_update(struct Sha256Ctx *, const uint8_t *, size_t);
|
||||
void sha256_final(struct Sha256Ctx *, uint8_t *);
|
||||
|
||||
bool luhn(const char *);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » system ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
char *strsignal(int) returnsnonnull libcesque;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » hooks ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
extern int (*const hook$strcmp16)(const char16_t *, const char16_t *);
|
||||
extern int (*const hook$strncmp16)(const char16_t *, const char16_t *, size_t);
|
||||
extern int (*const hook$wcscmp)(const wchar_t *, const wchar_t *);
|
||||
extern int (*const hook$wcsncmp)(const wchar_t *, const wchar_t *, size_t);
|
||||
#define __STR_HOOK(SYMBOL) hook$##SYMBOL
|
||||
#else
|
||||
#define __STR_HOOK(SYMBOL) SYMBOL
|
||||
#endif /* GNUC && !ANSI */
|
||||
|
||||
/* TODO(jart): Use @gotpcrel. */
|
||||
#undef __STR_HOOK
|
||||
#define __STR_HOOK(SYMBOL) SYMBOL
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » generic typing ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#if __STDC_VERSION__ + 0 >= 201112
|
||||
|
||||
#define strstr(haystack, needle) \
|
||||
_Generic(*(haystack), wchar_t \
|
||||
: wcsstr, char16_t \
|
||||
: strstr16, default \
|
||||
: strstr)(haystack, needle)
|
||||
|
||||
#define strchr(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcschr, char16_t \
|
||||
: strchr16, default \
|
||||
: (isconstant(s) && isconstant(c) ? __builtin_strchr : _strchr))(s, \
|
||||
c)
|
||||
|
||||
#define strrchr(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcsrchr, char16_t \
|
||||
: strrchr16, default \
|
||||
: strrchr)(s, c)
|
||||
|
||||
#define strchrnul(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcschrnul, char16_t \
|
||||
: strchrnul16, default \
|
||||
: strchrnul)(s, c)
|
||||
|
||||
#define strnlen(s, n) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcsnlen, char16_t \
|
||||
: strnlen16, default \
|
||||
: strnlen)(s, n)
|
||||
|
||||
#define strnlen_s(s, n) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcsnlen_s, char16_t \
|
||||
: strnlen16_s, default \
|
||||
: strnlen_s)(s, n)
|
||||
|
||||
#define strpbrk(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcspbrk, char16_t \
|
||||
: strpbrk16, default \
|
||||
: strpbrk)(s, c)
|
||||
|
||||
#define strspn(s, c) \
|
||||
_Generic(*(s), wchar_t : wcsspn, char16_t : strspn16, default : strspn)(s, c)
|
||||
|
||||
#define strcspn(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcscspn, char16_t \
|
||||
: strcspn16, default \
|
||||
: strcspn)(s, c)
|
||||
|
||||
/* clang-format off */
|
||||
#define strcmp(s1, s2) \
|
||||
_Generic((s1)[0], \
|
||||
wchar_t: __STR_HOOK(wcscmp), \
|
||||
char16_t: _Generic(*(s2), \
|
||||
char: strcmp16to8, \
|
||||
default: __STR_HOOK(strcmp16)), \
|
||||
default: _Generic(*(s2), \
|
||||
char16_t: strcmp8to16, \
|
||||
default: strcmp))(s1, s2)
|
||||
/* clang-format on */
|
||||
|
||||
#define strncmp(s1, s2, n) \
|
||||
_Generic(*(s1), wchar_t \
|
||||
: __STR_HOOK(wcsncmp), char16_t \
|
||||
: _Generic(*(s2), char \
|
||||
: strncmp16to8, default \
|
||||
: __STR_HOOK(strncmp16)), \
|
||||
default \
|
||||
: _Generic(*(s2), char16_t \
|
||||
: strncmp8to16, default \
|
||||
: strncmp))(s1, s2, n)
|
||||
|
||||
#define strcasecmp(s1, s2) \
|
||||
_Generic(*(s1), wchar_t \
|
||||
: wcscasecmp, char16_t \
|
||||
: strcasecmp16, default \
|
||||
: strcasecmp)(s1, s2)
|
||||
|
||||
#define strncasecmp(s1, s2, n) \
|
||||
_Generic(*(s1), wchar_t \
|
||||
: wcsncasecmp, char16_t \
|
||||
: strncasecmp16, default \
|
||||
: strncasecmp)(s1, s2, n)
|
||||
|
||||
#define startswith(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcsstartswith, char16_t \
|
||||
: startswith16, default \
|
||||
: startswith)(s, c)
|
||||
|
||||
#define endswith(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcsendswith, char16_t \
|
||||
: endswith16, default \
|
||||
: endswith)(s, c)
|
||||
|
||||
#define strclen(s) \
|
||||
_Generic(*(s), wchar_t : wcslen, char16_t : strclen16, default : strclen)(s)
|
||||
|
||||
#define strnclen(s, n) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcslen, char16_t \
|
||||
: strnclen16, default \
|
||||
: strnclen)(s, n)
|
||||
|
||||
#define chomp(s) \
|
||||
_Generic(*(s), wchar_t : wchomp, char16_t : chomp16, default : chomp)(s)
|
||||
|
||||
#endif /* C11 */
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » optimizations ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
|
||||
#ifdef UNBLOAT_STDARG
|
||||
#define __STR_XMM_CLOBBER
|
||||
#else
|
||||
#define __STR_XMM_CLOBBER "xmm3",
|
||||
#endif
|
||||
|
||||
#define __memcpy_isgoodsize(SIZE) \
|
||||
(isconstant(SIZE) && ((SIZE) <= __BIGGEST_ALIGNMENT__ * 2 && \
|
||||
__builtin_popcount((unsigned)(SIZE)) == 1))
|
||||
|
||||
#define __memset_isgoodsize(SIZE) \
|
||||
(isconstant(SIZE) && (((SIZE) <= __BIGGEST_ALIGNMENT__ && \
|
||||
__builtin_popcount((unsigned)(SIZE)) == 1) || \
|
||||
((SIZE) % __BIGGEST_ALIGNMENT__ == 0 && \
|
||||
(SIZE) / __BIGGEST_ALIGNMENT__ <= 3)))
|
||||
|
||||
#define memcpy(DEST, SRC, SIZE) \
|
||||
(__memcpy_isgoodsize(SIZE) ? __builtin_memcpy(DEST, SRC, SIZE) \
|
||||
: __memcpy("_memcpy", DEST, SRC, SIZE))
|
||||
|
||||
#define memset(DEST, BYTE, SIZE) \
|
||||
(__memset_isgoodsize(SIZE) ? __builtin_memset(DEST, BYTE, SIZE) \
|
||||
: __memset(DEST, BYTE, SIZE))
|
||||
|
||||
#if defined(__STDC_HOSTED__) && (defined(__SSE2__) || defined(UNBLOAT_STDARG))
|
||||
|
||||
#define memmove(DEST, SRC, SIZE) __memcpy("_memmove", (DEST), (SRC), (SIZE))
|
||||
#define __memcpy(FN, DEST, SRC, SIZE) \
|
||||
({ \
|
||||
void *DeSt = (DEST); \
|
||||
const void *SrC = (SRC); \
|
||||
size_t SiZe = (SIZE); \
|
||||
asm("call\t" FN \
|
||||
: "=m"(*(char(*)[SiZe])(DeSt)) \
|
||||
: "D"(DeSt), "S"(SrC), "d"(SiZe), "m"(*(const char(*)[SiZe])(SrC)) \
|
||||
: __STR_XMM_CLOBBER "cc"); \
|
||||
DeSt; \
|
||||
})
|
||||
#define mempcpy(DEST, SRC, SIZE) \
|
||||
({ \
|
||||
size_t SIze = (SIZE); \
|
||||
(void *)((char *)memcpy((DEST), (SRC), SIze) + SIze); \
|
||||
})
|
||||
#define __memset(DEST, BYTE, SIZE) \
|
||||
({ \
|
||||
void *DeSt = (DEST); \
|
||||
size_t SiZe = (SIZE); \
|
||||
asm("call\t_memset" \
|
||||
: "=m"(*(char(*)[SiZe])(DeSt)) \
|
||||
: "D"(DeSt), "S"(BYTE), "d"(SiZe) \
|
||||
: __STR_XMM_CLOBBER "cc"); \
|
||||
DeSt; \
|
||||
})
|
||||
|
||||
#else /* hosted/sse2/unbloat */
|
||||
|
||||
#define memmove(DEST, SRC, SIZE) __memcpy((DEST), (SRC), (SIZE))
|
||||
#define mempcpy(DEST, SRC, SIZE) \
|
||||
({ \
|
||||
void *Rdi, *Dest = (DEST); \
|
||||
const void *Rsi, *Src = (SRC); \
|
||||
size_t SiZe = (SIZE); \
|
||||
size_t Rcx; \
|
||||
asm("rep movsb" \
|
||||
: "=D"(Rdi), "=S"(Rsi), "=D"(Rcx), "=m"(*(char(*)[SiZe])(Dest)) \
|
||||
: "0"(Dest), "1"(Src), "2"(SiZe), "m"(*(const char(*)[SiZe])(Src)) \
|
||||
: "cc"); \
|
||||
Rdi; \
|
||||
})
|
||||
#define __memcpy(FN, DEST, SRC, SIZE) \
|
||||
({ \
|
||||
void *Rdi, *Dest = (DEST); \
|
||||
const void *Rsi, *Src = (SRC); \
|
||||
size_t SiZe = (SIZE); \
|
||||
size_t Rcx; \
|
||||
asm("rep movsb" \
|
||||
: "=D"(Rdi), "=S"(Rsi), "=c"(Rcx), "=m"(*(char(*)[SiZe])(Dest)) \
|
||||
: "0"(Dest), "1"(Src), "2"(SiZe), "m"(*(const char(*)[SiZe])(Src)) \
|
||||
: "cc"); \
|
||||
Dest; \
|
||||
})
|
||||
#define __memset(DEST, BYTE, SIZE) \
|
||||
({ \
|
||||
void *Rdi, *Dest = (DEST); \
|
||||
size_t SiZe = (SIZE); \
|
||||
size_t Rcx; \
|
||||
asm("rep stosb" \
|
||||
: "=D"(Rdi), "=c"(Rcx), "=m"(*(char(*)[SiZe])(Dest)) \
|
||||
: "0"(Dest), "1"(SiZe), "S"(BYTE) \
|
||||
: "cc"); \
|
||||
Dest; \
|
||||
})
|
||||
|
||||
#endif /* hosted/sse2/unbloat */
|
||||
|
||||
#if __STDC_VERSION__ + 0 >= 201112
|
||||
#define strlen(s) \
|
||||
chooseexpr((typescompatible(typeof(s), const char[]) && \
|
||||
isconstant(((const char *)(s))[0])), \
|
||||
sizeof(s) - 1, \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcslen, char16_t \
|
||||
: strlen16, default \
|
||||
: _strlen)(s))
|
||||
#else
|
||||
#define strlen(s) \
|
||||
chooseexpr(isconstant(s) && typescompatible(typeof(s), const char[]), \
|
||||
__builtin_strlen(s), _strlen(s))
|
||||
#endif /* C11+ */
|
||||
|
||||
#define tpencode(BUF, SIZE, CH, AWESOME) __tpencode(BUF, SIZE, CH, AWESOME)
|
||||
#define pututf16(BUF, SIZE, CH, AWESOME) __pututf16(BUF, SIZE, CH, AWESOME)
|
||||
#define getutf16(BUF, CHPTR) __getutf16(BUF, CHPTR)
|
||||
#define tpdecode(S, OUT) __tpdecode(S, OUT)
|
||||
size_t _strlen(const char *s) asm("strlen") strlenesque;
|
||||
char *_strchr(const char *, int) asm("strchr") strlenesque;
|
||||
void *_memchr(const void *, int, size_t) asm("memchr") strlenesque;
|
||||
forceinline unsigned __tpencode(char *s, size_t size, wint_t wc,
|
||||
bool32 awesome) {
|
||||
unsigned char *p = (unsigned char *)s;
|
||||
if (size >= 1 && (0x00 <= wc && wc <= 0x7f)) {
|
||||
if (wc >= 32 || !awesome) {
|
||||
p[0] = (unsigned char)wc;
|
||||
return 1;
|
||||
} else if (size >= 2) {
|
||||
p[0] = 0xc0;
|
||||
p[1] = 0x80 | (unsigned char)wc;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
unsigned ax;
|
||||
asm("call\ttpencode"
|
||||
: "=a"(ax), "=m"(*(char(*)[size])s)
|
||||
: "D"(s), "S"(size), "d"(wc)
|
||||
: "cc");
|
||||
return ax;
|
||||
}
|
||||
forceinline int __tpdecode(const char *s, wint_t *out) {
|
||||
if (0 <= *s && *s <= 0x7f) {
|
||||
*out = *s;
|
||||
return 1;
|
||||
}
|
||||
int ax;
|
||||
asm("call\ttpdecode"
|
||||
: "=a"(ax), "=m"(*(char(*)[6])s)
|
||||
: "D"(s), "S"(out)
|
||||
: "cc");
|
||||
return ax;
|
||||
}
|
||||
forceinline int __pututf16(char16_t *s, size_t size, wint_t wc,
|
||||
bool32 awesome) {
|
||||
if (size >= 1 && (0x00 <= wc && wc <= 0xD7FF)) {
|
||||
if (wc >= 32 || !awesome) {
|
||||
s[0] = (char16_t)wc;
|
||||
return 1;
|
||||
} else if (size >= 2) {
|
||||
s[0] = 0xd800;
|
||||
s[1] = 0xdc00 | (char16_t)wc;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
int ax;
|
||||
asm("call\tpututf16"
|
||||
: "=a"(ax), "=m"(*(char16_t(*)[size])s)
|
||||
: "D"(s), "S"(size), "d"(wc)
|
||||
: "cc");
|
||||
return ax;
|
||||
}
|
||||
forceinline unsigned __getutf16(const char16_t *s, wint_t *wc) {
|
||||
if ((0x00 <= s[0] && s[0] <= 0xD7FF)) {
|
||||
*wc = s[0];
|
||||
return 1;
|
||||
}
|
||||
unsigned ax;
|
||||
asm("call\tgetutf16" : "=a"(ax), "=m"(*wc) : "D"(s), "S"(wc), "m"(*s) : "cc");
|
||||
return ax;
|
||||
}
|
||||
|
||||
/*
|
||||
* GCC has builtins for these, that only do things for literals. They
|
||||
* also cause the compiler to whine in a kafkaesque way when flags like
|
||||
* -Werror=shadow and -Werror=implicit-function-declaration are passed.
|
||||
*/
|
||||
#define isascii(c) isascii_(c)
|
||||
#define isspace(c) isspace_(c)
|
||||
#define isalpha(c) isalpha_(c)
|
||||
#define isdigit(c) isdigit_(c)
|
||||
#define isalnum(c) isalnum_(c)
|
||||
#define isxdigit(c) isxdigit_(c)
|
||||
#define isprint(c) isprint_(c)
|
||||
#define islower(c) islower_(c)
|
||||
#define isupper(c) isupper_(c)
|
||||
#define isblank(c) isblank_(c)
|
||||
#define iscntrl(c) iscntrl_(c)
|
||||
#define isgraph(c) isgraph_(c)
|
||||
#define tolower(c) tolower_(c)
|
||||
#define ispunct(c) ispunct_(c)
|
||||
#define toupper(c) toupper_(c)
|
||||
#define hextoint(c) hextoint_(c)
|
||||
#define DECLARE_CTYPE(NAME, EXPR) \
|
||||
pureconst forceinline nodebuginfo int NAME(int i) { \
|
||||
unsigned char c = (unsigned char)i; \
|
||||
return (EXPR); \
|
||||
}
|
||||
DECLARE_CTYPE(isascii_, 0 <= c && c <= 0x7f)
|
||||
DECLARE_CTYPE(isspace_, kCtype[c] & 0x01)
|
||||
DECLARE_CTYPE(isalpha_, kCtype[c] & 0x02)
|
||||
DECLARE_CTYPE(isdigit_, '0' <= c && c <= '9')
|
||||
DECLARE_CTYPE(isalnum_, kCtype[c] & 0x06)
|
||||
DECLARE_CTYPE(isxdigit_, kCtype[c] & 0x08)
|
||||
DECLARE_CTYPE(isprint_, kCtype[c] & 0x10)
|
||||
DECLARE_CTYPE(islower_, 'a' <= c && c <= 'z')
|
||||
DECLARE_CTYPE(isupper_, 'A' <= c && c <= 'Z')
|
||||
DECLARE_CTYPE(isblank_, kCtype[c] & 0x80)
|
||||
DECLARE_CTYPE(iscntrl_, !isprint_(c))
|
||||
DECLARE_CTYPE(isgraph_, isprint_(c) && (c) != ' ')
|
||||
DECLARE_CTYPE(tolower_, kToLower[c])
|
||||
DECLARE_CTYPE(ispunct_, isprint(c) && !(kCtype[c] & 0x07))
|
||||
DECLARE_CTYPE(toupper_, kToUpper[c])
|
||||
DECLARE_CTYPE(hextoint_, (c + 9 * (1 & (SAR(c, 6)))) & 0xf)
|
||||
#undef DECLARE_CTYPE
|
||||
#define iswalnum(c) iswalnum_(c)
|
||||
#define iswalpha(c) iswalpha_(c)
|
||||
#define iswblank(c) iswblank_(c)
|
||||
#define iswcntrl(c) iswcntrl_(c)
|
||||
#define iswdigit(c) iswdigit_(c)
|
||||
#define iswgraph(c) iswgraph_(c)
|
||||
#define iswlower(c) iswlower_(c)
|
||||
#define iswspace(c) iswspace_(c)
|
||||
#define iswupper(c) iswupper_(c)
|
||||
#define iswxdigit(c) iswxdigit_(c)
|
||||
#define iswpunct(c) iswpunct_(c)
|
||||
#define iswprint(c) iswprint_(c)
|
||||
#define towlower(c) towlower_(c)
|
||||
#define towupper(c) towupper_(c)
|
||||
#define DECLARE_WCTYPE(R, NAME, T, EXPR) \
|
||||
forceinline nodebuginfo R NAME(T c) { \
|
||||
return EXPR; \
|
||||
}
|
||||
DECLARE_WCTYPE(int, iswalnum_, wint_t, isascii(c) ? isalnum(c) : c)
|
||||
DECLARE_WCTYPE(int, iswalpha_, wint_t, isascii(c) ? isalpha(c) : c)
|
||||
DECLARE_WCTYPE(int, iswblank_, wint_t, isascii(c) ? isblank(c) : c)
|
||||
DECLARE_WCTYPE(int, iswcntrl_, wint_t, isascii(c) ? iscntrl(c) : c)
|
||||
DECLARE_WCTYPE(int, iswdigit_, wint_t, isascii(c) ? isdigit(c) : c)
|
||||
DECLARE_WCTYPE(int, iswgraph_, wint_t, isascii(c) ? isgraph(c) : c)
|
||||
DECLARE_WCTYPE(int, iswlower_, wint_t, isascii(c) ? islower(c) : c)
|
||||
DECLARE_WCTYPE(int, iswspace_, wint_t, isascii(c) ? isspace(c) : c)
|
||||
DECLARE_WCTYPE(int, iswupper_, wint_t, isascii(c) ? isupper(c) : c)
|
||||
DECLARE_WCTYPE(int, iswxdigit_, wint_t, isascii(c) ? isxdigit(c) : c)
|
||||
DECLARE_WCTYPE(int, iswpunct_, wint_t, !isascii(c) || ispunct(c))
|
||||
DECLARE_WCTYPE(int, iswprint_, wint_t, !isascii(c) || isprint(c))
|
||||
DECLARE_WCTYPE(unsigned, towlower_, unsigned, isascii(c) ? tolower(c) : c)
|
||||
DECLARE_WCTYPE(unsigned, towupper_, unsigned, isascii(c) ? toupper(c) : c)
|
||||
#undef DECLARE_WCTYPE
|
||||
|
||||
#endif /* __GNUC__ && !__STRICT_ANSI__ */
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_STR_H_ */
|
55
libc/str/str.mk
Normal file
55
libc/str/str.mk
Normal file
|
@ -0,0 +1,55 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
PKGS += LIBC_STR
|
||||
|
||||
LIBC_STR_ARTIFACTS += LIBC_STR_A
|
||||
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_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))
|
||||
|
||||
LIBC_STR_A_SRCS = \
|
||||
$(LIBC_STR_A_SRCS_A) \
|
||||
$(LIBC_STR_A_SRCS_S) \
|
||||
$(LIBC_STR_A_SRCS_C)
|
||||
|
||||
LIBC_STR_A_OBJS = \
|
||||
$(LIBC_STR_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(LIBC_STR_A_SRCS_A:%.s=o/$(MODE)/%.o) \
|
||||
$(LIBC_STR_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(LIBC_STR_A_SRCS_C:%.c=o/$(MODE)/%.o)
|
||||
|
||||
LIBC_STR_A_CHECKS = \
|
||||
$(LIBC_STR_A).pkg \
|
||||
$(LIBC_STR_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
LIBC_STR_A_DIRECTDEPS = \
|
||||
LIBC_STUBS \
|
||||
LIBC_NEXGEN32E
|
||||
|
||||
LIBC_STR_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_STR_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(LIBC_STR_A): libc/str/ \
|
||||
$(LIBC_STR_A).pkg \
|
||||
$(LIBC_STR_A_OBJS)
|
||||
|
||||
$(LIBC_STR_A).pkg: \
|
||||
$(LIBC_STR_A_OBJS) \
|
||||
$(foreach x,$(LIBC_STR_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
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_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))
|
||||
LIBC_STR_TESTS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_TESTS))
|
||||
$(LIBC_STR_OBJS): $(BUILD_FILES) libc/str/str.mk
|
||||
|
||||
.PHONY: o/$(MODE)/libc/str
|
||||
o/$(MODE)/libc/str: $(LIBC_STR_CHECKS)
|
32
libc/str/strcasecmp8to16.c
Normal file
32
libc/str/strcasecmp8to16.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/strcmp8to16i.h"
|
||||
|
||||
/**
|
||||
* Compares UTF-8 and UTF-16 strings, ignoring case.
|
||||
*/
|
||||
int strcasecmp8to16(const char *s1, const char16_t *s2) {
|
||||
return strcmp8to16i(s1, s2, -1ul, towlower);
|
||||
}
|
||||
|
||||
int strcasecmp16to8(const char16_t *s1, const char *s2) {
|
||||
return -strcasecmp8to16(s2, s1);
|
||||
}
|
30
libc/str/strcat.c
Normal file
30
libc/str/strcat.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Appends 𝑠 to 𝑑.
|
||||
*
|
||||
* @param 𝑑 is a NUL-terminated string buffer
|
||||
* @param 𝑠 is a NUL-terminated string
|
||||
* @return 𝑑
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *strcat(char *d, const char *s) { return strcpy(d + strlen(d), s); }
|
39
libc/str/strclen.c
Normal file
39
libc/str/strclen.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns number of characters in UTF-8 string.
|
||||
*/
|
||||
size_t(strclen)(const char *s) { return strnclen(s, -1ull); }
|
||||
|
||||
noinline size_t(strnclen)(const char *s, size_t n) {
|
||||
const unsigned char *p = (const unsigned char *)s;
|
||||
size_t l = 0;
|
||||
if (n) {
|
||||
while (*p && n && iscont(*p)) ++p, --n;
|
||||
while (*p) {
|
||||
if (!iscont(*p++)) l++;
|
||||
if (!--n) break;
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
36
libc/str/strclen16.c
Normal file
36
libc/str/strclen16.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns number of characters in UTF-16 or UCS-2 string.
|
||||
*/
|
||||
size_t strclen16(const char16_t *s) { return strnclen16(s, -1ull); }
|
||||
|
||||
noinline size_t strnclen16(const char16_t *p, size_t n) {
|
||||
size_t l = 0;
|
||||
if (n) {
|
||||
while (*p) {
|
||||
if ((*p++ & UTF16_MASK) != UTF16_CONT) l++;
|
||||
if (!--n) break;
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
34
libc/str/strcmp8to16.c
Normal file
34
libc/str/strcmp8to16.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/strcmp8to16i.h"
|
||||
|
||||
forceinline unsigned identity32u(unsigned x) { return x; }
|
||||
|
||||
/**
|
||||
* Compares UTF-8 and UTF-16 strings.
|
||||
*/
|
||||
int strcmp8to16(const char *s1, const char16_t *s2) {
|
||||
return strcmp8to16i(s1, s2, -1ul, identity32u);
|
||||
}
|
||||
|
||||
int strcmp16to8(const char16_t *s1, const char *s2) {
|
||||
return -strcmp8to16(s2, s1);
|
||||
}
|
24
libc/str/strcmp8to16i.h
Normal file
24
libc/str/strcmp8to16i.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_STRCMP8TO16I_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_STRCMP8TO16I_H_
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/str/str.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
forceinline int strcmp8to16i(const char *s1, const char16_t *s2, size_t n,
|
||||
unsigned xlat(unsigned)) {
|
||||
int res = 0;
|
||||
if (n) {
|
||||
do {
|
||||
wint_t wc1, wc2;
|
||||
s1 += abs(tpdecode(s1, &wc1));
|
||||
s2 += abs(getutf16(s2, &wc2));
|
||||
if ((res = xlat(wc1) - xlat(wc2)) || !wc1) break;
|
||||
} while (n == -1ul || --n);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_STRCMP8TO16I_H_ */
|
36
libc/str/strcpy.c
Normal file
36
libc/str/strcpy.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Copies bytes from 𝑠 to 𝑑 until a NUL is encountered.
|
||||
*
|
||||
* @param 𝑑 is destination memory
|
||||
* @param 𝑠 is a NUL-terminated string
|
||||
* @note 𝑑 and 𝑠 can't overlap
|
||||
* @return original dest
|
||||
* @see memccpy()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *strcpy(char *d, const char *s) {
|
||||
memccpy(d, s, '\0', SIZE_MAX);
|
||||
return d;
|
||||
}
|
33
libc/str/strcpy16.c
Normal file
33
libc/str/strcpy16.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Copies NUL-terminated UCS-2 or UTF-16 string.
|
||||
*
|
||||
* DEST and SRC must not overlap unless DEST ≤ SRC.
|
||||
*
|
||||
* @param dest is destination memory
|
||||
* @param src is a NUL-terminated 16-bit string
|
||||
* @return original dest
|
||||
*/
|
||||
char16_t *strcpy16(char16_t *dest, const char16_t *src) {
|
||||
return memcpy(dest, src, (strlen16(src) + 1) << 1);
|
||||
}
|
41
libc/str/strlcat.c
Normal file
41
libc/str/strlcat.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Appends string SRC to DEST, the BSD way.
|
||||
*
|
||||
* @param dest is a buffer holding a NUL-terminated string
|
||||
* @param src is a NUL-terminated string
|
||||
* @param size is byte capacity of dest
|
||||
* @return strlen(dest) + strlen(src)
|
||||
* @note dest and src can't overlap
|
||||
* @see strncat()
|
||||
*/
|
||||
size_t strlcat(char *dest, const char *src, size_t size) {
|
||||
size_t destlen = strnlen(dest, size);
|
||||
size_t srclen = strlen(src);
|
||||
if (size) {
|
||||
memcpy(&dest[destlen], src, min(srclen, size - destlen));
|
||||
dest[min(destlen + srclen, size - 1)] = '\0';
|
||||
}
|
||||
return destlen + srclen;
|
||||
}
|
42
libc/str/strlcpy.c
Normal file
42
libc/str/strlcpy.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Copies string, the BSD way.
|
||||
*
|
||||
* @param d is buffer which needn't be initialized
|
||||
* @param s is a NUL-terminated string
|
||||
* @param n is byte capacity of d
|
||||
* @return strlen(s)
|
||||
* @note d and s can't overlap
|
||||
* @note we prefer memccpy()
|
||||
*/
|
||||
size_t strlcpy(char *d, const char *s, size_t n) {
|
||||
size_t slen, actual;
|
||||
slen = strlen(s);
|
||||
if (n) {
|
||||
actual = min(n, slen);
|
||||
memcpy(d, s, actual);
|
||||
d[actual] = '\0';
|
||||
}
|
||||
return slen;
|
||||
}
|
33
libc/str/strncasecmp8to16.c
Normal file
33
libc/str/strncasecmp8to16.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/strcmp8to16i.h"
|
||||
|
||||
/**
|
||||
* Compares UTF-8 and UTF-16 strings, ignoring case, with limit.
|
||||
*/
|
||||
int strncasecmp8to16(const char *s1, const char16_t *s2, size_t n) {
|
||||
assume(n != -1ul);
|
||||
return strcmp8to16i(s1, s2, n, towlower);
|
||||
}
|
||||
|
||||
int strncasecmp16to8(const char16_t *s1, const char *s2, size_t n) {
|
||||
return -strncasecmp8to16(s2, s1, n);
|
||||
}
|
40
libc/str/strncat.c
Normal file
40
libc/str/strncat.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Appends at most 𝑛 bytes from 𝑠 to 𝑑.
|
||||
*
|
||||
* @param 𝑑 is both a NUL-terminated string and a buffer, needing
|
||||
* an ARRAYLEN() of at least strlen(𝑑)+strnlen(𝑠,𝑛)+1
|
||||
* @param 𝑠 is character array which needn't be NUL-terminated
|
||||
* @param 𝑛 is maximum number of characters from s to copy
|
||||
* @return 𝑑
|
||||
* @note 𝑑 and 𝑠 can't overlap
|
||||
* @asyncsignaslenafe
|
||||
*/
|
||||
char *strncat(char *d, const char *s, size_t n) {
|
||||
size_t o;
|
||||
if (!memccpy(d + (o = strlen(d)), s, '\0', n)) {
|
||||
d[o + n] = '\0';
|
||||
}
|
||||
return d;
|
||||
}
|
35
libc/str/strncmp8to16.c
Normal file
35
libc/str/strncmp8to16.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/strcmp8to16i.h"
|
||||
|
||||
forceinline unsigned identity32u(unsigned x) { return x; }
|
||||
|
||||
/**
|
||||
* Compares UTF-8 and UTF-16 strings, with limit.
|
||||
*/
|
||||
int strncmp8to16(const char *s1, const char16_t *s2, size_t n) {
|
||||
assume(n != -1ul);
|
||||
return strcmp8to16i(s1, s2, n, identity32u);
|
||||
}
|
||||
|
||||
int strncmp16to8(const char16_t *s1, const char *s2, size_t n) {
|
||||
return -strncmp8to16(s2, s1, n);
|
||||
}
|
42
libc/str/strncpy.c
Normal file
42
libc/str/strncpy.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Prepares static search buffer.
|
||||
*
|
||||
* 1. If SRC is too long, it's truncated and *not* NUL-terminated.
|
||||
* 2. If SRC is too short, the remainder is zero-filled.
|
||||
*
|
||||
* Please note this function isn't designed to prevent untrustworthy
|
||||
* data from modifying memory without authorization; the memccpy()
|
||||
* function can be used for that purpose.
|
||||
*
|
||||
* @return dest
|
||||
* @see stpncpy(), memccpy()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *(strncpy)(char *dest, const char *src, size_t stride) {
|
||||
char *p;
|
||||
if ((p = memccpy(dest, src, '\0', stride))) {
|
||||
memset(p, 0, dest + stride - p);
|
||||
}
|
||||
return dest;
|
||||
}
|
35
libc/str/strntolower.c
Normal file
35
libc/str/strntolower.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
char *strntolower(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;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
35
libc/str/strntoupper.c
Normal file
35
libc/str/strntoupper.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
30
libc/str/strrchr.c
Normal file
30
libc/str/strrchr.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Searches for last instance of character in string.
|
||||
*
|
||||
* @param s is NUL-terminated string to search
|
||||
* @param c is treated as unsigned char
|
||||
* @return address of last c in s, or NULL if not found
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *(strrchr)(const char *s, int c) { return memrchr(s, c, strlen(s)); }
|
32
libc/str/strrchr16.c
Normal file
32
libc/str/strrchr16.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Searches for last instance of char16_t in string.
|
||||
*
|
||||
* @param s is NUL-terminated char16_t string to search
|
||||
* @param c is treated as char16_t
|
||||
* @return address of last c in s, or NULL if not found
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char16_t *strrchr16(const char16_t *s, int c) {
|
||||
return memrchr16(s, c, strlen16(s));
|
||||
}
|
49
libc/str/strsep.c
Normal file
49
libc/str/strsep.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Tokenizes string.
|
||||
*
|
||||
* This works by mutating the caller's pointer and the string itself.
|
||||
* The returned value is the next available token, or NULL if we've
|
||||
* reached the end. Upon each call, *str is updated to point past the
|
||||
* terminator we inserted. Multiple delimiter bytes may be passed, which
|
||||
* are treated as a set of characters, not a substring.
|
||||
*
|
||||
* @param str on first call points to var holding string to be tokenized
|
||||
* and is used by this function to track state on subsequent calls
|
||||
* @param delim is a set of characters that constitute separators
|
||||
* @return next token or NULL when we've reached the end or *str==NULL
|
||||
* @note unlike strtok() this does empty tokens and is re-entrant
|
||||
*/
|
||||
char *strsep(char **str, const char *delim) {
|
||||
char *token = *str;
|
||||
if (token) {
|
||||
size_t i = strcspn(token, delim);
|
||||
char *next = NULL;
|
||||
if (token[i]) {
|
||||
token[i] = '\0';
|
||||
next = &token[i + 1];
|
||||
}
|
||||
*str = next;
|
||||
}
|
||||
return token;
|
||||
}
|
42
libc/str/strsignal.c
Normal file
42
libc/str/strsignal.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static const char kSig[4] = "SIG";
|
||||
static const char kUnknown[8] = "UNKNOWN";
|
||||
alignas(1) static const char kStrSignals[][8] = {
|
||||
"EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "BUS",
|
||||
"FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM",
|
||||
"STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "URG",
|
||||
"XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "IO", "PWR", "SYS"};
|
||||
|
||||
static char g_strsignal[4 + 8];
|
||||
|
||||
char *strsignal(int sig) {
|
||||
if (0 <= sig && (unsigned)sig < ARRAYLEN(kStrSignals)) {
|
||||
memcpy(g_strsignal, kSig, 4);
|
||||
memcpy(&g_strsignal[3], kStrSignals[sig], 8);
|
||||
} else {
|
||||
memcpy(g_strsignal, &kUnknown, 8);
|
||||
}
|
||||
return g_strsignal;
|
||||
}
|
57
libc/str/strstr.c
Normal file
57
libc/str/strstr.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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Searches for substring.
|
||||
*
|
||||
* @param haystack is the search area, as a NUL-terminated string
|
||||
* @param needle is the desired substring, also NUL-terminated
|
||||
* @return pointer to first substring within haystack, or NULL
|
||||
* @asyncsignalsafe
|
||||
* @see memmem()
|
||||
*/
|
||||
char *(strstr)(const char *haystack, const char *needle) {
|
||||
if (needle[0]) {
|
||||
if (needle[1]) {
|
||||
if (!((intptr_t)needle & 0xf) && X86_HAVE(SSE4_2) && !IsTiny()) {
|
||||
return strstr$sse42(haystack, needle);
|
||||
} else {
|
||||
size_t needlelen;
|
||||
alignas(16) char needle2[64];
|
||||
needlelen = strlen(needle);
|
||||
if (needlelen < 64 && X86_HAVE(SSE4_2) && !IsTiny()) {
|
||||
memcpy(needle2, needle, (needlelen + 1) * sizeof(char));
|
||||
return strstr$sse42(haystack, needle2);
|
||||
} else {
|
||||
return tinystrstr(haystack, needle);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return strchr(haystack, needle[0]);
|
||||
}
|
||||
} else {
|
||||
return haystack;
|
||||
}
|
||||
}
|
38
libc/str/strstr16.c
Normal file
38
libc/str/strstr16.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#undef memmem
|
||||
#undef strlen
|
||||
#undef strstr
|
||||
#undef strchr
|
||||
|
||||
#define char char16_t
|
||||
#define memmem memmem16
|
||||
#define strlen strlen16
|
||||
#define strstr strstr16
|
||||
#define strchr strchr16
|
||||
#define strstr$sse42 strstr16$sse42
|
||||
#define tinystrstr tinystrstr16
|
||||
|
||||
#include "libc/str/strstr.c"
|
34
libc/str/strtok.c
Normal file
34
libc/str/strtok.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Extracts non-empty tokens from string.
|
||||
*
|
||||
* @param s is mutated and should be NULL on subsequent calls
|
||||
* @param sep is a NUL-terminated set of bytes to consider separators
|
||||
* @return pointer to next token or NULL for end
|
||||
* @see strtok_r() and strsep() for superior functions
|
||||
* @notasyncsignalsafe
|
||||
*/
|
||||
char *strtok(char *s, const char *sep) {
|
||||
static char *state;
|
||||
return strtok_r(s, sep, &state);
|
||||
}
|
54
libc/str/strtok_r.c
Normal file
54
libc/str/strtok_r.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Extracts non-empty tokens from string.
|
||||
*
|
||||
* @param s is mutated and should be NULL on subsequent calls
|
||||
* @param sep is a NUL-terminated set of bytes to consider separators
|
||||
* @param state tracks progress between calls
|
||||
* @return pointer to next token or NULL for end
|
||||
* @see strsep() which is similar
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *strtok_r(char *s, const char *sep, char **state) {
|
||||
if (!s) {
|
||||
s = *state;
|
||||
if (!s) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
size_t leadingseps = strspn(s, sep);
|
||||
s += leadingseps;
|
||||
if (*s) {
|
||||
size_t tokenlen = strcspn(s, sep);
|
||||
if (s[tokenlen]) {
|
||||
s[tokenlen] = '\0';
|
||||
*state = &s[tokenlen + 1];
|
||||
return s;
|
||||
} else if (tokenlen) {
|
||||
s[tokenlen] = '\0';
|
||||
*state = NULL;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return (*state = NULL);
|
||||
}
|
32
libc/str/tinymemmem.c
Normal file
32
libc/str/tinymemmem.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tinymemmem.h"
|
||||
|
||||
/**
|
||||
* Naïve substring search implementation.
|
||||
* @see libc/alg/memmem.c
|
||||
*/
|
||||
void *tinymemmem(const void *haystk, size_t haystksize, const void *needle,
|
||||
size_t needlesize) {
|
||||
return (/*unconst*/ void *)tinymemmemi(
|
||||
(const unsigned char *)haystk, haystksize, (const unsigned char *)needle,
|
||||
needlesize);
|
||||
}
|
24
libc/str/tinymemmem.h
Normal file
24
libc/str/tinymemmem.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_
|
||||
#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 = haystk;
|
||||
const char *pe = p + 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 /* COSMOPOLITAN_LIBC_STR_TINYMEMMEM_H_ */
|
30
libc/str/tinystrstr.c
Normal file
30
libc/str/tinystrstr.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/tinystrstr.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);
|
||||
}
|
26
libc/str/tinystrstr.h
Normal file
26
libc/str/tinystrstr.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_
|
||||
#include "libc/str/str.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#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 /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_ */
|
30
libc/str/tinystrstr16.c
Normal file
30
libc/str/tinystrstr16.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/tinystrstr.h"
|
||||
|
||||
/**
|
||||
* Naïve substring search implementation.
|
||||
* @see libc/str/strstr.c
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char16_t *tinystrstr16(const char16_t *haystack, const char16_t *needle) {
|
||||
return (/*unconst*/ char16_t *)tinystrstr(haystack, needle);
|
||||
}
|
38
libc/str/tpdecode.ncabi.c
Normal file
38
libc/str/tpdecode.ncabi.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpdecodecb.h"
|
||||
|
||||
forceinline int getbyte(void *arg, uint32_t i) {
|
||||
return ((const unsigned char *)arg)[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Thompson-Pike Varint Decoder.
|
||||
*
|
||||
* @param s is a NUL-terminated string
|
||||
* @return number of bytes successfully consumed or -1 w/ errno
|
||||
* @note synchronization is performed
|
||||
* @see libc/str/tpdecodecb.h (for implementation)
|
||||
*/
|
||||
int(tpdecode)(const char *s, wint_t *out) {
|
||||
return tpdecodecb(out, (unsigned char)s[0], getbyte, (void *)s);
|
||||
}
|
56
libc/str/tpdecodecb.h
Normal file
56
libc/str/tpdecodecb.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef COSMOPOLITAN_LIBC_STR_TPDECODECB_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_TPDECODECB_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
* Generic Thompson-Pike Varint Decoder.
|
||||
* @return number of bytes successfully consumed or -1 w/ errno
|
||||
* @note synchronization is performed
|
||||
*/
|
||||
forceinline int tpdecodecb(wint_t *out, int first,
|
||||
int get(void *arg, uint32_t i), void *arg) {
|
||||
uint32_t wc, cb, need, msb, i = 1;
|
||||
if ((wc = first) == -1) return -1;
|
||||
while ((wc & 0b11000000) == 0b10000000) {
|
||||
if ((wc = get(arg, i++)) == -1) return -1;
|
||||
}
|
||||
if ((wc & 0b10000000) == 0b10000000) {
|
||||
asm("bsr\t%1,%0" : "=r"(msb) : "rm"(~wc & 0xff) : "cc");
|
||||
if (!msb) msb = 1;
|
||||
need = 7 - msb;
|
||||
wc &= ((1u << msb) - 1) | 0b00000011;
|
||||
for (uint32_t j = 1; j < need; ++j) {
|
||||
if ((cb = get(arg, i++)) == -1) return -1;
|
||||
if ((cb & 0b11000000) == 0b10000000) {
|
||||
wc = wc << 6 | (cb & 0b00111111);
|
||||
} else {
|
||||
if (out) *out = u'<EFBFBD>';
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (out) *out = (wint_t)wc;
|
||||
return i;
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_TPDECODECB_H_ */
|
71
libc/str/tpenc.S
Normal file
71
libc/str/tpenc.S
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ Encodes Thompson-Pike varint.
|
||||
/
|
||||
/ @param edi is int to encode
|
||||
/ @return rax is word-encoded byte buffer
|
||||
/ @clob edi,rax,flags
|
||||
/ @note invented on a napkin in a new jersey diner
|
||||
tpenc: .leafprologue
|
||||
.profilable
|
||||
push %rcx
|
||||
push %rdx
|
||||
mov %edi,%edi
|
||||
xor %eax,%eax
|
||||
cmp $127,%edi
|
||||
jbe 3f
|
||||
bsr %edi,%ecx
|
||||
ezlea kTpenc,dx
|
||||
mov -7*(1+1)(%rdx,%rcx,2),%ecx
|
||||
1: mov %edi,%edx
|
||||
shr $6,%edi
|
||||
and $0b00111111,%dl
|
||||
or $0b10000000,%al
|
||||
or %dl,%al
|
||||
shl $8,%rax
|
||||
dec %cl
|
||||
jnz 1b
|
||||
2: or %ch,%al
|
||||
3: or %rdi,%rax
|
||||
pop %rdx
|
||||
pop %rcx
|
||||
.leafepilogue
|
||||
.endfn tpenc,globl
|
||||
|
||||
.rodata
|
||||
kTpenc: .rept 4 # MSB≤10 (0x7FF)
|
||||
.byte 1,0b11000000 # len,mark
|
||||
.endr
|
||||
.rept 5 # MSB≤15 (0xFFFF)
|
||||
.byte 2,0b11100000 # len,mark
|
||||
.endr
|
||||
.rept 5 # MSB≤20 (0x1FFFFF)
|
||||
.byte 3,0b11110000 # len,mark
|
||||
.endr
|
||||
.rept 5 # MSB≤25 (0x3FFFFFF)
|
||||
.byte 4,0b11111000 # len,mark
|
||||
.endr
|
||||
.rept 6 # MSB≤31 (0xffffffff)
|
||||
.byte 5,0b11111100 # len,mark
|
||||
.endr
|
||||
.endobj kTpenc
|
23
libc/str/tpenc.h
Normal file
23
libc/str/tpenc.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_TPENC_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_TPENC_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
uint64_t tpenc(int32_t) pureconst;
|
||||
uint64_t tpenc2(int32_t) pureconst;
|
||||
|
||||
#define tpenc(CODE) \
|
||||
({ \
|
||||
unsigned long Buf; \
|
||||
int Di, Code = (CODE); \
|
||||
if (0 <= Code && Code <= 127) { \
|
||||
Buf = Code; \
|
||||
} else { \
|
||||
asm("call\ttpenc" : "=a"(Buf), "=D"(Di) : "1"(CODE) : "cc"); \
|
||||
} \
|
||||
Buf; \
|
||||
})
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_TPENC_H_ */
|
55
libc/str/tpencode.ncabi.c
Normal file
55
libc/str/tpencode.ncabi.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Thompson-Pike Varint Encoder.
|
||||
*
|
||||
* Implementation Details: The header macro should ensure this function
|
||||
* is only called for non-ASCII, or DCE'd entirely. In addition to that
|
||||
* this function makes a promise to not clobber any registers but %rax.
|
||||
*
|
||||
* @param buf is what ch gets encoded to
|
||||
* @param size is the number of bytes available in buf
|
||||
* @param ch is a 32-bit integer
|
||||
* @param awesome mode enables numbers the IETF unilaterally banned
|
||||
* @return number of bytes written
|
||||
* @note this encoding was designed on a napkin in a new jersey diner
|
||||
*/
|
||||
unsigned(tpencode)(char *buf, size_t size, wint_t ch, bool32 awesome) {
|
||||
unsigned char *p = (unsigned char *)buf;
|
||||
if ((0 <= ch && ch < 32) && awesome && size >= 2) {
|
||||
p[0] = 0xc0;
|
||||
p[1] = 0x80 | (unsigned char)ch;
|
||||
return 2;
|
||||
}
|
||||
struct TpEncode op = UseTpDecoderRing(ch);
|
||||
size_t i = op.len;
|
||||
if (op.len <= size) {
|
||||
for (;;) {
|
||||
p[--i] = (unsigned char)(0b10000000 | (ch & 0b00111111));
|
||||
if (!i) break;
|
||||
ch >>= 6;
|
||||
}
|
||||
p[0] = op.mark | (unsigned char)ch;
|
||||
}
|
||||
return op.len;
|
||||
}
|
47
libc/str/tprecode16to8.c
Normal file
47
libc/str/tprecode16to8.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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Transcodes UTF-16 to UTF-8.
|
||||
*
|
||||
* @param dst is output buffer
|
||||
* @param dstsize is bytes in dst
|
||||
* @param src is NUL-terminated UTF-16 input string
|
||||
* @return number of bytes written excluding NUL
|
||||
*/
|
||||
size_t tprecode16to8(char *dst, size_t dstsize, const char16_t *src) {
|
||||
size_t i = 0;
|
||||
if (dstsize) {
|
||||
for (;;) {
|
||||
wint_t wc;
|
||||
src += abs(getutf16(src, &wc));
|
||||
if (!wc || dstsize == 1) {
|
||||
dst[i] = '\0';
|
||||
break;
|
||||
}
|
||||
size_t got = abs(tpencode(&dst[i], dstsize, wc, false));
|
||||
dstsize -= got;
|
||||
i += got;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
47
libc/str/tprecode8to16.c
Normal file
47
libc/str/tprecode8to16.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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Transcodes UTF-8 to UTF-16.
|
||||
*
|
||||
* @param dst is output buffer
|
||||
* @param dstsize is shorts in dst
|
||||
* @param src is NUL-terminated UTF-8 input string
|
||||
* @return number of shorts written excluding NUL
|
||||
*/
|
||||
size_t tprecode8to16(char16_t *dst, size_t dstsize, const char *src) {
|
||||
size_t i = 0;
|
||||
if (dstsize) {
|
||||
for (;;) {
|
||||
wint_t wc;
|
||||
src += abs(tpdecode(src, &wc));
|
||||
if (!wc || dstsize == 1) {
|
||||
dst[i] = u'\0';
|
||||
break;
|
||||
}
|
||||
size_t got = abs(pututf16(&dst[i], dstsize, wc, false));
|
||||
dstsize -= got;
|
||||
i += got;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
260
libc/str/undeflate.c
Normal file
260
libc/str/undeflate.c
Normal file
|
@ -0,0 +1,260 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/intrin/repmovsb.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nexgen32e/kompressor.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/undeflate.h"
|
||||
|
||||
#define kDeflateCompressionTypeNone 0b00
|
||||
#define kDeflateCompressionTypeFixedHuffman 0b01
|
||||
#define kDeflateCompressionTypeDynamicHuffman 0b10
|
||||
|
||||
#define kDeflateCodeLengthCopyPrevious3To6Times 16
|
||||
#define kDeflateCodeLengthRepeatZero3To10Times 17
|
||||
#define kDeflateCodeLengthRepeatZero11To138Times 18
|
||||
|
||||
#define CONSUME(BITS) \
|
||||
hold.word >>= BITS; \
|
||||
hold.bits -= BITS
|
||||
|
||||
#define MOAR(BITS) \
|
||||
while (hold.bits < BITS) { \
|
||||
al = *ip++; \
|
||||
hold.word |= (size_t)al << hold.bits; \
|
||||
hold.bits += 8; \
|
||||
}
|
||||
|
||||
struct DeflateHold {
|
||||
size_t word;
|
||||
size_t bits;
|
||||
};
|
||||
|
||||
static const struct DeflateConsts {
|
||||
uint16_t lenbase[32];
|
||||
uint16_t distbase[32];
|
||||
uint8_t lenbits[32];
|
||||
uint8_t distbits[32];
|
||||
uint8_t orders[19];
|
||||
struct RlDecode lensrl[6];
|
||||
} kDeflate = {
|
||||
{3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
|
||||
31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258},
|
||||
{1, 2, 3, 4, 5, 7, 9, 13, 17, 25,
|
||||
33, 49, 65, 97, 129, 193, 257, 385, 513, 769,
|
||||
1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2,
|
||||
2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5},
|
||||
{0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6,
|
||||
6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13},
|
||||
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15},
|
||||
{{144, 8}, {112, 9}, {24, 7}, {8, 8}, {32, 5}, {0, 0}},
|
||||
};
|
||||
|
||||
static uint32_t undeflatetree(struct DeflateState *ds, uint32_t *tree,
|
||||
const uint8_t *lens, size_t symcount) {
|
||||
size_t i, len;
|
||||
uint32_t code, slot;
|
||||
uint16_t codes[16], first[16], counts[16];
|
||||
memset(counts, 0, sizeof(counts));
|
||||
for (i = 0; i < symcount; i++) {
|
||||
counts[lens[i]]++;
|
||||
}
|
||||
codes[0] = 0;
|
||||
first[0] = 0;
|
||||
counts[0] = 0;
|
||||
for (i = 1; i < ARRAYLEN(codes); i++) {
|
||||
codes[i] = (codes[i - 1] + counts[i - 1]) << 1;
|
||||
first[i] = first[i - 1] + counts[i - 1];
|
||||
}
|
||||
assert(first[15] + counts[15] <= symcount);
|
||||
for (i = 0; i < symcount; i++) {
|
||||
if ((len = lens[i])) {
|
||||
code = codes[len]++;
|
||||
slot = first[len]++;
|
||||
tree[slot] = code << (32 - len) | i << 4 | len;
|
||||
}
|
||||
}
|
||||
return first[15];
|
||||
}
|
||||
|
||||
static struct DeflateHold undeflatesymbol(struct DeflateHold hold,
|
||||
const uint32_t *tree,
|
||||
size_t treecount,
|
||||
uint32_t *out_symbol) {
|
||||
size_t left, right, m;
|
||||
uint32_t search, key;
|
||||
left = 0;
|
||||
right = treecount;
|
||||
search = bitreverse16(hold.word);
|
||||
search <<= 16;
|
||||
search |= 0xffff;
|
||||
while (left < right) { /* TODO(jart): Make this O(1) like Zlib. */
|
||||
m = (left + right) >> 1;
|
||||
if (search < tree[m]) {
|
||||
right = m;
|
||||
} else {
|
||||
left = m + 1;
|
||||
}
|
||||
}
|
||||
key = tree[left - 1];
|
||||
assert(!((search ^ key) >> (32 - (key & 0xf))));
|
||||
*out_symbol = (key >> 4) & 0xfff;
|
||||
CONSUME(key & 0xf);
|
||||
return hold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompresses raw DEFLATE data.
|
||||
*
|
||||
* This is 10x smaller and 10x slower than chromium zlib.
|
||||
*
|
||||
* @param output should be followed by a single guard page, and have
|
||||
* 36kb of guard pages preceding it too
|
||||
* @note h/t Phil Katz, David Huffman, Claude Shannon
|
||||
*/
|
||||
ssize_t undeflate(void *output, size_t outputsize, void *input,
|
||||
size_t inputsize, struct DeflateState *ds) {
|
||||
struct DeflateHold hold;
|
||||
bool isfinalblock;
|
||||
size_t i, nlit, ndist;
|
||||
uint8_t *ip, *op, *si, b, al, last, compressiontype;
|
||||
uint32_t j, l, len, sym, tlit, tdist, tlen, nlen;
|
||||
|
||||
op = output;
|
||||
ip = input;
|
||||
hold.word = 0;
|
||||
hold.bits = 0;
|
||||
isfinalblock = 0;
|
||||
|
||||
while (!isfinalblock) {
|
||||
MOAR(3);
|
||||
isfinalblock = hold.word & 0b1;
|
||||
CONSUME(1);
|
||||
compressiontype = hold.word & 0b11;
|
||||
CONSUME(2);
|
||||
|
||||
switch (compressiontype) {
|
||||
case kDeflateCompressionTypeNone:
|
||||
CONSUME(hold.bits & 7);
|
||||
MOAR(32);
|
||||
len = hold.word & 0xffff;
|
||||
nlen = (hold.word >> 16) & 0xffff;
|
||||
assert(len == ~nlen);
|
||||
CONSUME(32);
|
||||
while (len--) {
|
||||
if (hold.bits) {
|
||||
*op++ = hold.word;
|
||||
CONSUME(8);
|
||||
} else {
|
||||
*op++ = *ip++;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
||||
case kDeflateCompressionTypeFixedHuffman:
|
||||
nlit = 288;
|
||||
ndist = 32;
|
||||
rldecode(ds->lens, kDeflate.lensrl);
|
||||
break;
|
||||
|
||||
case kDeflateCompressionTypeDynamicHuffman:
|
||||
MOAR(5 + 5 + 4);
|
||||
nlit = (hold.word & 0b11111) + 257;
|
||||
CONSUME(5);
|
||||
ndist = (hold.word & 0b11111) + 1;
|
||||
CONSUME(5);
|
||||
nlen = (hold.word & 0b1111) + 4;
|
||||
CONSUME(4);
|
||||
for (i = 0; i < nlen; i++) {
|
||||
MOAR(3);
|
||||
ds->lenlens[kDeflate.orders[i]] = hold.word & 0b111;
|
||||
CONSUME(3);
|
||||
}
|
||||
for (; i < ARRAYLEN(ds->lenlens); i++) {
|
||||
ds->lenlens[kDeflate.orders[i]] = 0;
|
||||
}
|
||||
tlen =
|
||||
undeflatetree(ds, ds->lencodes, ds->lenlens, ARRAYLEN(ds->lenlens));
|
||||
i = 0;
|
||||
last = 0;
|
||||
while (i < nlit + ndist) {
|
||||
MOAR(16);
|
||||
hold = undeflatesymbol(hold, ds->lencodes, tlen, &sym);
|
||||
b = 2;
|
||||
j = 1;
|
||||
switch (sym) {
|
||||
case kDeflateCodeLengthRepeatZero11To138Times:
|
||||
b += 4;
|
||||
j += 8;
|
||||
/* fallthrough */
|
||||
case kDeflateCodeLengthRepeatZero3To10Times:
|
||||
b += 1;
|
||||
last = 0;
|
||||
/* fallthrough */
|
||||
case kDeflateCodeLengthCopyPrevious3To6Times:
|
||||
MOAR(b);
|
||||
j += (hold.word & ((1u << b) - 1u)) + 2u;
|
||||
CONSUME(b);
|
||||
break;
|
||||
default:
|
||||
last = sym;
|
||||
break;
|
||||
}
|
||||
while (j--) {
|
||||
ds->lens[i++] = last;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
tlit = undeflatetree(ds, ds->litcodes, ds->lens, nlit);
|
||||
tdist = undeflatetree(ds, ds->distcodes, &ds->lens[nlit], ndist);
|
||||
|
||||
do {
|
||||
MOAR(16);
|
||||
hold = undeflatesymbol(hold, ds->litcodes, tlit, &sym);
|
||||
if (sym < 256) {
|
||||
*op++ = sym;
|
||||
} else if (sym > 256) {
|
||||
sym -= 257;
|
||||
b = kDeflate.lenbits[sym];
|
||||
MOAR(b);
|
||||
l = kDeflate.lenbase[sym] + (hold.word & ((1u << b) - 1));
|
||||
CONSUME(b);
|
||||
MOAR(16);
|
||||
hold = undeflatesymbol(hold, ds->distcodes, tdist, &sym);
|
||||
b = kDeflate.distbits[sym];
|
||||
MOAR(b);
|
||||
/* max readback: 24577 + 2**13-1 = 32768 */
|
||||
si = op - ((uint32_t)kDeflate.distbase[sym] +
|
||||
(uint32_t)(hold.word & ((1u << b) - 1)));
|
||||
CONSUME(b);
|
||||
repmovsb(&op, &si, l);
|
||||
}
|
||||
} while (sym != 256);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
19
libc/str/undeflate.h
Normal file
19
libc/str/undeflate.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_UNDEFLATE_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_UNDEFLATE_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct DeflateState {
|
||||
uint8_t lenlens[19];
|
||||
uint32_t lencodes[19];
|
||||
uint32_t distcodes[32];
|
||||
uint32_t litcodes[288];
|
||||
uint8_t lens[288 + 32];
|
||||
};
|
||||
|
||||
ssize_t undeflate(void *output, size_t outputsize, void *input,
|
||||
size_t inputsize, struct DeflateState *ds);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_UNDEFLATE_H_ */
|
87
libc/str/varint.h
Normal file
87
libc/str/varint.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_VARINT_H_
|
||||
#define COSMOPOLITAN_LIBC_VARINT_H_
|
||||
#include "libc/limits.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define unzigzag(x) ((x >> 1) ^ -(x & 1))
|
||||
#define zigzag(x) _Generic((x), int32_t : zigzag32, default : zigzag64)(x)
|
||||
|
||||
forceinline int32_t zigzag32(int32_t x) {
|
||||
return (int64_t)((uint64_t)x << 1) ^ (x >> 31);
|
||||
}
|
||||
|
||||
forceinline int64_t zigzag64(int64_t x) {
|
||||
return (int64_t)((uint64_t)x << 1) ^ (x >> 63);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies variable-length integer to buffer.
|
||||
*
|
||||
* @param p needs 10+ bytes for 64-bit and 5+ for 32-bit
|
||||
* @param x is unsigned number to encode
|
||||
* @return pointer past last written byte
|
||||
* @see writesint() which has more efficient encoding for signed numbers
|
||||
*/
|
||||
forceinline uint8_t *writevint(uint8_t *p, uint64_t x) {
|
||||
do {
|
||||
*p++ = (uint8_t)(x | 0x80);
|
||||
x >>= 7;
|
||||
} while (x > 0);
|
||||
p[-1] &= 0x7f;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies variable-length signed integer to buffer.
|
||||
*
|
||||
* @param p needs 10+ bytes for 64-bit and 5+ for 32-bit
|
||||
* @param x is unsigned number to encode
|
||||
* @return pointer past last written byte
|
||||
*/
|
||||
forceinline uint8_t *writesint(uint8_t *p, int64_t x) {
|
||||
return writevint(p, zigzag(x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads variable-length integer from buffer.
|
||||
*
|
||||
* @param x is unsigned number to encode
|
||||
* @return pointer past last read byte or -1ul on error
|
||||
*/
|
||||
forceinline uint8_t *readvint(uint8_t *p, uint8_t *pe, uint64_t *res) {
|
||||
uint8_t b;
|
||||
uint64_t x, o;
|
||||
x = 0;
|
||||
b = 0;
|
||||
while (p < pe) {
|
||||
o = *p++;
|
||||
x |= ((uint64_t)o & 0x7f) << b;
|
||||
if (!(o & 0x80)) {
|
||||
*res = x;
|
||||
return p;
|
||||
}
|
||||
if ((b += 7) > 64) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (uint8_t *)-1ul;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads variable-length zig-zagged integer from buffer.
|
||||
*
|
||||
* @param x is unsigned number to encode
|
||||
* @return pointer past last read byte or -1ul on error
|
||||
*/
|
||||
forceinline uint8_t *readsint(uint8_t *p, uint8_t *pe, int64_t *res) {
|
||||
uint64_t u;
|
||||
if ((p = readvint(p, pe, &u)) != (uint8_t *)-1ul) {
|
||||
*res = unzigzag((int64_t)u);
|
||||
return p;
|
||||
} else {
|
||||
return (uint8_t *)-1ul;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_VARINT_H_ */
|
31
libc/str/wchomp.c
Normal file
31
libc/str/wchomp.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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Mutates line to remove line-ending characters.
|
||||
*
|
||||
* @param line is NULL-propagating
|
||||
* @see getline
|
||||
*/
|
||||
wchar_t *wchomp(wchar_t *line) {
|
||||
if (line) line[strcspn(line, L"\r\n")] = '\0';
|
||||
return line;
|
||||
}
|
26
libc/str/wcrtomb.c
Normal file
26
libc/str/wcrtomb.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
size_t wcrtomb(char *s, wchar_t wc, mbstate_t *st) {
|
||||
if (!s) return 1;
|
||||
return tpencode(s, MB_CUR_MAX, wc, false);
|
||||
}
|
32
libc/str/wcsendswith.c
Normal file
32
libc/str/wcsendswith.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#undef char
|
||||
#undef endswith
|
||||
#undef strlen
|
||||
#undef strnlen
|
||||
|
||||
#define char wchar_t
|
||||
#define endswith wcsendswith
|
||||
#define strlen wcslen
|
||||
#define strnlen wcsnlen
|
||||
|
||||
#include "libc/str/endswith.c"
|
29
libc/str/wcsncpy.c
Normal file
29
libc/str/wcsncpy.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
wchar_t *wcsncpy(wchar_t *d, const wchar_t *s, size_t n) {
|
||||
wchar_t *a;
|
||||
for (a = d; n && *s; --n) {
|
||||
*d++ = *s++;
|
||||
}
|
||||
wmemset(d, 0, n);
|
||||
return a;
|
||||
}
|
32
libc/str/wcsrchr.c
Normal file
32
libc/str/wcsrchr.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Searches for last instance of wchar_t in string.
|
||||
*
|
||||
* @param s is NUL-terminated wchar_t string to search
|
||||
* @param c is the needle
|
||||
* @return address of last c in s, or NULL if not found
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
wchar_t *wcsrchr(const wchar_t *s, wchar_t c) {
|
||||
return wmemrchr(s, c, wcslen(s));
|
||||
}
|
39
libc/str/wcsrtombs.c
Normal file
39
libc/str/wcsrtombs.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
size_t wcsrtombs(char *dest, const wchar_t **src, size_t len, mbstate_t *ps) {
|
||||
/* TODO(jart): broken broken broken insane api */
|
||||
size_t i = 0;
|
||||
if (len) {
|
||||
for (;;) {
|
||||
if (!**src || len == 1) {
|
||||
dest[i] = '\0';
|
||||
break;
|
||||
}
|
||||
size_t got = abs(tpencode(&dest[i], len, **src, false));
|
||||
len -= got;
|
||||
i += got;
|
||||
*src += 1;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
32
libc/str/wcsstartswith.c
Normal file
32
libc/str/wcsstartswith.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#undef char
|
||||
#undef startswith
|
||||
#undef strlen
|
||||
#undef strncmp
|
||||
|
||||
#define char wchar_t
|
||||
#define startswith wcsstartswith
|
||||
#define strlen wcslen
|
||||
#define strncmp wcsncmp
|
||||
|
||||
#include "libc/str/startswith.c"
|
24
libc/str/wcstombs.c
Normal file
24
libc/str/wcstombs.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
size_t wcstombs(char *s, const wchar_t *ws, size_t n) {
|
||||
return wcsrtombs(s, &(const wchar_t *){ws}, n, 0);
|
||||
}
|
29
libc/str/wctob.c
Normal file
29
libc/str/wctob.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
int wctob(wint_t c) {
|
||||
if (0 <= c && c <= 127) {
|
||||
return c;
|
||||
} else {
|
||||
return EOF;
|
||||
}
|
||||
}
|
26
libc/str/wctomb.c
Normal file
26
libc/str/wctomb.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
int wctomb(char *s, wchar_t wc) {
|
||||
if (!s) return 0;
|
||||
return tpencode(s, MB_CUR_MAX, wc, false);
|
||||
}
|
24
libc/str/wmemcpy.c
Normal file
24
libc/str/wmemcpy.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
compatfn wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t count) {
|
||||
return memcpy(dest, src, count * sizeof(wchar_t));
|
||||
}
|
24
libc/str/wmemmove.c
Normal file
24
libc/str/wmemmove.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
compatfn wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t count) {
|
||||
return memmove(dest, src, count * sizeof(wchar_t));
|
||||
}
|
24
libc/str/wmempcpy.c
Normal file
24
libc/str/wmempcpy.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
compatfn wchar_t *wmempcpy(wchar_t *dest, const wchar_t *src, size_t count) {
|
||||
return mempcpy(dest, src, count * sizeof(wchar_t));
|
||||
}
|
34
libc/str/zipfindcentraldir.c
Normal file
34
libc/str/zipfindcentraldir.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/zip.h"
|
||||
|
||||
uint8_t *zipfindcentraldir(const uint8_t *map, size_t mapsize) {
|
||||
const uint8_t *p, *pe;
|
||||
for (p = map + mapsize - kZipCdirHdrMinSize,
|
||||
pe = mapsize > 65536 + kZipCdirHdrMinSize
|
||||
? map + mapsize - 65536 - kZipCdirHdrMinSize
|
||||
: map;
|
||||
p >= pe; --p) {
|
||||
if (ZIP_CDIR_MAGIC(p) == kZipCdirHdrMagic) {
|
||||
return (/*unconst*/ uint8_t *)p;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue