Jeff King <peff@xxxxxxxx> writes: > I am tempted to just call this new one strbuf_split and update all > callers. There aren't that many. Yes, that is indeed tempting, and because we have a new parameter the compiler will catch any new callers that pop up in a mismerge so that would be perfectly safe. > -struct strbuf **strbuf_split(const struct strbuf *sb, int delim) > +struct strbuf **strbuf_split_max(const struct strbuf *sb, int delim, int max) > { > int alloc = 2, pos = 0; > char *n, *p; > @@ -114,7 +114,10 @@ struct strbuf **strbuf_split(const struct strbuf *sb, int delim) > p = n = sb->buf; > while (n < sb->buf + sb->len) { > int len; > - n = memchr(n, delim, sb->len - (n - sb->buf)); > + if (max <= 0 || pos + 1 < max) > + n = memchr(n, delim, sb->len - (n - sb->buf)); > + else > + n = NULL; > if (pos + 1 >= alloc) { > alloc = alloc * 2; > ret = xrealloc(ret, sizeof(struct strbuf *) * alloc); Hmm, even when we know the value of max, we go exponential, and even do so by hand without using ALLOC_GROW(). Somewhat sad. Also do we currently rely on the bug that strbuf_split() returns (NULL,) instead of ("", NULL) when given an empty string? If not, perhaps... strbuf.c | 50 +++++++++++++++++++++++++++++++------------------- 1 files changed, 31 insertions(+), 19 deletions(-) diff --git a/strbuf.c b/strbuf.c index 09c43ae..7a8ee3a 100644 --- a/strbuf.c +++ b/strbuf.c @@ -103,31 +103,43 @@ void strbuf_ltrim(struct strbuf *sb) sb->buf[sb->len] = '\0'; } -struct strbuf **strbuf_split(const struct strbuf *sb, int delim) +struct strbuf **strbuf_split_max(const struct strbuf *sb, int delim, int max) { - int alloc = 2, pos = 0; char *n, *p; - struct strbuf **ret; + struct strbuf **ret = NULL; struct strbuf *t; - - ret = xcalloc(alloc, sizeof(struct strbuf *)); - p = n = sb->buf; - while (n < sb->buf + sb->len) { - int len; - n = memchr(n, delim, sb->len - (n - sb->buf)); - if (pos + 1 >= alloc) { - alloc = alloc * 2; - ret = xrealloc(ret, sizeof(struct strbuf *) * alloc); + int pass, count = 0; + + for (pass = 0; pass < 2; pass++) { + /* First pass counts, second pass allocates and fills */ + if (pass) + ret = xcalloc(count + 1 + !count, sizeof(struct strbuf *)); + count = 0; + n = sb->buf; + while (n < sb->buf + sb->len) { + p = n; + if (max <= 0 || count + 1 < max) + n = memchr(n, delim, sb->len - (n - sb->buf)); + else + n = NULL; + if (!n) + n = sb->buf + sb->len - 1; + + if (pass) { + int len = n - p + 1; + t = xmalloc(sizeof(struct strbuf)); + strbuf_init(t, len); + strbuf_add(t, p, len); + ret[count] = t; + } + count++; + n++; } - if (!n) - n = sb->buf + sb->len - 1; - len = n - p + 1; + } + if (!count) { t = xmalloc(sizeof(struct strbuf)); - strbuf_init(t, len); - strbuf_add(t, p, len); - ret[pos] = t; - ret[++pos] = NULL; - p = ++n; + strbuf_init(t, 0); + ret[0] = t; } return ret; } -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html