From 6a8c21269ff2d9a9bc34ab30930eaf2308b55c9c Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sun, 16 May 2021 18:22:39 -0700 Subject: [PATCH] Make trivial code size enhancements --- libc/fmt/fmt.c | 29 +++------- net/http/parseurl.c | 107 +++++++++++++++++------------------- test/libc/str/strlen_test.c | 62 ++++++++++++++------- tool/net/redbean.c | 5 +- 4 files changed, 103 insertions(+), 100 deletions(-) diff --git a/libc/fmt/fmt.c b/libc/fmt/fmt.c index add6f33c1..adf3d4edb 100644 --- a/libc/fmt/fmt.c +++ b/libc/fmt/fmt.c @@ -308,7 +308,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) { /* evaluate specifier */ qchar = '"'; log2base = 0; - alphabet = "0123456789abcdef"; + alphabet = "0123456789abcdefpx"; switch ((d = *format++)) { case 'p': flags |= FLAGS_HASH; @@ -316,7 +316,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) { signbit = 63; goto FormatNumber; case 'X': - alphabet = "0123456789ABCDEF"; + alphabet = "0123456789ABCDEFPX"; /* fallthrough */ case 'x': log2base = 4; @@ -548,8 +548,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) { } else { PUT('+'); } - for (c = 2, k = 10; 10 * k <= decpt; c++, k *= 10) { - } + for (c = 2, k = 10; 10 * k <= decpt; c++) k *= 10; for (;;) { i1 = decpt / k; PUT(i1 + '0'); @@ -657,7 +656,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) { i1 /= 10; } } - if ((sgn = pun.u[1] & 0x80000000)) { + if (pun.u[1] & 0x80000000) { pun.u[1] &= 0x7fffffff; if (pun.d || sign) sign = '-'; } @@ -686,18 +685,9 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) { PUT(alphabet[17]); PUT(c); if (prec > 0 || alt) PUT('.'); - if (prec > 0) { - if ((i1 = prec) > 5) i1 = 5; - prec -= i1; - do { - PUT(alphabet[(pun.u[1] >> 16) & 0xf]); - pun.u[1] <<= 4; - } while (--i1 > 0); - while (prec > 0) { - --prec; - PUT(alphabet[(pun.u[0] >> 28) & 0xf]); - pun.u[0] <<= 4; - } + while (prec-- > 0) { + PUT(alphabet[(pun.q >> 48) & 0xf]); + pun.q <<= 4; } PUT(alphabet[16]); if (bex < 0) { @@ -706,8 +696,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) { } else { PUT('+'); } - for (c = 1; 10 * c <= bex; c *= 10) { - } + for (c = 1; 10 * c <= bex;) c *= 10; for (;;) { i1 = bex / c; PUT('0' + i1); @@ -715,7 +704,7 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) { bex -= i1 * c; bex *= 10; } - continue; + break; case '%': PUT('%'); diff --git a/net/http/parseurl.c b/net/http/parseurl.c index fd1767bb9..cf5a8c0a6 100644 --- a/net/http/parseurl.c +++ b/net/http/parseurl.c @@ -24,15 +24,10 @@ #include "net/http/url.h" struct UrlParser { - unsigned i; - int c; - const char *data; - size_t size; - char isform; - char islatin1; - char isopaque; - char *p; - char *q; + char *p, *q; + const char *s; + unsigned c, i, n; + char isform, islatin1, isopaque; }; static void EmitLatin1(char **p, int c) { @@ -71,9 +66,8 @@ static void EmitVal(struct UrlParser *u, struct UrlParams *h, bool t) { static void ParseEscape(struct UrlParser *u) { int a, b, c = '%'; - if (u->i + 2 <= u->size && - ((a = kHexToInt[u->data[u->i + 0] & 0xff]) != -1 && - (b = kHexToInt[u->data[u->i + 1] & 0xff]) != -1)) { + if (u->i + 2 <= u->n && ((a = kHexToInt[u->s[u->i + 0] & 255]) != -1 && + (b = kHexToInt[u->s[u->i + 1] & 255]) != -1)) { c = a << 4 | b; u->i += 2; } @@ -81,10 +75,10 @@ static void ParseEscape(struct UrlParser *u) { } static bool ParseScheme(struct UrlParser *u, struct Url *h) { - while (u->i < u->size) { - u->c = u->data[u->i++] & 0xff; + while (u->i < u->n) { + u->c = u->s[u->i++] & 255; if (u->c == '/') { - if (u->i == 1 && u->i < u->size && u->data[u->i] == '/') { + if (u->i == 1 && u->i < u->n && u->s[u->i] == '/') { ++u->i; return true; } else { @@ -95,8 +89,8 @@ static bool ParseScheme(struct UrlParser *u, struct Url *h) { h->scheme.p = u->q; h->scheme.n = u->p - u->q; u->q = u->p; - if (u->i < u->size && u->data[u->i] == '/') { - if (u->i + 1 < u->size && u->data[u->i + 1] == '/') { + if (u->i < u->n && u->s[u->i] == '/') { + if (u->i + 1 < u->n && u->s[u->i + 1] == '/') { u->i += 2; return true; } else { @@ -138,8 +132,8 @@ static bool ParseScheme(struct UrlParser *u, struct Url *h) { static void ParseAuthority(struct UrlParser *u, struct Url *h) { unsigned t = 1; const char *c = NULL; - while (u->i < u->size) { - u->c = u->data[u->i++] & 0xff; + while (u->i < u->n) { + u->c = u->s[u->i++] & 255; if (u->c == '/' || u->c == '#' || u->c == '?') { break; } else if (u->c == '[') { @@ -188,8 +182,8 @@ static void ParseAuthority(struct UrlParser *u, struct Url *h) { } static void ParsePath(struct UrlParser *u, struct UrlView *h) { - while (u->i < u->size) { - u->c = u->data[u->i++] & 0xff; + while (u->i < u->n) { + u->c = u->s[u->i++] & 255; if (u->c == '#') { break; } else if (u->c == '?' && !u->isopaque) { @@ -209,9 +203,9 @@ static void ParsePath(struct UrlParser *u, struct UrlView *h) { static void ParseQuery(struct UrlParser *u, struct UrlParams *h) { bool t = false; - if (!h->p) h->p = xmalloc(0); - while (u->i < u->size) { - u->c = u->data[u->i++] & 0xff; + if (!h->p) h->p = malloc(0); + while (u->i < u->n) { + u->c = u->s[u->i++] & 255; if (u->c == '#') { break; } else if (u->c == '%') { @@ -237,8 +231,8 @@ static void ParseQuery(struct UrlParser *u, struct UrlParams *h) { } static void ParseFragment(struct UrlParser *u, struct UrlView *h) { - while (u->i < u->size) { - u->c = u->data[u->i++] & 0xff; + while (u->i < u->n) { + u->c = u->s[u->i++] & 255; if (u->c == '%') { ParseEscape(u); } else if (u->c >= 0200 && u->islatin1) { @@ -252,20 +246,19 @@ static void ParseFragment(struct UrlParser *u, struct UrlView *h) { u->q = u->p; } -static char *ParseUrlImpl(const char *data, size_t size, struct Url *h, - bool latin1) { +static char *ParseUrlImpl(const char *s, size_t n, struct Url *h, bool latin1) { char *m; struct UrlParser u; - if (size == -1) size = data ? strlen(data) : 0; + if (n == -1) n = s ? strlen(s) : 0; u.i = 0; u.c = 0; + u.s = s; + u.n = n; u.isform = false; u.isopaque = false; u.islatin1 = latin1; - u.data = data; - u.size = size; memset(h, 0, sizeof(*h)); - if ((m = malloc(latin1 ? u.size * 2 : u.size))) { + if ((m = malloc(latin1 ? u.n * 2 : u.n))) { u.q = u.p = m; if (ParseScheme(&u, h)) ParseAuthority(&u, h); if (u.c != '#' && u.c != '?') ParsePath(&u, &h->path); @@ -287,7 +280,7 @@ static char *ParseUrlImpl(const char *data, size_t size, struct Url *h, * There's no failure condition for this routine. This is a permissive * parser. This doesn't normalize path segments like `.` or `..` so use * IsAcceptablePath() to check for those. No restrictions are imposed - * beyond that which is strictly necessary for parsing. All the data + * beyond that which is strictly necessary for parsing. All the s * that is provided will be consumed to the one of the fields. Strict * conformance is enforced on some fields more than others, like scheme, * since it's the most non-deterministically defined field of them all. @@ -297,18 +290,18 @@ static char *ParseUrlImpl(const char *data, size_t size, struct Url *h, * for the things we won't do, like tokenizing path segments into an * array and then nesting another array beneath each of those for * storing semicolon parameters. So this parser won't make SIP easy. - * What it can do is parse HTTP URLs and most URIs like data:opaque, + * What it can do is parse HTTP URLs and most URIs like s:opaque, * better in fact than most things which claim to be URI parsers. * - * @param data is value like `/hi?x=y&z` or `http://a.example/hi#x` - * @param size is byte length and -1 implies strlen + * @param s is value like `/hi?x=y&z` or `http://a.example/hi#x` + * @param n is byte length and -1 implies strlen * @param h is assumed to be uninitialized * @return memory backing UrlView needing free (and h.params.p too) * @see URI Generic Syntax RFC3986 RFC2396 * @see EncodeUrl() */ -char *ParseUrl(const char *data, size_t size, struct Url *h) { - return ParseUrlImpl(data, size, h, false); +char *ParseUrl(const char *s, size_t n, struct Url *h) { + return ParseUrlImpl(s, n, h, false); } /** @@ -325,13 +318,13 @@ char *ParseUrl(const char *data, size_t size, struct Url *h) { * necessary for parsing. This doesn't normalize path segments like `.` * or `..`. Use IsAcceptablePath() to check for those. * - * @param data is value like `/hi?x=y&z` or `http://a.example/hi#x` - * @param size is byte length and -1 implies strlen + * @param s is value like `/hi?x=y&z` or `http://a.example/hi#x` + * @param n is byte length and -1 implies strlen * @param h is assumed to be uninitialized * @return memory backing UrlView needing free (and h.params.p too) */ -char *ParseRequestUri(const char *data, size_t size, struct Url *h) { - return ParseUrlImpl(data, size, h, true); +char *ParseRequestUri(const char *s, size_t n, struct Url *h) { + return ParseUrlImpl(s, n, h, true); } /** @@ -349,23 +342,23 @@ char *ParseRequestUri(const char *data, size_t size, struct Url *h) { * parser that doesn't impose character restrictions beyond what is * necessary for parsing. * - * @param data is value like `foo=bar&x=y&z` - * @param size is byte length and -1 implies strlen + * @param s is value like `foo=bar&x=y&z` + * @param n is byte length and -1 implies strlen * @param h must be zeroed by caller and this appends if reused - * @return UrlView memory with same size needing free (h.p needs free too) + * @return UrlView memory with same n needing free (h.p needs free too) */ -char *ParseParams(const char *data, size_t size, struct UrlParams *h) { +char *ParseParams(const char *s, size_t n, struct UrlParams *h) { char *m; struct UrlParser u; - if (size == -1) size = data ? strlen(data) : 0; + if (n == -1) n = s ? strlen(s) : 0; u.i = 0; + u.s = s; + u.n = n; u.c = '?'; u.isform = true; u.islatin1 = false; u.isopaque = false; - u.data = data; - u.size = size; - if ((m = malloc(u.size))) { + if ((m = malloc(u.n))) { u.q = u.p = m; ParseQuery(&u, h); } @@ -391,23 +384,23 @@ char *ParseParams(const char *data, size_t size, struct UrlParams *h) { * called conditionally after ParseRequestUri() if the host is absent. * Fields unrelated to authority won't be impacted by this function. * - * @param data is value like `127.0.0.1` or `foo.example:80` - * @param size is byte length and -1 implies strlen + * @param s is value like `127.0.0.1` or `foo.example:80` + * @param n is byte length and -1 implies strlen * @param h is needs to be initialized by caller * @return memory backing UrlView needing free */ -char *ParseHost(const char *data, size_t size, struct Url *h) { +char *ParseHost(const char *s, size_t n, struct Url *h) { char *m; struct UrlParser u; - if (size == -1) size = data ? strlen(data) : 0; + if (n == -1) n = s ? strlen(s) : 0; u.i = 0; u.c = 0; + u.s = s; + u.n = n; u.isform = false; u.islatin1 = true; u.isopaque = false; - u.data = data; - u.size = size; - if ((m = malloc(u.size * 2))) { + if ((m = malloc(u.n * 2))) { u.q = u.p = m; ParseAuthority(&u, h); } diff --git a/test/libc/str/strlen_test.c b/test/libc/str/strlen_test.c index db32b8bb1..e5e9e2713 100644 --- a/test/libc/str/strlen_test.c +++ b/test/libc/str/strlen_test.c @@ -159,25 +159,47 @@ BENCH(strlen, bench) { extern size_t strlen_(const char *) asm("strlen"); extern size_t strlen_pure_(const char *) asm("strlen_pure"); static char b[2048]; + static char c[512]; + static char d[256]; memset(b, -1, sizeof(b) - 1); - EZBENCH2("strlen 1", donothing, strlen_("")); - EZBENCH2("strlen_pure 1", donothing, strlen_pure_("")); - EZBENCH2("strlen 2", donothing, strlen_("1")); - EZBENCH2("strlen_pure 2", donothing, strlen_pure_("1")); - EZBENCH2("strlen 7", donothing, strlen_("123456")); - EZBENCH2("strlen_pure 7", donothing, strlen_pure_("123456")); - EZBENCH2("strlen 8", donothing, strlen_("1234567")); - EZBENCH2("strlen_pure 8", donothing, strlen_pure_("1234567")); - EZBENCH2("strlen 9", donothing, strlen_("12345678")); - EZBENCH2("strlen_pure 9", donothing, strlen_pure_("12345678")); - EZBENCH2("strlen 11", donothing, strlen_("12345678aa")); - EZBENCH2("strlen_pure 11", donothing, strlen_pure_("12345678aa")); - EZBENCH2("strlen 13", donothing, strlen_("12345678aabb")); - EZBENCH2("strlen_pure 13", donothing, strlen_pure_("12345678aabb")); - EZBENCH2("strlen 16", donothing, strlen_("123456781234567")); - EZBENCH2("strlen_pure 16", donothing, strlen_pure_("123456781234567")); - EZBENCH2("strlen 17", donothing, strlen_("123456781234567e")); - EZBENCH2("strlen_pure 17", donothing, strlen_pure_("123456781234567e")); - EZBENCH2("strlen 1023", donothing, strlen_(b)); - EZBENCH2("strlen_pure 1023", donothing, strlen_pure_(b)); + memset(c, -1, sizeof(c) - 1); + memset(d, -1, sizeof(d) - 1); + EZBENCH2("strlen_sse 1", donothing, strlen_("")); + EZBENCH2("strlen_swar 1", donothing, strlen_pure_("")); + EZBENCH2("strlen_sse 2", donothing, strlen_("1")); + EZBENCH2("strlen_swar 2", donothing, strlen_pure_("1")); + EZBENCH2("strlen_sse 3", donothing, strlen_("11")); + EZBENCH2("strlen_swar 3", donothing, strlen_pure_("11")); + EZBENCH2("strlen_sse 4", donothing, strlen_("113")); + EZBENCH2("strlen_swar 4", donothing, strlen_pure_("113")); + EZBENCH2("strlen_sse 7", donothing, strlen_("123456")); + EZBENCH2("strlen_swar 7", donothing, strlen_pure_("123456")); + EZBENCH2("strlen_sse 8", donothing, strlen_("1234567")); + EZBENCH2("strlen_swar 8", donothing, strlen_pure_("1234567")); + EZBENCH2("strlen_sse 9", donothing, strlen_("12345678")); + EZBENCH2("strlen_swar 9", donothing, strlen_pure_("12345678")); + EZBENCH2("strlen_sse 11", donothing, strlen_("12345678aa")); + EZBENCH2("strlen_swar 11", donothing, strlen_pure_("12345678aa")); + EZBENCH2("strlen_sse 13", donothing, strlen_("12345678aabb")); + EZBENCH2("strlen_swar 13", donothing, strlen_pure_("12345678aabb")); + EZBENCH2("strlen_sse 16", donothing, strlen_("123456781234567")); + EZBENCH2("strlen_swar 16", donothing, strlen_pure_("123456781234567")); + EZBENCH2("strlen_sse 17", donothing, strlen_("123456781234567e")); + EZBENCH2("strlen_swar 17", donothing, strlen_pure_("123456781234567e")); + EZBENCH2("strlen_sse 34", donothing, + strlen_("123456781234567e123456781234567ee")); + EZBENCH2("strlen_swar 34", donothing, + strlen_pure_("123456781234567e123456781234567ee")); + EZBENCH2("strlen_sse 68", donothing, + strlen_("123456781234567e123456781234567ee123456781234567e1234567812" + "34567eee")); + EZBENCH2("strlen_swar 68", donothing, + strlen_pure_("123456781234567e123456781234567ee123456781234567e12345" + "6781234567eee")); + EZBENCH2("strlen_sse 256", donothing, strlen_(d)); + EZBENCH2("strlen_swar 256", donothing, strlen_pure_(d)); + EZBENCH2("strlen_sse 512", donothing, strlen_(c)); + EZBENCH2("strlen_swar 512", donothing, strlen_pure_(c)); + EZBENCH2("strlen_sse 2048", donothing, strlen_(b)); + EZBENCH2("strlen_swar 2048", donothing, strlen_pure_(b)); } diff --git a/tool/net/redbean.c b/tool/net/redbean.c index 7f863f343..ed16061a0 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -2024,8 +2024,7 @@ static char *RedirectSlash(void) { static char *ServeIndex(const char *path, size_t pathlen) { size_t i, n; char *p, *q; - p = NULL; - for (i = 0; !p && i < ARRAYLEN(kIndexPaths); ++i) { + for (p = 0, i = 0; !p && i < ARRAYLEN(kIndexPaths); ++i) { q = MergePaths(path, pathlen, kIndexPaths[i], strlen(kIndexPaths[i]), &n); p = RoutePath(q, n); free(q); @@ -4093,7 +4092,7 @@ static char *HandleRequest(void) { !IsAcceptableHost(url.host.p, url.host.n) || !IsAcceptablePort(url.port.p, url.port.n)) { LockInc(&shared->c.urisrefused); - return ServeFailure(400, "Bad Request"); + return ServeFailure(400, "Bad URI"); } LOGF("RECEIVED %s HTTP%02d %.*s %s %`'.*s %`'.*s", DescribeClient(), msg.version, msg.xmethod.b - msg.xmethod.a, inbuf.p + msg.xmethod.a,