Re: [PATCH] wip: change ISSPACE to use ascii whitespace check.
Alejandro Colomar via Mutt-dev <[email protected]>
| Newsgroups | gmane.mail.mutt.devel |
|---|---|
| Message-ID | <aZbvktbVG_lJndcz@devuan> |
Hi Ian,
On 2026-02-19T10:30:09+0000, Ian Collier via Mutt-dev wrote:
> On Thu, Feb 19, 2026 at 01:46:34AM +0100, Alejandro Colomar via Mutt-dev wrote:
> > On 2026-02-18T23:42:28+0000, Ian Collier via Mutt-dev wrote:
> > > I do not understand why strchrnul and strcmp are even being invoked here.
>
> > Because they are necessary. (Well, strcmp(3) is not, as you could do
> > manual byte operations, but it's simple, more readable, and optimized
> > out.) strchrnul(3) is necessary.
>
> > strchr(s, '\0') != NULL
>
> > would evaluate to true, which is a misbehavior: it would treat '\0' as
> > white space, while it is not.
>
> The nul character is a bit of an edge case when considering strxxx functions,
> of course. But that's easily fixed:
>
> c && strchr(s, c) != NULL
>
> No doubt you'll now be telling me that you don't want to evaluate c twice
> in the context of a macro. Well then, use an inline function. :-)
An inline function with that would be an alternative. A macro is more
compact, though, and can be implemented as a one-liner. When
implementing several of these, it can help readability of the entire set
of APIs if they fit in a compact space and they are very similar:
// isascii_c - is [:ascii:] C-locale
#define isascii_c(c) (!!strchr(CTYPE_ASCII_C, c))
#define iscntrl_c(c) (!!strchr(CTYPE_CNTRL_C, c))
#define islower_c(c) (!streq(strchrnul(CTYPE_LOWER_C, c), ""))
#define isupper_c(c) (!streq(strchrnul(CTYPE_UPPER_C, c), ""))
#define isdigit_c(c) (!streq(strchrnul(CTYPE_DIGIT_C, c), ""))
#define ispunct_c(c) (!streq(strchrnul(CTYPE_PUNCT_C, c), ""))
#define isspace_c(c) (!streq(strchrnul(CTYPE_SPACE_C, c), ""))
#define isalpha_c(c) (!streq(strchrnul(CTYPE_ALPHA_C, c), ""))
#define isalnum_c(c) (!streq(strchrnul(CTYPE_ALNUM_C, c), ""))
#define isgraph_c(c) (!streq(strchrnul(CTYPE_GRAPH_C, c), ""))
#define isprint_c(c) (!streq(strchrnul(CTYPE_PRINT_C, c), ""))
#define isxdigit_c(c) (!streq(strchrnul(CTYPE_XDIGIT_C, c), ""))
Here's a comparison of the assembly they produce:
alx@devuan:~/tmp$ diff -u isspace?.c
--- isspace1.c 2026-02-19 12:43:01.016632233 +0100
+++ isspace2.c 2026-02-19 12:39:40.987744755 +0100
@@ -1,8 +1,7 @@
#include <string.h>
#define CTYPE_SPACE_C " \t\n\v\f\r"
-#define streq(a,b) (strcmp(a,b) == 0)
bool
isspace_c(int c)
{
- return !streq(strchrnul(CTYPE_SPACE_C, c), "");
+ return c && strchr(CTYPE_SPACE_C, c) != NULL;
}
alx@devuan:~/tmp$ gcc -S -O2 isspace?.c
alx@devuan:~/tmp$ diff -u isspace?.s
--- isspace1.s 2026-02-19 12:44:24.264776257 +0100
+++ isspace2.s 2026-02-19 12:44:24.276776354 +0100
@@ -1,4 +1,4 @@
- .file "isspace1.c"
+ .file "isspace2.c"
.text
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
@@ -10,16 +10,23 @@
isspace_c:
.LFB0:
.cfi_startproc
+ testl %edi, %edi
+ je .L5
subq $8, %rsp
.cfi_def_cfa_offset 16
movl %edi, %esi
leaq .LC0(%rip), %rdi
- call strchrnul@PLT
- cmpb $0, (%rax)
+ call strchr@PLT
+ testq %rax, %rax
setne %al
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
+ .p2align 4,,10
+ .p2align 3
+.L5:
+ xorl %eax, %eax
+ ret
.cfi_endproc
.LFE0:
.size isspace_c, .-isspace_c
The strchrnul(3) version seems to have significantly less instructions.
And strchrnul(3) is internally simpler than strchr(3). In musl, for
example, strchrnul(3) is used to implement strchr(3).
Have a lovely day!
Alex
--
<https://www.alejandro-colomar.es>
signature.asc
(application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEES7Jt9u9GbmlWADAi64mZXMKQwqkFAmmW+VcACgkQ64mZXMKQ wqlWqw//UjjrlDrELfotNW5C7vr/69IJvIY8guX15b/l5JL4IvhHGnUjfffMkvQu kZ2UuHCi57odyrdsPp1HWmbiPVrZdiaftulSci8Zz1fPCH3NWwmY+E3JYd0GrsRK mqAubjsdBA0tiIM/vOdI4CnGPEJnOZkvptUU4ssfL8gsIN73bgwYDXRONBjuNmLS uYxYVEEmeI9F/Wwq5b3EL0G+1NMqZAxoA8we3hgWT4T+QB+Ns+CJRLvBNV2adeoP Oi5WX3H6DXYhleHdH4aDwc6LePMf5h0uzDk6agrrmPNOjibteEtXxmTHURd6J/hl TYvg26nmHB9Yz68mlWcvq5E+w3CuBzKXC0awLjV7CWUluU/ouLtC2c5I/AQS3OBT gNw6Or475PDlE77loNIVuYZcA5oNx9VeZSl7RpzZaW6dnnl/tZ15K8Qt491ZwtuN SJxX5vQapFeKmc9gkYLt4T4viSRiUW4pm772LnEGGgOaZIQozhxq/iWUioZI3sKq ZzfDxW7ameMhXpuSM1HnGj0CGLe+CcgaKy/XKedqqVd8ueDUYMn4OKA3y5e5BCpx 40g93Z6Q9EBbhEVa1GzvgWkgauwyw5jc8H7WtWSYfHhQHyFvyzfweo49NB+eC8ey l6LS87gqFgOnWahlvZXocqid9D2YHAiLzHr4Y5i7r6xF3BuRJtg= =abrv -----END PGP SIGNATURE-----