github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/pkg/parsers/parsers.go (about)

     1  // Package parsers provides helper functions to parse and validate different type
     2  // of string. It can be hosts, unix addresses, tcp addresses, filters, kernel
     3  // operating system versions.
     4  package parsers // import "github.com/docker/docker/pkg/parsers"
     5  
     6  import (
     7  	"fmt"
     8  	"strconv"
     9  	"strings"
    10  )
    11  
    12  // ParseKeyValueOpt parses and validates the specified string as a key/value pair (key=value)
    13  func ParseKeyValueOpt(opt string) (string, string, error) {
    14  	parts := strings.SplitN(opt, "=", 2)
    15  	if len(parts) != 2 {
    16  		return "", "", fmt.Errorf("Unable to parse key/value option: %s", opt)
    17  	}
    18  	return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
    19  }
    20  
    21  // ParseUintListMaximum parses and validates the specified string as the value
    22  // found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be
    23  // one of the formats below. Note that duplicates are actually allowed in the
    24  // input string. It returns a `map[int]bool` with available elements from `val`
    25  // set to `true`. Values larger than `maximum` cause an error if max is non zero,
    26  // in order to stop the map becoming excessively large.
    27  // Supported formats:
    28  //     7
    29  //     1-6
    30  //     0,3-4,7,8-10
    31  //     0-0,0,1-7
    32  //     03,1-3      <- this is gonna get parsed as [1,2,3]
    33  //     3,2,1
    34  //     0-2,3,1
    35  func ParseUintListMaximum(val string, maximum int) (map[int]bool, error) {
    36  	return parseUintList(val, maximum)
    37  }
    38  
    39  // ParseUintList parses and validates the specified string as the value
    40  // found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be
    41  // one of the formats below. Note that duplicates are actually allowed in the
    42  // input string. It returns a `map[int]bool` with available elements from `val`
    43  // set to `true`.
    44  // Supported formats:
    45  //     7
    46  //     1-6
    47  //     0,3-4,7,8-10
    48  //     0-0,0,1-7
    49  //     03,1-3      <- this is gonna get parsed as [1,2,3]
    50  //     3,2,1
    51  //     0-2,3,1
    52  func ParseUintList(val string) (map[int]bool, error) {
    53  	return parseUintList(val, 0)
    54  }
    55  
    56  func parseUintList(val string, maximum int) (map[int]bool, error) {
    57  	if val == "" {
    58  		return map[int]bool{}, nil
    59  	}
    60  
    61  	availableInts := make(map[int]bool)
    62  	split := strings.Split(val, ",")
    63  	errInvalidFormat := fmt.Errorf("invalid format: %s", val)
    64  
    65  	for _, r := range split {
    66  		if !strings.Contains(r, "-") {
    67  			v, err := strconv.Atoi(r)
    68  			if err != nil {
    69  				return nil, errInvalidFormat
    70  			}
    71  			if maximum != 0 && v > maximum {
    72  				return nil, fmt.Errorf("value of out range, maximum is %d", maximum)
    73  			}
    74  			availableInts[v] = true
    75  		} else {
    76  			split := strings.SplitN(r, "-", 2)
    77  			min, err := strconv.Atoi(split[0])
    78  			if err != nil {
    79  				return nil, errInvalidFormat
    80  			}
    81  			max, err := strconv.Atoi(split[1])
    82  			if err != nil {
    83  				return nil, errInvalidFormat
    84  			}
    85  			if max < min {
    86  				return nil, errInvalidFormat
    87  			}
    88  			if maximum != 0 && max > maximum {
    89  				return nil, fmt.Errorf("value of out range, maximum is %d", maximum)
    90  			}
    91  			for i := min; i <= max; i++ {
    92  				availableInts[i] = true
    93  			}
    94  		}
    95  	}
    96  	return availableInts, nil
    97  }