80 lines
1.4 KiB
Go
80 lines
1.4 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"math"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
var units []string = []string{"KB", "MB", "GB", "B"}
|
||
|
|
||
|
// ByteSize represents a number of bytes
|
||
|
type ByteSize struct {
|
||
|
HumanRep string
|
||
|
NumberRep int64
|
||
|
}
|
||
|
|
||
|
// Byte size size suffixes.
|
||
|
const (
|
||
|
B int64 = 1
|
||
|
KB int64 = 1 << (10 * iota)
|
||
|
MB
|
||
|
GB
|
||
|
)
|
||
|
|
||
|
// Used to convert user input to ByteSize
|
||
|
var unitMap = map[string]int64{
|
||
|
"B": B,
|
||
|
"KB": KB,
|
||
|
"MB": MB,
|
||
|
"GB": GB,
|
||
|
}
|
||
|
|
||
|
// Converts string representaiion of a sistring representaiion of sizeze into ByteSize
|
||
|
func (b *ByteSize) ParseFromString(s string) error {
|
||
|
s = strings.TrimSpace(s)
|
||
|
b.HumanRep = s
|
||
|
var fragments []string
|
||
|
unitFound := ""
|
||
|
|
||
|
for _, unit := range units {
|
||
|
fragments = strings.Split(s, unit)
|
||
|
if len(fragments) == 2 {
|
||
|
unitFound = unit
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if len(unitFound) == 0 {
|
||
|
return fmt.Errorf("unrecognized size suffix")
|
||
|
}
|
||
|
|
||
|
value, err := strconv.ParseFloat(fragments[0], 64)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
unit, ok := unitMap[strings.ToUpper(unitFound)]
|
||
|
if !ok {
|
||
|
return fmt.Errorf("unrecognized size suffix %s", fragments[1])
|
||
|
}
|
||
|
|
||
|
b.NumberRep = int64(value * float64(unit))
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Converts a number of bytes into ByteSize
|
||
|
func (b *ByteSize) ParseFromNumber(n int64) {
|
||
|
b.NumberRep = n
|
||
|
bf := float64(n)
|
||
|
for _, unit := range []string{"", "K", "M", "G"} {
|
||
|
if math.Abs(bf) < 1024.0 {
|
||
|
b.HumanRep = fmt.Sprintf("%3.1f%sB", bf, unit)
|
||
|
return
|
||
|
}
|
||
|
bf /= 1024.0
|
||
|
}
|
||
|
b.HumanRep = fmt.Sprintf("%.1fTB", bf)
|
||
|
}
|