github.com/walkingsparrow/docker@v1.4.2-0.20151218153551-b708a2249bfa/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 5 6 import ( 7 "fmt" 8 "strconv" 9 "strings" 10 ) 11 12 // PartParser parses and validates the specified string (data) using the specified template 13 // e.g. ip:public:private -> 192.168.0.1:80:8000 14 func PartParser(template, data string) (map[string]string, error) { 15 // ip:public:private 16 var ( 17 templateParts = strings.Split(template, ":") 18 parts = strings.Split(data, ":") 19 out = make(map[string]string, len(templateParts)) 20 ) 21 if len(parts) != len(templateParts) { 22 return nil, fmt.Errorf("Invalid format to parse. %s should match template %s", data, template) 23 } 24 25 for i, t := range templateParts { 26 value := "" 27 if len(parts) > i { 28 value = parts[i] 29 } 30 out[t] = value 31 } 32 return out, nil 33 } 34 35 // ParseKeyValueOpt parses and validates the specified string as a key/value pair (key=value) 36 func ParseKeyValueOpt(opt string) (string, string, error) { 37 parts := strings.SplitN(opt, "=", 2) 38 if len(parts) != 2 { 39 return "", "", fmt.Errorf("Unable to parse key/value option: %s", opt) 40 } 41 return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil 42 } 43 44 // ParsePortRange parses and validates the specified string as a port-range (8000-9000) 45 func ParsePortRange(ports string) (uint64, uint64, error) { 46 if ports == "" { 47 return 0, 0, fmt.Errorf("Empty string specified for ports.") 48 } 49 if !strings.Contains(ports, "-") { 50 start, err := strconv.ParseUint(ports, 10, 16) 51 end := start 52 return start, end, err 53 } 54 55 parts := strings.Split(ports, "-") 56 start, err := strconv.ParseUint(parts[0], 10, 16) 57 if err != nil { 58 return 0, 0, err 59 } 60 end, err := strconv.ParseUint(parts[1], 10, 16) 61 if err != nil { 62 return 0, 0, err 63 } 64 if end < start { 65 return 0, 0, fmt.Errorf("Invalid range specified for the Port: %s", ports) 66 } 67 return start, end, nil 68 } 69 70 // ParseUintList parses and validates the specified string as the value 71 // found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be 72 // one of the formats below. Note that duplicates are actually allowed in the 73 // input string. It returns a `map[int]bool` with available elements from `val` 74 // set to `true`. 75 // Supported formats: 76 // 7 77 // 1-6 78 // 0,3-4,7,8-10 79 // 0-0,0,1-7 80 // 03,1-3 <- this is gonna get parsed as [1,2,3] 81 // 3,2,1 82 // 0-2,3,1 83 func ParseUintList(val string) (map[int]bool, error) { 84 if val == "" { 85 return map[int]bool{}, nil 86 } 87 88 availableInts := make(map[int]bool) 89 split := strings.Split(val, ",") 90 errInvalidFormat := fmt.Errorf("invalid format: %s", val) 91 92 for _, r := range split { 93 if !strings.Contains(r, "-") { 94 v, err := strconv.Atoi(r) 95 if err != nil { 96 return nil, errInvalidFormat 97 } 98 availableInts[v] = true 99 } else { 100 split := strings.SplitN(r, "-", 2) 101 min, err := strconv.Atoi(split[0]) 102 if err != nil { 103 return nil, errInvalidFormat 104 } 105 max, err := strconv.Atoi(split[1]) 106 if err != nil { 107 return nil, errInvalidFormat 108 } 109 if max < min { 110 return nil, errInvalidFormat 111 } 112 for i := min; i <= max; i++ { 113 availableInts[i] = true 114 } 115 } 116 } 117 return availableInts, nil 118 }