first commit
This commit is contained in:
79
progress/format.go
Normal file
79
progress/format.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package progress
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// humanSize formats a byte count by abbreviating it: divide by
|
||||
// 1024 while the value is at least one unit and a larger unit remains, then bump
|
||||
// to the next unit when the quotient is >=922 (so 0.9Mi shows instead of 922Ki).
|
||||
// The unit ladder is capped at Gi, so a terabyte prints
|
||||
// as "1024.0GiB". When human is false it prints the raw integer with a B suffix.
|
||||
func humanSize(n int64, human bool) string {
|
||||
if !human {
|
||||
return fmt.Sprintf("%dB", n)
|
||||
}
|
||||
const unit = 1024
|
||||
if n < unit {
|
||||
return fmt.Sprintf("%dB", n)
|
||||
}
|
||||
// "KMG" caps the ladder at Gi (the units {"","Ki","Mi","Gi"}).
|
||||
const suffixes = "KMG"
|
||||
div, exp := int64(unit), 0
|
||||
for v := n / unit; v >= unit && exp+1 < len(suffixes); v /= unit {
|
||||
div *= unit
|
||||
exp++
|
||||
}
|
||||
// Bump to the next unit when the quotient is >=922 and a unit remains, so
|
||||
// 922*1024 bytes reads as 0.9MiB rather than 922KiB.
|
||||
if q := n / div; q >= 922 && exp+1 < len(suffixes) {
|
||||
div *= unit
|
||||
exp++
|
||||
}
|
||||
val := float64(n) / float64(div)
|
||||
suffix := suffixes[exp]
|
||||
// One decimal for small mantissas and for anything that overflowed the
|
||||
// capped Gi unit (1024.0GiB and up); a bare integer otherwise (e.g. 20MiB).
|
||||
if val < 10 || exp == len(suffixes)-1 && val >= unit {
|
||||
return fmt.Sprintf("%.1f%ciB", val, suffix)
|
||||
}
|
||||
return fmt.Sprintf("%.0f%ciB", val, suffix)
|
||||
}
|
||||
|
||||
// speed formats a bytes-per-second rate. The DL:/UL: fields show the bare
|
||||
// abbreviated size with no "/s" suffix.
|
||||
func speed(bytesPerSec int64, human bool) string {
|
||||
return humanSize(bytesPerSec, human)
|
||||
}
|
||||
|
||||
// secfmt renders a duration as "1h2m3s", appending each unit only when it is
|
||||
// nonzero (but still showing seconds when the whole input is 0):
|
||||
// 3600s->"1h", 120s->"2m", 3720s->"1h2m". A non-positive or absurd
|
||||
// duration renders as "--".
|
||||
func secfmt(d time.Duration) string {
|
||||
s := int64(d.Seconds())
|
||||
if s < 0 || d > 99*time.Hour {
|
||||
return "--"
|
||||
}
|
||||
h, m, sec := s/3600, (s%3600)/60, s%60
|
||||
var str string
|
||||
if h > 0 {
|
||||
str += fmt.Sprintf("%dh", h)
|
||||
}
|
||||
if m > 0 {
|
||||
str += fmt.Sprintf("%dm", m)
|
||||
}
|
||||
if sec > 0 || s == 0 {
|
||||
str += fmt.Sprintf("%ds", sec)
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
// percent returns completed/total as a 0-100 integer, or 0 when total is unknown.
|
||||
func percent(completed, total int64) int {
|
||||
if total <= 0 {
|
||||
return 0
|
||||
}
|
||||
return int(completed * 100 / total)
|
||||
}
|
||||
Reference in New Issue
Block a user