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.
4package parsers // import "github.com/docker/docker/pkg/parsers"
5
6import (
7	"fmt"
8	"strconv"
9	"strings"
10)
11
12// ParseKeyValueOpt parses and validates the specified string as a key/value pair (key=value)
13func 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// ParseUintList 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`.
26// Supported formats:
27//     7
28//     1-6
29//     0,3-4,7,8-10
30//     0-0,0,1-7
31//     03,1-3      <- this is gonna get parsed as [1,2,3]
32//     3,2,1
33//     0-2,3,1
34func ParseUintList(val string) (map[int]bool, error) {
35	if val == "" {
36		return map[int]bool{}, nil
37	}
38
39	availableInts := make(map[int]bool)
40	split := strings.Split(val, ",")
41	errInvalidFormat := fmt.Errorf("invalid format: %s", val)
42
43	for _, r := range split {
44		if !strings.Contains(r, "-") {
45			v, err := strconv.Atoi(r)
46			if err != nil {
47				return nil, errInvalidFormat
48			}
49			availableInts[v] = true
50		} else {
51			split := strings.SplitN(r, "-", 2)
52			min, err := strconv.Atoi(split[0])
53			if err != nil {
54				return nil, errInvalidFormat
55			}
56			max, err := strconv.Atoi(split[1])
57			if err != nil {
58				return nil, errInvalidFormat
59			}
60			if max < min {
61				return nil, errInvalidFormat
62			}
63			for i := min; i <= max; i++ {
64				availableInts[i] = true
65			}
66		}
67	}
68	return availableInts, nil
69}
70