...
1 package progress
2
3 import (
4 "fmt"
5 )
6
7
8 type UnitsNotationPosition int
9
10
11
12 const (
13 UnitsNotationPositionBefore UnitsNotationPosition = iota
14 UnitsNotationPositionAfter
15 )
16
17
18 type UnitsFormatter func(value int64) string
19
20
21 type Units struct {
22 Formatter UnitsFormatter
23 Notation string
24 NotationPosition UnitsNotationPosition
25 }
26
27
28 func (tu Units) Sprint(value int64) string {
29 formatter := tu.Formatter
30 if formatter == nil {
31 formatter = FormatNumber
32 }
33
34 formattedValue := formatter(value)
35 switch tu.NotationPosition {
36 case UnitsNotationPositionAfter:
37 return formattedValue + tu.Notation
38 default:
39 return tu.Notation + formattedValue
40 }
41 }
42
43 var (
44
45
46 UnitsDefault = Units{
47 Notation: "",
48 NotationPosition: UnitsNotationPositionBefore,
49 Formatter: FormatNumber,
50 }
51
52
53
54 UnitsBytes = Units{
55 Notation: "",
56 NotationPosition: UnitsNotationPositionBefore,
57 Formatter: FormatBytes,
58 }
59
60
61
62
63 UnitsCurrencyDollar = Units{
64 Notation: "$",
65 NotationPosition: UnitsNotationPositionBefore,
66 Formatter: FormatNumber,
67 }
68
69
70
71
72 UnitsCurrencyEuro = Units{
73 Notation: "₠",
74 NotationPosition: UnitsNotationPositionBefore,
75 Formatter: FormatNumber,
76 }
77
78
79
80
81 UnitsCurrencyPound = Units{
82 Notation: "£",
83 NotationPosition: UnitsNotationPositionBefore,
84 Formatter: FormatNumber,
85 }
86 )
87
88
89 func FormatBytes(value int64) string {
90 return formatNumber(value, map[int64]string{
91 1000000000000000: "PB",
92 1000000000000: "TB",
93 1000000000: "GB",
94 1000000: "MB",
95 1000: "KB",
96 0: "B",
97 })
98 }
99
100
101 func FormatNumber(value int64) string {
102 return formatNumber(value, map[int64]string{
103 1000000000000000: "Q",
104 1000000000000: "T",
105 1000000000: "B",
106 1000000: "M",
107 1000: "K",
108 0: "",
109 })
110 }
111
112 var (
113 unitScales = []int64{
114 1000000000000000,
115 1000000000000,
116 1000000000,
117 1000000,
118 1000,
119 }
120 )
121
122 func formatNumber(value int64, notations map[int64]string) string {
123 for _, unitScale := range unitScales {
124 if value >= unitScale {
125 return fmt.Sprintf("%.2f%s", float64(value)/float64(unitScale), notations[unitScale])
126 }
127 }
128 return fmt.Sprintf("%d%s", value, notations[0])
129 }
130
View as plain text