Merge pull request #34205 from yuwata/pretty-print-buffering

pretty-print: introduce WITH_BUFFERED_STDERR macro to enable buffering
This commit is contained in:
Mike Yuan
2024-09-04 14:34:21 +02:00
committed by GitHub
3 changed files with 45 additions and 33 deletions
+6 -20
View File
@@ -460,7 +460,7 @@ bool shall_tint_background(void) {
return cache != 0;
}
void draw_progress_bar_unbuffered(const char *prefix, double percentage) {
void draw_progress_bar_impl(const char *prefix, double percentage) {
fputc('\r', stderr);
if (prefix) {
fputs(prefix, stderr);
@@ -516,7 +516,7 @@ void draw_progress_bar_unbuffered(const char *prefix, double percentage) {
}
void clear_progress_bar_unbuffered(const char *prefix) {
void clear_progress_bar_impl(const char *prefix) {
fputc('\r', stderr);
if (terminal_is_dumb())
@@ -531,28 +531,14 @@ void clear_progress_bar_unbuffered(const char *prefix) {
}
void draw_progress_bar(const char *prefix, double percentage) {
/* We are going output a bunch of small strings that shall appear as a single line to STDERR which is
* unbuffered by default. Let's temporarily turn on full buffering, so that this is passed to the tty
* as a single buffer, to make things more efficient. */
char buffer[LONG_LINE_MAX];
setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
draw_progress_bar_unbuffered(prefix, percentage);
fflush(stderr);
/* Disable buffering again */
setvbuf(stderr, NULL, _IONBF, 0);
WITH_BUFFERED_STDERR;
draw_progress_bar_impl(prefix, percentage);
}
void clear_progress_bar(const char *prefix) {
char buffer[LONG_LINE_MAX];
setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
clear_progress_bar_unbuffered(prefix);
fflush(stderr);
setvbuf(stderr, NULL, _IONBF, 0);
WITH_BUFFERED_STDERR;
clear_progress_bar_impl(prefix);
}
+31 -2
View File
@@ -55,5 +55,34 @@ bool shall_tint_background(void);
void draw_progress_bar(const char *prefix, double percentage);
void clear_progress_bar(const char *prefix);
void draw_progress_bar_unbuffered(const char *prefix, double percentage);
void clear_progress_bar_unbuffered(const char *prefix);
void draw_progress_bar_impl(const char *prefix, double percentage);
void clear_progress_bar_impl(const char *prefix);
static inline FILE* enable_buffering(FILE *f, char *buffer, size_t size) {
assert(f);
assert(buffer);
assert(size > 0);
if (setvbuf(f, buffer, _IOFBF, size) != 0)
return NULL;
return f;
}
static inline void fflush_and_disable_bufferingp(FILE **p) {
assert(p);
if (*p) {
fflush(*p);
setvbuf(*p, NULL, _IONBF, 0); /* Disable buffering again. */
}
}
/* Even though the macro below is slightly generic, but it may not work most streams except for stderr,
* as stdout is buffered and fopen() enables buffering by default. */
#define _WITH_BUFFERED_STREAM(f, size, p) \
_unused_ _cleanup_(fflush_and_disable_bufferingp) FILE *p = \
enable_buffering(f, (char[size]) {}, size)
#define WITH_BUFFERED_STDERR \
_WITH_BUFFERED_STREAM(stderr, LONG_LINE_MAX, UNIQ_T(p, UNIQ))