github.com/michael-k/docker@v1.7.0-rc2/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  // using SI standard (eg. "44kB", "17MB")
    53  func HumanSize(size float64) string {
    54  	return CustomSize("%.4g %s", float64(size), 1000.0, decimapAbbrs)
    55  }
    56  
    57  func BytesSize(size float64) string {
    58  	return CustomSize("%.4g %s", size, 1024.0, binaryAbbrs)
    59  }
    60  
    61  // FromHumanSize returns an integer from a human-readable specification of a
    62  // size using SI standard (eg. "44kB", "17MB")
    63  func FromHumanSize(size string) (int64, error) {
    64  	return parseSize(size, decimalMap)
    65  }
    66  
    67  // RAMInBytes parses a human-readable string representing an amount of RAM
    68  // in bytes, kibibytes, mebibytes, gibibytes, or tebibytes and
    69  // returns the number of bytes, or -1 if the string is unparseable.
    70  // Units are case-insensitive, and the 'b' suffix is optional.
    71  func RAMInBytes(size string) (int64, error) {
    72  	return parseSize(size, binaryMap)
    73  }
    74  
    75  // Parses the human-readable size string into the amount it represents
    76  func parseSize(sizeStr string, uMap unitMap) (int64, error) {
    77  	matches := sizeRegex.FindStringSubmatch(sizeStr)
    78  	if len(matches) != 3 {
    79  		return -1, fmt.Errorf("invalid size: '%s'", sizeStr)
    80  	}
    81  
    82  	size, err := strconv.ParseInt(matches[1], 10, 0)
    83  	if err != nil {
    84  		return -1, err
    85  	}
    86  
    87  	unitPrefix := strings.ToLower(matches[2])
    88  	if mul, ok := uMap[unitPrefix]; ok {
    89  		size *= mul
    90  	}
    91  
    92  	return size, nil
    93  }