MCPcopy Create free account
hub / github.com/coreutils/coreutils / seq_fast

Function seq_fast

src/seq.c:461–538  ·  view source on GitHub ↗

Print all whole numbers from A to B, inclusive -- to stdout, each followed by a newline. Then exit. */

Source from the content-addressed store, hash-verified

459/* Print all whole numbers from A to B, inclusive -- to stdout, each
460 followed by a newline. Then exit. */
461static void
462seq_fast (char const *a, char const *b, uintmax_t step)
463{
464 /* Skip past any redundant leading '0's. Without this, our naive cmp
465 function would declare 000 to be larger than 99. */
466 a = trim_leading_zeros (a);
467 b = trim_leading_zeros (b);
468
469 idx_t p_len = strlen (a);
470 idx_t b_len = strlen (b);
471 bool inf = b_len == 3 && memeq (b, "inf", 4);
472
473 /* Allow for at least 31 digits without realloc.
474 1 more than p_len is needed for the inf case. */
475 enum { INITIAL_ALLOC_DIGITS = 31 };
476 idx_t inc_size = MAX (MAX (p_len + 1, b_len), INITIAL_ALLOC_DIGITS);
477 /* Ensure we only increase by at most 1 digit at buffer boundaries. */
478 static_assert (SEQ_FAST_STEP_LIMIT_DIGITS < INITIAL_ALLOC_DIGITS - 1);
479
480 /* Copy A (sans NUL) to end of new buffer. */
481 char *p0 = xmalloc (inc_size);
482 char *endp = p0 + inc_size;
483 char *p = memcpy (endp - p_len, a, p_len);
484
485 /* Reduce number of write calls which is seen to
486 give a speed-up of more than 2x over naive stdio code
487 when printing the first 10^9 integers. */
488 char buf[BUFSIZ];
489 char *buf_end = buf + sizeof buf;
490 char *bufp = buf;
491
492 while (inf || cmp (p, endp - p, b, b_len) <= 0)
493 {
494 /* Append number, flushing output buffer while the number's
495 digits do not fit with room for a separator or terminator. */
496 char *pp = p;
497 while (buf_end - bufp <= endp - pp)
498 {
499 memcpy (bufp, pp, buf_end - bufp);
500 pp += buf_end - bufp;
501 if (full_write (STDOUT_FILENO, buf, sizeof buf) != sizeof buf)
502 write_error ();
503 bufp = buf;
504 }
505
506 /* The rest of the number, followed by a separator or terminator,
507 will fit. Tentatively append a separator. */
508 bufp = mempcpy (bufp, pp, endp - pp);
509 *bufp++ = *separator;
510
511 /* Grow number buffer if needed for the inf case. */
512 if (p == p0)
513 {
514 char *new_p0 = xpalloc (NULL, &inc_size, 1, -1, 1);
515 idx_t saved_p_len = endp - p;
516 endp = new_p0 + inc_size;
517 p = memcpy (endp - saved_p_len, p0, saved_p_len);
518 free (p0);

Callers 1

mainFunction · 0.85

Calls 4

trim_leading_zerosFunction · 0.85
cmpFunction · 0.85
write_errorFunction · 0.85
incr_growsFunction · 0.85

Tested by

no test coverage detected