File: units.go

package info (click to toggle)
mongo-tools 3.4.14-4
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 18,612 kB
  • sloc: python: 9,281; asm: 4,229; ansic: 1,606; sh: 817; makefile: 67; cpp: 59; lisp: 19
file content (68 lines) | stat: -rw-r--r-- 2,195 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package text

import (
	"fmt"
	"math"
)

const (
	decimal = 1000
	binary  = 1024
)

var (
	longByteUnits  = []string{"B", "KB", "MB", "GB"}
	shortByteUnits = []string{"B", "K", "M", "G"}
	shortBitUnits  = []string{"b", "k", "m", "g"}
)

// FormatByteAmount takes an int64 representing a size in bytes and
// returns a formatted string of a minimum amount of significant figures.
//  e.g. 12.4 GB, 0.0 B, 124.5 KB
func FormatByteAmount(size int64) string {
	return formatUnitAmount(binary, size, 3, longByteUnits)
}

// FormatMegabyteAmount is equivalent to FormatByteAmount but expects
// an amount of MB instead of bytes.
func FormatMegabyteAmount(size int64) string {
	return formatUnitAmount(binary, size*1024*1024, 3, shortByteUnits)
}

// FormatBits takes in a bit (not byte) count and returns a formatted string
// including units with three total digits (except if it is less than 1k)
// e.g. 12.0g, 0b, 124k
func FormatBits(size int64) string {
	return formatUnitAmount(decimal, size, 3, shortBitUnits)
}

// formatUnitAmount formats the size using the units and at least minDigits
// numbers, unless the number is already less than the base, where no decimal
// will be added
func formatUnitAmount(base, size int64, minDigits int, units []string) string {
	result := float64(size)
	divisor := float64(base)
	var shifts int
	// keep dividing by base and incrementing our unit until
	// we hit the right unit or run out of unit strings
	for ; result >= divisor && shifts < len(units)-1; shifts++ {
		result /= divisor
	}
	result = round(result, minDigits)

	var precision int                  // Number of digits to show after the decimal
	len := 1 + int(math.Log10(result)) // Number of pre-decimal digits in result
	if shifts != 0 && len < minDigits {
		// Add as many decimal digits as we can
		precision = minDigits - len
	}
	format := fmt.Sprintf("%%.%df%%s", precision)
	return fmt.Sprintf(format, result, units[shifts])
}

// round applies the gradeschool method to round to the nth place
func round(result float64, precision int) float64 {
	divisor := float64(math.Pow(10.0, float64(precision-1)))
	// round(x) == floor(x + 0.5)
	return math.Floor(result*divisor+0.5) / divisor
}