dotcloud/docker

View on GitHub
pkg/parsers/parsers.go

Summary

Maintainability
A
2 hrs
Test Coverage
// 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
}