Re: [PATCH 2/5] t/helper/test-hashmap.c: avoid using `strtok()`
- From
Taylor Blau <me@ttaylorr.com>
- Date
- Apr 18, 2023, 18:06 UTC
- Message-ID
- <ZD7cGx2zKQ2KYnLS@nand.local>
- In-Reply-To
- <20230418102320.GB508219@coredump.intra.peff.net>
On Tue, Apr 18, 2023 at 06:23:20AM -0400, Jeff King wrote:
Show 19 quoted lines
> On Thu, Apr 13, 2023 at 07:31:46PM -0400, Taylor Blau wrote: > > > Avoid using the non-reentrant `strtok()` to separate the parts of each > > incoming command. Instead of replacing it with `strtok_r()`, let's > > instead use the more friendly `string_list_split_in_place_multi()`. > > Junio mentioned this offhand in his response, but I wanted to highlight > one difference in before/after behavior here. > > [before] > $ printf 'add foo bar\niterate\n' | t/helper/test-tool hashmap > foo bar > > [after] > $ printf 'add foo bar\niterate\n' | t/helper/test-tool hashmap > foo bar > > I think that's fine for this test script, but it may be an indication > that we want string-list's split to support different semantics.
I agree that it's OK for the test scripts, but probably isn't the right thing for all cases. In the reroll I'll send shortly, I reimplemented this in a way that (a) doesn't change the behavior of `string_list_split_in_place()`, and (b) allows us to easily change the semantics for `string_list_split_in_place_multi()`.
Show 37 quoted lines
> > @@ -159,21 +161,34 @@ int cmd__hashmap(int argc, const char **argv)
> >
> > /* process commands from stdin */
> > while (strbuf_getline(&line, stdin) != EOF) {
> > - char *cmd, *p1 = NULL, *p2 = NULL;
> > + char *cmd, *p1, *p2;
> > unsigned int hash = 0;
> > struct test_entry *entry;
> >
> > + /*
> > + * Because we memdup() the arguments out of the
> > + * string_list before inserting them into the hashmap,
> > + * it's OK to set its length back to zero to avoid
> > + * re-allocating the items array once per line.
> > + *
> > + * By doing so, we'll instead overwrite the existing
> > + * entries and avoid re-allocating.
> > + */
> > + parts.nr = 0;
>
> I think this is OK, but I wonder if we should wrap it in a function that
> makes sure the strings aren't owned by the strdup (and thus aren't being
> leaked). Something like:
>
> void string_list_setlen(struct string_list *sl, size_t nr)
> {
> /* alternatively, I guess we could actually free nr..sl->nr */
> if (sl->strdup_strings)
> BUG("you can't setlen on a string-list which owns its strings");
> if (nr > sl->nr)
> BUG("you can't grow a string-list with setlen");
> sl->nr = nr;
> }
>
> That is probably overkill for these two test helpers, but I wonder if
> the pattern might escape into "real" code (especially if we suggest
> using string-list instead of strtok).I like this suggestion. I added a new patch (for which you are listed under Co-authored-by) which adds this function as-is.
Thanks, Taylor