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-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.