From d8cc637b568db8958653e11c0f350354c02bf2ce Mon Sep 17 00:00:00 2001 From: Andrew Wood Date: Fri, 3 Apr 2026 21:49:41 +0100 Subject: [PATCH] Add the "%{ratio}" formatter (#67). --- Makefile.am | 1 + src/include/pv-internal.h | 2 ++ src/pv/display.c | 3 ++- src/pv/format/ratio.c | 50 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/pv/format/ratio.c diff --git a/Makefile.am b/Makefile.am index 936b152..486b230 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,6 +32,7 @@ src/pv/format/name.c \ src/pv/format/previousline.c \ src/pv/format/progressbar.c \ src/pv/format/rate.c \ +src/pv/format/ratio.c \ src/pv/format/sgr.c \ src/pv/format/timer.c \ src/pv/loop.c \ diff --git a/src/include/pv-internal.h b/src/include/pv-internal.h index d0231e9..1faf224 100644 --- a/src/include/pv-internal.h +++ b/src/include/pv-internal.h @@ -318,6 +318,7 @@ struct pvstate_s { bool showing_timer; /* set if showing timer */ bool showing_bytes; /* set if showing byte/line count */ + bool showing_ratio; /* set if showing monitoring in:out ratio */ bool showing_rate; /* set if showing transfer rate */ bool showing_last_written; /* set if displaying the last few bytes written */ bool showing_previous_line; /* set if displaying the previously output line */ @@ -602,6 +603,7 @@ pvdisplay_bytecount_t pv_formatter_fineta(pvformatter_args_t); pvdisplay_bytecount_t pv_formatter_rate(pvformatter_args_t); pvdisplay_bytecount_t pv_formatter_average_rate(pvformatter_args_t); pvdisplay_bytecount_t pv_formatter_bytes(pvformatter_args_t); +pvdisplay_bytecount_t pv_formatter_ratio(pvformatter_args_t); pvdisplay_bytecount_t pv_formatter_buffer_percent(pvformatter_args_t); pvdisplay_bytecount_t pv_formatter_last_written(pvformatter_args_t); pvdisplay_bytecount_t pv_formatter_previous_line(pvformatter_args_t); diff --git a/src/pv/display.c b/src/pv/display.c index 365b9b0..551e0b9 100644 --- a/src/pv/display.c +++ b/src/pv/display.c @@ -533,6 +533,7 @@ pvdisplay_bytecount_t pv_formatter_segmentcontent(char *content, pvformatter_arg { "b", &pv_formatter_bytes, false }, { "{bytes}", &pv_formatter_bytes, false }, { "{transferred}", &pv_formatter_bytes, false }, + { "{ratio}", &pv_formatter_ratio, false }, { "T", &pv_formatter_buffer_percent, false }, { "{buffer-percent}", &pv_formatter_buffer_percent, false }, { "A", &pv_formatter_last_written, false }, @@ -544,7 +545,6 @@ pvdisplay_bytecount_t pv_formatter_segmentcontent(char *content, pvformatter_arg { "{sgr:colour,...}", &pv_formatter_sgr, false }, { NULL, NULL, false } }; - /* TODO: formatter for ratio, for "-M both" */ return format_component_array; } @@ -621,6 +621,7 @@ static void pv__format_init(pvprogramstatus_t status, readonly_pvcontrol_t contr display->showing_timer = false; display->showing_bytes = false; + display->showing_ratio = false; display->showing_rate = false; display->showing_last_written = false; display->showing_previous_line = false; diff --git a/src/pv/format/ratio.c b/src/pv/format/ratio.c new file mode 100644 index 0000000..cce8567 --- /dev/null +++ b/src/pv/format/ratio.c @@ -0,0 +1,50 @@ +/* + * Formatter function for ratio of bytes transferred by the other monitored + * side to bytes transferred by this side. + * + * Copyright 2026 Andrew Wood + * + * License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'. + */ + +#include "config.h" +#include "pv.h" +#include "pv-internal.h" + + +/* + * Ratio of bytes or lines transferred by the other monitored side ("-M + * both") to the bytes or lines transferred by this side. + */ +pvdisplay_bytecount_t pv_formatter_ratio(pvformatter_args_t args) +{ + char content[128]; /* flawfinder: ignore - always bounded */ + + args->display->showing_ratio = true; + + if (0 == args->buffer_size) + return 0; + + content[0] = '\0'; + + if (0 == args->transfer->otherside_transferred || 0 == args->transfer->transferred) { + (void) pv_snprintf(content, sizeof(content), "%s:%s", "-", "-"); + } else if (args->transfer->otherside_transferred == args->transfer->transferred) { + (void) pv_snprintf(content, sizeof(content), "%d:%d", 1, 1); + } else { + long double side1, side2, ratio; + + side1 = (long double) (args->transfer->otherside_transferred); + side2 = (long double) (args->transfer->transferred); + + if (side1 > side2) { + ratio = side1 / side2; + (void) pv_snprintf(content, sizeof(content), "%.4Lg:%d", ratio, 1); + } else { + ratio = side2 / side1; + (void) pv_snprintf(content, sizeof(content), "%d:%.4Lg", 1, ratio); + } + } + + return pv_formatter_segmentcontent(content, args); +}