From 8ba5c3493ddc521047075d7d2268a588988bbb0e Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 8 Nov 2024 19:55:54 -0800 Subject: [PATCH] seq: simplify output buffer management MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * src/seq.c (seq_fast): Simplify by using an output buffer of known size (BUFSIZ) on the stack, rather than a heap buffer that might grow. For the number buffer, don’t bother appending NUL since nobody uses the NUL, and xpalloc from nullptr not p0 since we need to move the buffer data by hand anyway. --- src/seq.c | 67 +++++++++++++++++++++++-------------------------------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/src/seq.c b/src/seq.c index 33594667a7..2049c7803f 100644 --- a/src/seq.c +++ b/src/seq.c @@ -473,9 +473,10 @@ seq_fast (char const *a, char const *b, uintmax_t step) /* Ensure we only increase by at most 1 digit at buffer boundaries. */ static_assert (SEQ_FAST_STEP_LIMIT_DIGITS < INITIAL_ALLOC_DIGITS - 1); - /* Copy input strings (incl NUL) to end of new buffers. */ - char *p0 = xmalloc (inc_size + 1); - char *p = memcpy (p0 + inc_size - p_len, a, p_len + 1); + /* Copy A (sans NUL) to end of new buffer. */ + char *p0 = xmalloc (inc_size); + char *endp = p0 + inc_size; + char *p = memcpy (endp - p_len, a, p_len); bool ok = inf || cmp (p, p_len, b, b_len) <= 0; if (ok) @@ -483,53 +484,41 @@ seq_fast (char const *a, char const *b, uintmax_t step) /* Reduce number of fwrite calls which is seen to give a speed-up of more than 2x over the unbuffered code when printing the first 10^9 integers. */ - size_t buf_size = MAX (BUFSIZ, (inc_size + 1) * 2); - char *buf = xmalloc (buf_size); - char const *buf_end = buf + buf_size; - + char buf[BUFSIZ]; + char *buf_end = buf + sizeof buf; char *bufp = buf; - /* Write first number to buffer. */ - bufp = mempcpy (bufp, p, p_len); - - /* Append separator then number. */ while (true) { - char *endp = p + p_len; + /* Append number. */ + char *pp = p; + while (buf_end - bufp <= endp - pp) + { + memcpy (bufp, pp, buf_end - bufp); + pp += buf_end - bufp; + if (fwrite (buf, sizeof buf, 1, stdout) != 1) + write_error (); + bufp = buf; + } + bufp = mempcpy (bufp, pp, endp - pp); + + /* Compute next number, and exit loop if it grows sufficiently. */ for (uintmax_t n_incr = step; n_incr; n_incr--) p -= incr_grows (p, endp); - p_len = endp - p; - - if (! inf && 0 < cmp (p, p_len, b, b_len)) + if (! inf && 0 < cmp (p, endp - p, b, b_len)) break; *bufp++ = *separator; - /* Double up the buffers when needed for the inf case. */ - if (p_len == inc_size) + /* Grow buffer if needed for the inf case. */ + if (p == p0) { - inc_size *= 2; - p0 = xrealloc (p0, inc_size + 1); - p = memmove (p0 + p_len, p0, p_len + 1); - - if (buf_size < (inc_size + 1) * 2) - { - size_t buf_offset = bufp - buf; - buf_size = (inc_size + 1) * 2; - buf = xrealloc (buf, buf_size); - buf_end = buf + buf_size; - bufp = buf + buf_offset; - } - } - - bufp = mempcpy (bufp, p, p_len); - /* If no place for another separator + number then - output buffer so far, and reset to start of buffer. */ - if (buf_end - (p_len + 1) < bufp) - { - if (fwrite (buf, bufp - buf, 1, stdout) != 1) - write_error (); - bufp = buf; + idx_t saved_p_len = endp - p; + char *new_p0 = xpalloc (nullptr, &inc_size, 1, -1, 1); + endp = new_p0 + inc_size; + p = memcpy (endp - saved_p_len, p0, saved_p_len); + free (p0); + p0 = new_p0; } } -- 2.47.2