| // Package parsers provides helper functions to parse and validate different type |
| // of string. It can be hosts, unix addresses, tcp addresses, filters, kernel |
| // operating system versions. |
| package parsers // import "github.com/docker/docker/pkg/parsers" |
| |
| import ( |
| "fmt" |
| "strconv" |
| "strings" |
| ) |
| |
| // ParseKeyValueOpt parses and validates the specified string as a key/value |
| // pair (key=value). |
| func ParseKeyValueOpt(opt string) (key string, value string, err error) { |
| k, v, ok := strings.Cut(opt, "=") |
| if !ok { |
| return "", "", fmt.Errorf("unable to parse key/value option: %s", opt) |
| } |
| return strings.TrimSpace(k), strings.TrimSpace(v), nil |
| } |
| |
| // ParseUintListMaximum parses and validates the specified string as the value |
| // found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be |
| // one of the formats below. Note that duplicates are actually allowed in the |
| // input string. It returns a `map[int]bool` with available elements from `val` |
| // set to `true`. Values larger than `maximum` cause an error if max is non zero, |
| // in order to stop the map becoming excessively large. |
| // Supported formats: |
| // |
| // 7 |
| // 1-6 |
| // 0,3-4,7,8-10 |
| // 0-0,0,1-7 |
| // 03,1-3 <- this is gonna get parsed as [1,2,3] |
| // 3,2,1 |
| // 0-2,3,1 |
| func ParseUintListMaximum(val string, maximum int) (map[int]bool, error) { |
| return parseUintList(val, maximum) |
| } |
| |
| // ParseUintList parses and validates the specified string as the value |
| // found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be |
| // one of the formats below. Note that duplicates are actually allowed in the |
| // input string. It returns a `map[int]bool` with available elements from `val` |
| // set to `true`. |
| // Supported formats: |
| // |
| // 7 |
| // 1-6 |
| // 0,3-4,7,8-10 |
| // 0-0,0,1-7 |
| // 03,1-3 <- this is gonna get parsed as [1,2,3] |
| // 3,2,1 |
| // 0-2,3,1 |
| func ParseUintList(val string) (map[int]bool, error) { |
| return parseUintList(val, 0) |
| } |
| |
| func parseUintList(val string, maximum int) (map[int]bool, error) { |
| if val == "" { |
| return map[int]bool{}, nil |
| } |
| |
| availableInts := make(map[int]bool) |
| split := strings.Split(val, ",") |
| errInvalidFormat := fmt.Errorf("invalid format: %s", val) |
| |
| for _, r := range split { |
| if !strings.Contains(r, "-") { |
| v, err := strconv.Atoi(r) |
| if err != nil { |
| return nil, errInvalidFormat |
| } |
| if maximum != 0 && v > maximum { |
| return nil, fmt.Errorf("value of out range, maximum is %d", maximum) |
| } |
| availableInts[v] = true |
| } else { |
| minS, maxS, _ := strings.Cut(r, "-") |
| min, err := strconv.Atoi(minS) |
| if err != nil { |
| return nil, errInvalidFormat |
| } |
| max, err := strconv.Atoi(maxS) |
| if err != nil { |
| return nil, errInvalidFormat |
| } |
| if max < min { |
| return nil, errInvalidFormat |
| } |
| if maximum != 0 && max > maximum { |
| return nil, fmt.Errorf("value of out range, maximum is %d", maximum) |
| } |
| for i := min; i <= max; i++ { |
| availableInts[i] = true |
| } |
| } |
| } |
| return availableInts, nil |
| } |