# Re: \[PATCH 1/2\] test-lib-functions: make packetize() more efficient

- From: Junio C Hamano \<hidden\>
- Date: 2020-03-27 19:18:42 
- List: git
- Page: https://ratatoskr.run/git/2020/03/7840734
- Thread: https://ratatoskr.run/git/2020/03/7840734/t.md

```text
Jeff King [ref] writes:

> The packetize() function takes its input on stdin, and requires 4
> separate sub-processes to format a simple string. We can do much better
> by getting the length via the shell's "${#packet}" construct. The one
> caveat is that the shell can't put a NUL into a variable, so we'll have
> to continue to provide the stdin form for a few calls.

Yuck.  Binary protocol and shell variables do not mix well.

Documentation/CodingGuidelines forbids ${#parameter} in the first
place and we seem to use it only when we know we are using bash.

Perhaps we should start considering to lift it.  I dunno.

> +# convert function arguments or stdin (if not arguments given) to pktline
> +# representation. If multiple arguments are given, they are separated by
> +# whitespace and put in a single packet. Note that data containing NULs must be
> +# given on stdin, and that empty input becomes an empty packet, not a flush
> +# packet (for that you can just print 0000 yourself).

>  packetize() {
> +	if test $# -gt 0
> +	then
> +		packet="$*"
> +		printf '%04x%s' "$((4 + ${#packet}))" "$packet"

This allows 

		packetize "want $hash_head"

to be written like so:

		packetize want "$hash_head"

which maybe is a handy thing to do.

> +	else
> +		cat >packetize.tmp &&
> +		len=$(wc -c <packetize.tmp) &&
> +		printf '%04x' "$(($len + 4))" &&
> +		cat packetize.tmp &&
> +		rm -f packetize.tmp

	perl -e '
		my $data = do { local $?; <STDIN> };
                printf "%04x%s", length($data), $data;
	'

That's one process but much heavier than cat/wc/printf/cat, I guess.

> +	fi
>  }
>  
>  # Parse the input as a series of pktlines, writing the result to stdout.
```
