diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2023-08-07 19:41:12 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2023-08-07 19:41:38 -0400 |
commit | 2bc5a379b5f4f6a35465a2df19107209ed191d06 (patch) | |
tree | f38dcb368af2650a537aad5e890fc0ee64f15a6d /src | |
parent | 39baf8a76ddefe3a9f02fc1170b213939ab2d5c2 (diff) | |
download | bfs-2bc5a379b5f4f6a35465a2df19107209ed191d06.tar.xz |
bfstd: Check multiple chars at once for isascii()
Diffstat (limited to 'src')
-rw-r--r-- | src/bfstd.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/src/bfstd.c b/src/bfstd.c index 9cfd09c..a71e4b4 100644 --- a/src/bfstd.c +++ b/src/bfstd.c @@ -639,17 +639,34 @@ static size_t printable_len(const char *str, size_t len, enum wesc_flags flags) call_once(&once, char_cache_init); // Fast path: avoid multibyte checks - size_t i; - for (i = 0; i < len; ++i) { + size_t i, word; + for (i = 0; i + sizeof(word) <= len;) { + // Word-at-a-time isascii() + memcpy(&word, str + i, sizeof(word)); + // 0xFFFF... / 0xFF == 0x10101... + size_t mask = (SIZE_MAX / 0xFF) << 7; + if (word & mask) { + goto multibyte; + } + + for (size_t j = 0; j < sizeof(word); ++i, ++j) { + if (!xisprint(str[i], flags)) { + return i; + } + } + } + + for (; i < len; ++i) { unsigned char c = str[i]; if (!isascii(c)) { - break; + goto multibyte; } if (!xisprint(c, flags)) { return i; } } +multibyte: mbstate_t mb; memset(&mb, 0, sizeof(mb)); |