Use Lua auto buffers when possible

This commit is contained in:
Justine Tunney 2022-05-29 14:47:14 -07:00
parent 13ee75150c
commit da6d610056
8 changed files with 204 additions and 101 deletions

View file

@ -115,15 +115,13 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
unsigned u;
char ibuf[21];
bool longdouble;
long double ldbl;
unsigned long lu;
wchar_t charbuf[1];
const char *alphabet;
int (*out)(const char *, void *, size_t);
unsigned char signbit, log2base;
char *s, *q, qchar;
int d, w, n;
int sign, prec, flags, width, lasterr;
const char *alphabet;
unsigned char signbit, log2base;
int (*out)(const char *, void *, size_t);
int d, w, n, sign, prec, flags, width, lasterr;
lasterr = errno;
out = fn ? fn : (void *)missingno;
@ -139,44 +137,44 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
}
if (!IsTiny()) {
if (format[1] == 's') { /* FAST PATH: PLAIN STRING */
if (format[1] == 's') { // FAST PATH: PLAIN STRING
s = va_arg(va, char *);
if (!s) s = "(null)";
if (out(s, arg, strlen(s)) == -1) return -1;
format += 2;
continue;
} else if (format[1] == 'd') { /* FAST PATH: PLAIN INTEGER */
} else if (format[1] == 'd') { // FAST PATH: PLAIN INTEGER
d = va_arg(va, int);
if (out(ibuf, arg, FormatInt64(ibuf, d) - ibuf) == -1) return -1;
if (out(ibuf, arg, FormatInt32(ibuf, d) - ibuf) == -1) return -1;
format += 2;
continue;
} else if (format[1] == 'u') { /* FAST PATH: PLAIN UNSIGNED */
} else if (format[1] == 'u') { // FAST PATH: PLAIN UNSIGNED
u = va_arg(va, unsigned);
if (out(ibuf, arg, FormatUint64(ibuf, u) - ibuf) == -1) return -1;
if (out(ibuf, arg, FormatUint32(ibuf, u) - ibuf) == -1) return -1;
format += 2;
continue;
} else if (format[1] == 'x') { /* FAST PATH: PLAIN HEX */
} else if (format[1] == 'x') { // FAST PATH: PLAIN HEX
u = va_arg(va, unsigned);
if (out(ibuf, arg, uint64toarray_radix16(u, ibuf)) == -1) return -1;
format += 2;
continue;
} else if (format[1] == 'l' && format[2] == 'x') {
lu = va_arg(va, unsigned long); /* FAST PATH: PLAIN LONG HEX */
lu = va_arg(va, unsigned long); // FAST PATH: PLAIN LONG HEX
if (out(ibuf, arg, uint64toarray_radix16(lu, ibuf)) == -1) return -1;
format += 3;
continue;
} else if (format[1] == 'l' && format[2] == 'd') {
ld = va_arg(va, long); /* FAST PATH: PLAIN LONG */
ld = va_arg(va, long); // FAST PATH: PLAIN LONG
if (out(ibuf, arg, FormatInt64(ibuf, ld) - ibuf) == -1) return -1;
format += 3;
continue;
} else if (format[1] == 'l' && format[2] == 'u') {
lu = va_arg(va, unsigned long); /* FAST PATH: PLAIN UNSIGNED LONG */
lu = va_arg(va, unsigned long); // FAST PATH: PLAIN UNSIGNED LONG
if (out(ibuf, arg, FormatUint64(ibuf, lu) - ibuf) == -1) return -1;
format += 3;
continue;
} else if (format[1] == '.' && format[2] == '*' && format[3] == 's') {
n = va_arg(va, unsigned); /* FAST PATH: PRECISION STRING */
n = va_arg(va, unsigned); // FAST PATH: PRECISION STRING
s = va_arg(va, const char *);
if (s) {
n = strnlen(s, n);
@ -190,7 +188,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
}
}
/* GENERAL PATH */
// GENERAL PATH
format++;
sign = 0;
flags = 0;
@ -218,7 +216,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
goto getflag;
case '`':
flags |= FLAGS_REPR;
/* fallthrough */
// fallthrough
case '\'':
flags |= FLAGS_QUOTE;
goto getflag;
@ -227,14 +225,14 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
break;
}
/* evaluate width field */
// evaluate width field
width = 0;
if (isdigit(*format)) {
width = __fmt_atoi(&format);
} else if (*format == '*') {
w = va_arg(va, int);
if (w < 0) {
flags |= FLAGS_LEFT; /* reverse padding */
flags |= FLAGS_LEFT; // reverse padding
width = -w;
sign = '-';
} else {
@ -243,7 +241,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
format++;
}
/* evaluate prec field */
// evaluate prec field
prec = 0;
if (*format == '.') {
flags |= FLAGS_PRECISION;
@ -259,11 +257,11 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
prec = 0;
}
/* evaluate length field */
// evaluate length field
signbit = 31;
longdouble = false;
switch (*format) {
case 'j': /* intmax_t */
case 'j': // intmax_t
format++;
signbit = sizeof(intmax_t) * 8 - 1;
if (*format == 'j') {
@ -277,14 +275,14 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
break;
}
if (format[1] == 'l') format++;
/* fallthrough */
case 't': /* ptrdiff_t */
case 'z': /* size_t */
case 'Z': /* size_t */
// fallthrough
case 't': // ptrdiff_t
case 'z': // size_t
case 'Z': // size_t
format++;
signbit = 63;
break;
case 'L': /* long double */
case 'L': // long double
format++;
longdouble = true;
break;
@ -301,7 +299,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
break;
}
/* evaluate specifier */
// evaluate specifier
qchar = '"';
log2base = 0;
alphabet = "0123456789abcdefpx";
@ -313,7 +311,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
goto FormatNumber;
case 'X':
alphabet = "0123456789ABCDEFPX";
/* fallthrough */
// fallthrough
case 'x':
log2base = 4;
goto FormatNumber;
@ -326,9 +324,9 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
case 'd':
case 'i':
flags |= FLAGS_ISSIGNED;
/* fallthrough */
// fallthrough
case 'u': {
flags &= ~FLAGS_HASH; /* no hash for dec format */
flags &= ~FLAGS_HASH; // no hash for dec format
FormatNumber:
if (__fmt_ntoa(out, arg, va, signbit, log2base, prec, width, flags,
alphabet) == -1) {
@ -359,7 +357,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
}
case 'q':
flags |= FLAGS_QUOTE;
/* fallthrough */
// fallthrough
case 's':
p = va_arg(va, void *);
FormatString:

View file

@ -20,25 +20,7 @@
#include "libc/str/str.h"
#include "net/http/http.h"
// -_0-9A-Za-z
static const char kHostChars[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, // 0x20
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 0x30
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 0x50
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 0x70
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xa0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xb0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xc0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xd0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xe0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xf0
};
extern const char kHostChars[256]; // -_0-9A-Za-z
/**
* Returns true if host seems legit.

70
net/http/khostchars.S Normal file
View file

@ -0,0 +1,70 @@
#include "libc/macros.internal.h"
// generated by:
// o//tool/build/xlat.com -DA _- -skHostChars
//
// present absent
//
// 0x00
// § 0x10
// - !#§%&()*+, ./ 0x20
// 0123456789 :;<=>⁇ 0x30
// ABCDEFGHIJKLMNO @ 0x40
// PQRSTUVWXYZ _ []^ 0x50
// abcdefghijklmno ` 0x60
// pqrstuvwxyz {|}~ 0x70
// ÇüéâäàåçêëèïîìÄÅ 0x80
// ÉæÆôöòûùÿÖÜ¢£¥ƒ 0x90
// áíóúñѪº¿¬½¼¡«» 0xa0
// 0xb0
// 0xc0
// 0xd0
// αßΓπΣσμτΦΘΩδφε 0xe0
// ±÷°×²λ 0xf0
//
// const char kHostChars[256] = {
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, // 0x20
// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 0x30
// 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40
// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 0x50
// 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60
// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 0x70
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xa0
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xb0
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xc0
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xd0
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xe0
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xf0
// };
.initbss 300,_init_kHostChars
kHostChars:
.zero 256
.endobj kHostChars,globl
.previous
.initro 300,_init_kHostChars
kHostChars.rom:
.byte 45,0 # 00-2c -,
.byte 1,1 # 2d-2d ---
.byte 2,0 # 2e-2f .-/
.byte 10,1 # 30-39 0-9
.byte 7,0 # 3a-40 :-@
.byte 26,1 # 41-5a A-Z
.byte 4,0 # 5b-5e [-^
.byte 1,1 # 5f-5f _-_
.byte 1,0 # 60-60 `-`
.byte 26,1 # 61-7a a-z
.byte 133,0 # 7b-ff {-λ
.byte 0,0 # terminator
.endobj kHostChars.rom,globl
.init.start 300,_init_kHostChars
call rldecode
.init.end 300,_init_kHostChars
// 29 bytes total (11% original size)

View 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 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
#include "libc/limits.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
TEST(FormatInt32, test) {
char b[12];
EXPECT_STREQ("", FormatInt32(b, 0));
EXPECT_STREQ("0", b);
EXPECT_STREQ("", FormatInt32(b, INT32_MAX));
EXPECT_STREQ("2147483647", b);
EXPECT_STREQ("", FormatInt32(b, INT32_MIN));
EXPECT_STREQ("-2147483648", b);
}
TEST(FormatInt64, test) {
char b[21];
EXPECT_STREQ("", FormatInt64(b, 0));
EXPECT_STREQ("0", b);
EXPECT_STREQ("", FormatInt64(b, INT64_MAX));
EXPECT_STREQ("9223372036854775807", b);
EXPECT_STREQ("", FormatInt64(b, INT64_MIN));
EXPECT_STREQ("-9223372036854775808", b);
}
BENCH(FormatInt, bench) {
char b[21];
EZBENCH2("FormatUint32 max32", donothing, FormatUint32(b, INT_MAX));
EZBENCH2("FormatUint64 max32", donothing, FormatUint64(b, INT_MAX));
EZBENCH2("FormatInt32 min32", donothing, FormatInt32(b, INT_MIN));
EZBENCH2("FormatInt64 min32", donothing, FormatInt64(b, INT_MIN));
EZBENCH2("FormatInt32 max32", donothing, FormatInt32(b, INT_MAX));
EZBENCH2("FormatInt64 max32", donothing, FormatInt64(b, INT_MAX));
}

View file

@ -7,14 +7,11 @@ function main()
else
cmd = 'ls'
end
syscall = 'commandv'
ls = assert(unix.commandv(cmd))
syscall = 'pipe'
reader, writer = assert(unix.pipe(unix.O_CLOEXEC))
oldint = assert(unix.sigaction(unix.SIGINT, unix.SIG_IGN))
oldquit = assert(unix.sigaction(unix.SIGQUIT, unix.SIG_IGN))
oldmask = assert(unix.sigprocmask(unix.SIG_BLOCK, unix.Sigset(unix.SIGCHLD)))
syscall = 'fork'
child = assert(unix.fork())
if child == 0 then
unix.close(0)

View file

@ -153,16 +153,17 @@ int LuaRdseed(lua_State *L) {
}
int LuaDecimate(lua_State *L) {
char *p;
size_t n, m;
const char *s;
unsigned char *p;
luaL_Buffer buf;
s = luaL_checklstring(L, 1, &n);
m = ROUNDUP(n, 16);
p = LuaAllocOrDie(L, m);
p = luaL_buffinitsize(L, &buf, m);
bzero(p + n, m - n);
cDecimate2xUint8x8(m, p, (signed char[8]){-1, -3, 3, 17, 17, 3, -3, -1});
lua_pushlstring(L, (char *)p, (n + 1) >> 1);
free(p);
cDecimate2xUint8x8(m, (unsigned char *)p,
(signed char[8]){-1, -3, 3, 17, 17, 3, -3, -1});
luaL_pushresultsize(&buf, (n + 1) >> 1);
return 1;
}
@ -259,11 +260,15 @@ int LuaParseParams(lua_State *L) {
struct UrlParams h;
data = luaL_checklstring(L, 1, &size);
bzero(&h, sizeof(h));
m = ParseParams(data, size, &h);
LuaPushUrlParams(L, &h);
free(h.p);
free(m);
return 1;
if ((m = ParseParams(data, size, &h))) {
LuaPushUrlParams(L, &h);
free(h.p);
free(m);
return 1;
} else {
luaL_error(L, "out of memory");
unreachable;
}
}
int LuaParseHost(lua_State *L) {
@ -273,12 +278,16 @@ int LuaParseHost(lua_State *L) {
const char *p;
bzero(&h, sizeof(h));
p = luaL_checklstring(L, 1, &n);
m = ParseHost(p, n, &h);
lua_newtable(L);
LuaPushUrlView(L, &h.host);
LuaPushUrlView(L, &h.port);
free(m);
return 1;
if ((m = ParseHost(p, n, &h))) {
lua_newtable(L);
LuaPushUrlView(L, &h.host);
LuaPushUrlView(L, &h.port);
free(m);
return 1;
} else {
luaL_error(L, "out of memory");
unreachable;
}
}
int LuaPopcnt(lua_State *L) {
@ -395,23 +404,26 @@ int LuaEncodeLatin1(lua_State *L) {
size_t n;
p = luaL_checklstring(L, 1, &n);
f = LuaCheckControlFlags(L, 2);
p = EncodeLatin1(p, n, &n, f);
lua_pushlstring(L, p, n);
free(p);
return 1;
if ((p = EncodeLatin1(p, n, &n, f))) {
lua_pushlstring(L, p, n);
free(p);
return 1;
} else {
luaL_error(L, "out of memory");
unreachable;
}
}
int LuaGetRandomBytes(lua_State *L) {
char *p;
size_t n = luaL_optinteger(L, 1, 16);
size_t n;
luaL_Buffer buf;
n = luaL_optinteger(L, 1, 16);
if (!(n > 0 && n <= 256)) {
luaL_argerror(L, 1, "not in range 1..256");
unreachable;
}
p = LuaAllocOrDie(L, n);
CHECK_EQ(n, getrandom(p, n, 0));
lua_pushlstring(L, p, n);
free(p);
CHECK_EQ(n, getrandom(luaL_buffinitsize(L, &buf, n), n, 0));
luaL_pushresult(&buf);
return 1;
}
@ -701,32 +713,30 @@ static void LuaCompress2(lua_State *L, void *dest, size_t *destLen,
}
int LuaCompress(lua_State *L) {
int rc;
bool raw;
size_t n, m;
char *q, *e;
uint32_t crc;
const char *p;
luaL_Buffer buf;
int level, hdrlen;
p = luaL_checklstring(L, 1, &n);
level = luaL_optinteger(L, 2, Z_DEFAULT_COMPRESSION);
m = compressBound(n);
if (lua_toboolean(L, 3)) {
// raw mode
q = LuaAllocOrDie(L, m);
q = luaL_buffinitsize(L, &buf, m);
LuaCompress2(L, q, &m, p, n, level);
lua_pushlstring(L, q, m);
} else {
// easy mode
q = LuaAllocOrDie(L, 10 + 4 + m);
q = luaL_buffinitsize(L, &buf, 10 + 4 + m);
crc = crc32_z(0, p, n);
e = uleb64(q, n);
e = WRITE32LE(e, crc);
hdrlen = e - q;
LuaCompress2(L, q + hdrlen, &m, p, n, level);
lua_pushlstring(L, q, hdrlen + m);
m += hdrlen;
}
free(q);
luaL_pushresultsize(&buf, m);
return 1;
}
@ -735,6 +745,7 @@ int LuaUncompress(lua_State *L) {
uint32_t crc;
int rc, level;
const char *p;
luaL_Buffer buf;
size_t n, m, len;
p = luaL_checklstring(L, 1, &n);
if (lua_isnoneornil(L, 2)) {
@ -744,23 +755,20 @@ int LuaUncompress(lua_State *L) {
}
len = m;
crc = READ32LE(p + rc);
q = LuaAllocOrDie(L, m);
q = luaL_buffinitsize(L, &buf, m);
if (uncompress((void *)q, &m, (unsigned char *)p + rc + 4, n) != Z_OK ||
m != len || crc32_z(0, q, m) != crc) {
free(q);
luaL_error(L, "compressed value is corrupted");
unreachable;
}
} else {
len = m = luaL_checkinteger(L, 2);
q = LuaAllocOrDie(L, m);
q = luaL_buffinitsize(L, &buf, m);
if (uncompress((void *)q, &m, (void *)p, n) != Z_OK || m != len) {
free(q);
luaL_error(L, "compressed value is corrupted");
unreachable;
}
}
lua_pushlstring(L, q, m);
free(q);
luaL_pushresultsize(&buf, m);
return 1;
}

View file

@ -11,10 +11,6 @@ int LuaUnix(lua_State *);
int luaopen_argon2(lua_State *);
int luaopen_lsqlite3(lua_State *);
void *LuaRealloc(lua_State *, void *, size_t);
void *LuaAlloc(lua_State *, size_t);
void *LuaAllocOrDie(lua_State *, size_t);
int LuaBenchmark(lua_State *);
int LuaBin(lua_State *);
int LuaBsf(lua_State *);

View file

@ -103,7 +103,7 @@ struct UnixErrno {
static lua_State *GL;
void *LuaRealloc(lua_State *L, void *p, size_t n) {
static void *LuaRealloc(lua_State *L, void *p, size_t n) {
void *p2;
if ((p2 = realloc(p, n))) {
return p2;
@ -116,11 +116,11 @@ void *LuaRealloc(lua_State *L, void *p, size_t n) {
return p2;
}
void *LuaAlloc(lua_State *L, size_t n) {
static void *LuaAlloc(lua_State *L, size_t n) {
return LuaRealloc(L, 0, n);
}
void *LuaAllocOrDie(lua_State *L, size_t n) {
static void *LuaAllocOrDie(lua_State *L, size_t n) {
void *p;
if ((p = LuaAlloc(L, n))) {
return p;