123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- package tree
- import (
- "errors"
- "fmt"
- "math"
- "regexp"
- "strconv"
- "sync"
- )
- var ErrUnparsableSize = errors.New("unparsable size")
- var matchSize = regexp.MustCompile("^(\\d+(\\.\\d+)?)([KMGTP]?B?)$")
- type ByteSize uint
- const (
- B ByteSize = 1 << (10 * iota)
- KB
- MB
- GB
- TB
- PB
- )
- func isLastLevel(node Node, maxLevel int) bool {
- return maxLevel-1 == node.Level()
- }
- func parseUnit(unit string) ByteSize {
- switch unit {
- case "B":
- return B
- case "KB":
- return KB
- case "MB":
- return MB
- case "GB":
- return GB
- case "TB":
- return TB
- case "PB":
- // I reckon this will never happen, but you never know
- return PB
- default:
- panic(ErrUnknownUnit)
- }
- }
- func parseUnitSafe(unit string) (ByteSize, error) {
- var returnVal ByteSize
- var err error
- defer func() {
- if r := recover(); r != nil {
- returnVal = 0
- err = ErrUnparsableSize
- }
- }()
- returnVal = parseUnit(unit)
- return returnVal, err
- }
- func fmtUnit(unit ByteSize) string {
- switch unit {
- case B:
- return "B"
- case KB:
- return "KB"
- case MB:
- return "MB"
- case GB:
- return "GB"
- case TB:
- return "TB"
- case PB:
- // I reckon this will never happen, but you never know
- return "PB"
- default:
- panic(ErrUnknownUnit)
- }
- }
- func fmtSize(size int64, unit ByteSize) string {
- var dimension float64
- dimension = float64(size) / float64(unit)
- return fmt.Sprintf("%.2f %s", dimension, fmtUnit(unit))
- }
- func ParseSize(size string) (int64, error) {
- result := matchSize.FindStringSubmatch(size)
- sizeNum := result[1]
- if sizeNum == "" {
- return 0, ErrUnparsableSize
- }
- unit, err := parseUnitSafe(result[3])
- if err != nil {
- return 0, err
- }
- num, err := strconv.ParseFloat(sizeNum, 64)
- if err != nil {
- return 0, err
- }
- return int64(math.Floor(num * float64(unit))), nil
- }
- func isIntoLimits(size, min, max int64) bool {
- if min <= size {
- if max == 0 {
- return true
- }
- if size <= max {
- return true
- }
- }
- return false
- }
- func merge(cs []<-chan int64) <-chan int64 {
- var wg sync.WaitGroup
- out := make(chan int64)
- // Start an output goroutine for each input channel in cs. output
- // copies values from c to out until c is closed, then calls wg.Done.
- output := func(c <-chan int64) {
- for n := range c {
- out <- n
- }
- wg.Done()
- }
- wg.Add(len(cs))
- for _, c := range cs {
- go output(c)
- }
- // Start a goroutine to close out once all the output goroutines are
- // done. This must start after the wg.Add call.
- go func() {
- wg.Wait()
- close(out)
- }()
- return out
- }
|