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