diff options
| author | bingoohuang <bingoo.huang@gmail.com> | 2021-04-26 18:48:34 +0800 |
|---|---|---|
| committer | bingoohuang <bingoo.huang@gmail.com> | 2021-04-26 18:48:34 +0800 |
| commit | 31f1cdeac281fb88a3d03743f9796f81e1d74378 (patch) | |
| tree | 109fc3d221ab9fc629afc1c1711268066b31a0e3 /weed/util/bytes.go | |
| parent | d861cbd81b75b6684c971ac00e33685e6575b833 (diff) | |
| download | seaweedfs-31f1cdeac281fb88a3d03743f9796f81e1d74378.tar.xz seaweedfs-31f1cdeac281fb88a3d03743f9796f81e1d74378.zip | |
minFreeSpace argument allows size like 10GiB
Diffstat (limited to 'weed/util/bytes.go')
| -rw-r--r-- | weed/util/bytes.go | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/weed/util/bytes.go b/weed/util/bytes.go index c2a4df108..260e5067e 100644 --- a/weed/util/bytes.go +++ b/weed/util/bytes.go @@ -5,8 +5,13 @@ import ( "crypto/md5" "crypto/rand" "encoding/base64" + "errors" "fmt" "io" + "math" + "strconv" + "strings" + "unicode" ) // BytesToHumanReadable returns the converted human readable representation of the bytes. @@ -161,3 +166,105 @@ func NewBytesReader(b []byte) *BytesReader { Reader: bytes.NewReader(b), } } + +// EmptyTo returns to if s is empty. +func EmptyTo(s, to string) string { + if s == "" { + return to + } + + return s +} + +var ErrMinFreeSpaceBadValue = errors.New("minFreeSpace is invalid") + +// ParseMinFreeSpace parses min free space expression s as percentage like 1,10 or human readable size like 10G +func ParseMinFreeSpace(s string) (float32, error) { + if value, e := strconv.ParseFloat(s, 32); e == nil { + if value < 0 || value > 100 { + return 0, ErrMinFreeSpaceBadValue + } + return float32(value), nil + } else if directSize, e2 := ParseBytes(s); e2 == nil { + if directSize <= 100 { + return 0, ErrMinFreeSpaceBadValue + } + return float32(directSize), nil + } + + return 0, ErrMinFreeSpaceBadValue +} + +// ParseBytes parses a string representation of bytes into the number +// of bytes it represents. +// +// See Also: Bytes, IBytes. +// +// ParseBytes("42MB") -> 42000000, nil +// ParseBytes("42 MB") -> 42000000, nil +// ParseBytes("42 mib") -> 44040192, nil +func ParseBytes(s string) (uint64, error) { + lastDigit := 0 + hasComma := false + for _, r := range s { + if !(unicode.IsDigit(r) || r == '.' || r == ',') { + break + } + if r == ',' { + hasComma = true + } + lastDigit++ + } + + num := s[:lastDigit] + if hasComma { + num = strings.Replace(num, ",", "", -1) + } + + f, err := strconv.ParseFloat(num, 64) + if err != nil { + return 0, err + } + + extra := strings.ToLower(strings.TrimSpace(s[lastDigit:])) + if m, ok := bytesSizeTable[extra]; ok { + f *= float64(m) + if f >= math.MaxUint64 { + return 0, fmt.Errorf("too large: %v", s) + } + return uint64(f), nil + } + + return 0, fmt.Errorf("unhandled size name: %v", extra) +} + +var bytesSizeTable = map[string]uint64{ + "b": Byte, "kib": KiByte, "kb": KByte, "mib": MiByte, "mb": MByte, "gib": GiByte, "gb": GByte, + "tib": TiByte, "tb": TByte, "pib": PiByte, "pb": PByte, "eib": EiByte, "eb": EByte, + // Without suffix + "": Byte, "ki": KiByte, "k": KByte, "mi": MiByte, "m": MByte, "gi": GiByte, "g": GByte, + "ti": TiByte, "t": TByte, "pi": PiByte, "p": PByte, "ei": EiByte, "e": EByte, +} + +// IEC Sizes. +// kibis of bits +const ( + Byte = 1 << (iota * 10) + KiByte + MiByte + GiByte + TiByte + PiByte + EiByte +) + +// SI Sizes. +const ( + IByte = 1 + KByte = IByte * 1000 + MByte = KByte * 1000 + GByte = MByte * 1000 + TByte = GByte * 1000 + PByte = TByte * 1000 + EByte = PByte * 1000 +) |
