Thread (19 messages) flat view 19 messages, 3 authors, 1d ago

Re: [RFC PATCH 3/6] hex: make hex_to_bytes accept kind of hex to use

From: Jeff King <hidden>
Date: 2026-08-01 14:35:17

On Fri, Jul 31, 2026 at 12:38:17AM -0700, Junio C Hamano wrote:
"brian m. carlson" [off-list ref] writes:
quoted
-int hex_to_bytes(unsigned char *binary, const char *hex, size_t len)
+int hex_to_bytes(unsigned char *binary, const char *hex, size_t len, enum hexkind kind)
 {
 	for (; len; len--, hex += 2) {
-		unsigned int val = (hexval(hex[0], HEX_KIND_MIXED) << 4) | hexval(hex[1], HEX_KIND_MIXED);
+		unsigned int val = (hexval(hex[0], kind) << 4) | hexval(hex[1], kind);
 
 		if (val & ~0xff)
 			return -1;
It depends on how big 'len' would be to matter, but if we are
looping for a long stretch, choosing which one of the two hexval
tables to use outside the loop and using that inside may of course
be more performant.

I wondered how ugly such a restructure of the API would look like,
and it does not look _too_ bad.

	void *hextable = hex_table(HEX_KIND_MIXED);

	for (; len; len--, hex += 2) {
		unsigned int val =
			(hexval(hex[0], hextable) << 4) | hexval(hex[1], hextable);
		...
	}

The true type of hextable would be "signed char [256]", but the
callers of the hexval() function do not need to know it, hence I
chose "void *" here.
I had the same thought when reading this, but I wondered if the compiler
might be able to hoist the comparison out of the loop itself (because
hexval() it inlined anyway). It doesn't seem to do so, though (at least
with gcc-15). It loads both table addresses into registers, but there's
still a branch in the loop to decide which table to use.

So in theory this kind of manual hoisting could help.  Might not be that
big a deal with branch prediction, though.

-Peff
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help