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  }