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  }