aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-02-07 17:47:39 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-02-07 17:47:39 +0100
commitab843e3244e98f92e16b9c9c1f06dbab87e97175 (patch)
treec534b6d979ce22b71970b87ab3f6a725793aac25
parent2bd5b4e9a0442102ab937ed771b2c11142afb744 (diff)
downloadbusybox-w32-ab843e3244e98f92e16b9c9c1f06dbab87e97175.tar.gz
busybox-w32-ab843e3244e98f92e16b9c9c1f06dbab87e97175.tar.bz2
busybox-w32-ab843e3244e98f92e16b9c9c1f06dbab87e97175.zip
libbb: shrink wget/tftp progress indicator code for 32-bit
function old new delta bb_progress_update 756 654 -102 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--libbb/progress.c78
1 files changed, 38 insertions, 40 deletions
diff --git a/libbb/progress.c b/libbb/progress.c
index 64e6529ac..17272fd17 100644
--- a/libbb/progress.c
+++ b/libbb/progress.c
@@ -71,7 +71,7 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
71 uoff_t transferred, 71 uoff_t transferred,
72 uoff_t totalsize) 72 uoff_t totalsize)
73{ 73{
74 uoff_t beg_and_transferred; 74 unsigned beg_and_transferred; /* does not need uoff_t, see scaling code below */
75 unsigned since_last_update, elapsed; 75 unsigned since_last_update, elapsed;
76 int notty; 76 int notty;
77 int kiloscale; 77 int kiloscale;
@@ -102,33 +102,24 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
102 * without risking overflow: we guarantee 10 highest bits to be 0. 102 * without risking overflow: we guarantee 10 highest bits to be 0.
103 * Introduced error is less than 1 / 2^12 ~= 0.025% 103 * Introduced error is less than 1 / 2^12 ~= 0.025%
104 */ 104 */
105 if (ULONG_MAX > 0xffffffff || sizeof(off_t) == 4 || sizeof(off_t) != 8) { 105 while (totalsize >= (1 << 22)) {
106 /* 106 totalsize >>= 10;
107 * 64-bit CPU || small off_t: in either case, 107 beg_size >>= 10;
108 * >> is cheap, single-word operation. 108 transferred >>= 10;
109 * ... || strange off_t: also use this code 109 kiloscale++;
110 * (it is safe, just suboptimal wrt code size),
111 * because 32/64 optimized one works only for 64-bit off_t.
112 */
113 if (totalsize >= (1 << 22)) {
114 totalsize >>= 10;
115 beg_size >>= 10;
116 transferred >>= 10;
117 kiloscale = 1;
118 }
119 } else {
120 /* 32-bit CPU and 64-bit off_t.
121 * Use a 40-bit shift, it is easier to do on 32-bit CPU.
122 */
123/* ONE suppresses "warning: shift count >= width of type" */
124#define ONE (sizeof(off_t) > 4)
125 if (totalsize >= (uoff_t)(1ULL << 54*ONE)) {
126 totalsize = (uint32_t)(totalsize >> 32*ONE) >> 8;
127 beg_size = (uint32_t)(beg_size >> 32*ONE) >> 8;
128 transferred = (uint32_t)(transferred >> 32*ONE) >> 8;
129 kiloscale = 4;
130 }
131 } 110 }
111 /* If they were huge, now they are scaled down to [4194303,4096] range.
112 * (N * totalsize) won't overflow 32 bits for N up to 1024.
113 * The downside is that files larger than 4194303 kbytes (>4GB)
114 * never show kbytes download size, they show "0M","1M"... right away
115 * since kiloscale is already >1.
116 */
117#if ULONG_MAX == 0xffffffff
118/* 32-bit CPU, uoff_t arithmetic is complex on it, cast variables to narrower types */
119# define totalsize ((unsigned)totalsize)
120# define beg_size ((unsigned)beg_size)
121# define transferred ((unsigned)transferred)
122#endif
132 123
133 notty = !isatty(STDERR_FILENO); 124 notty = !isatty(STDERR_FILENO);
134 125
@@ -146,13 +137,18 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
146 137
147 barlength = get_terminal_width(2) - 49; 138 barlength = get_terminal_width(2) - 49;
148 if (barlength > 0) { 139 if (barlength > 0) {
149 /* god bless gcc for variable arrays :) */ 140 if (barlength > 999)
150 char buf[barlength + 1]; 141 barlength = 999;
151 unsigned stars = (unsigned)barlength * beg_and_transferred / totalsize; 142 {
152 memset(buf, ' ', barlength); 143 /* god bless gcc for variable arrays :) */
153 buf[barlength] = '\0'; 144 char buf[barlength + 1];
154 memset(buf, '*', stars); 145 unsigned stars = (unsigned)barlength * beg_and_transferred / totalsize;
155 fprintf(stderr, " |%s|", buf); 146 /* can't overflow ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
147 memset(buf, ' ', barlength);
148 buf[barlength] = '\0';
149 memset(buf, '*', stars);
150 fprintf(stderr, " |%s|", buf);
151 }
156 } 152 }
157 } 153 }
158 154
@@ -184,16 +180,18 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
184 fprintf(stderr, " --:--:-- ETA"); 180 fprintf(stderr, " --:--:-- ETA");
185 } else { 181 } else {
186 unsigned eta, secs, hours; 182 unsigned eta, secs, hours;
183 unsigned bytes;
187 184
188 totalsize -= beg_size; /* now it's "total to upload" */ 185 bytes = totalsize - beg_size;
189 186
190 /* Estimated remaining time = 187 /* Estimated remaining time =
191 * estimated_sec_to_dl_totalsize_bytes - elapsed_sec = 188 * estimated_sec_to_dl_bytes - elapsed_sec =
192 * totalsize / average_bytes_sec_so_far - elapsed = 189 * bytes / average_bytes_sec_so_far - elapsed =
193 * totalsize / (transferred/elapsed) - elapsed = 190 * bytes / (transferred/elapsed) - elapsed =
194 * totalsize * elapsed / transferred - elapsed 191 * bytes * elapsed / transferred - elapsed
195 */ 192 */
196 eta = totalsize * elapsed / transferred - elapsed; 193 eta = (unsigned long)bytes * elapsed / transferred - elapsed;
194 /* if 32bit, can overflow ^^^^^^^^^^, but this would only show bad ETA */
197 if (eta >= 1000*60*60) 195 if (eta >= 1000*60*60)
198 eta = 1000*60*60 - 1; 196 eta = 1000*60*60 - 1;
199 secs = eta % 3600; 197 secs = eta % 3600;