github.com/shiroyuki/docker@v1.9.0/pkg/units/size.go (about) 1 package units 2 3 import ( 4 "fmt" 5 "regexp" 6 "strconv" 7 "strings" 8 ) 9 10 // See: http://en.wikipedia.org/wiki/Binary_prefix 11 const ( 12 // Decimal 13 14 KB = 1000 15 MB = 1000 * KB 16 GB = 1000 * MB 17 TB = 1000 * GB 18 PB = 1000 * TB 19 20 // Binary 21 22 KiB = 1024 23 MiB = 1024 * KiB 24 GiB = 1024 * MiB 25 TiB = 1024 * GiB 26 PiB = 1024 * TiB 27 ) 28 29 type unitMap map[string]int64 30 31 var ( 32 decimalMap = unitMap{"k": KB, "m": MB, "g": GB, "t": TB, "p": PB} 33 binaryMap = unitMap{"k": KiB, "m": MiB, "g": GiB, "t": TiB, "p": PiB} 34 sizeRegex = regexp.MustCompile(`^(\d+)([kKmMgGtTpP])?[bB]?$`) 35 ) 36 37 var decimapAbbrs = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"} 38 var binaryAbbrs = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"} 39 40 // CustomSize returns a human-readable approximation of a size 41 // using custom format. 42 func CustomSize(format string, size float64, base float64, _map []string) string { 43 i := 0 44 for size >= base { 45 size = size / base 46 i++ 47 } 48 return fmt.Sprintf(format, size, _map[i]) 49 } 50 51 // HumanSize returns a human-readable approximation of a size 52 // capped at 4 valid numbers (eg. "2.746 MB", "796 KB"). 53 func HumanSize(size float64) string { 54 return CustomSize("%.4g %s", size, 1000.0, decimapAbbrs) 55 } 56 57 // BytesSize returns a human-readable size in bytes, kibibytes, 58 // mebibytes, gibibytes, or tebibytes (eg. "44kiB", "17MiB"). 59 func BytesSize(size float64) string { 60 return CustomSize("%.4g %s", size, 1024.0, binaryAbbrs) 61 } 62 63 // FromHumanSize returns an integer from a human-readable specification of a 64 // size using SI standard (eg. "44kB", "17MB"). 65 func FromHumanSize(size string) (int64, error) { 66 return parseSize(size, decimalMap) 67 } 68 69 // RAMInBytes parses a human-readable string representing an amount of RAM 70 // in bytes, kibibytes, mebibytes, gibibytes, or tebibytes and 71 // returns the number of bytes, or -1 if the string is unparseable. 72 // Units are case-insensitive, and the 'b' suffix is optional. 73 func RAMInBytes(size string) (int64, error) { 74 return parseSize(size, binaryMap) 75 } 76 77 // Parses the human-readable size string into the amount it represents. 78 func parseSize(sizeStr string, uMap unitMap) (int64, error) { 79 matches := sizeRegex.FindStringSubmatch(sizeStr) 80 if len(matches) != 3 { 81 return -1, fmt.Errorf("invalid size: '%s'", sizeStr) 82 } 83 84 size, err := strconv.ParseInt(matches[1], 10, 0) 85 if err != nil { 86 return -1, err 87 } 88 89 unitPrefix := strings.ToLower(matches[2]) 90 if mul, ok := uMap[unitPrefix]; ok { 91 size *= mul 92 } 93 94 return size, nil 95 }