parsers.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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 // import "github.com/docker/docker/pkg/parsers"
  5. import (
  6. "fmt"
  7. "strconv"
  8. "strings"
  9. )
  10. // ParseKeyValueOpt parses and validates the specified string as a key/value
  11. // pair (key=value).
  12. func ParseKeyValueOpt(opt string) (key string, value string, err error) {
  13. k, v, ok := strings.Cut(opt, "=")
  14. if !ok {
  15. return "", "", fmt.Errorf("unable to parse key/value option: %s", opt)
  16. }
  17. return strings.TrimSpace(k), strings.TrimSpace(v), nil
  18. }
  19. // ParseUintListMaximum parses and validates the specified string as the value
  20. // found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be
  21. // one of the formats below. Note that duplicates are actually allowed in the
  22. // input string. It returns a `map[int]bool` with available elements from `val`
  23. // set to `true`. Values larger than `maximum` cause an error if max is non zero,
  24. // in order to stop the map becoming excessively large.
  25. // Supported formats:
  26. //
  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
  34. func ParseUintListMaximum(val string, maximum int) (map[int]bool, error) {
  35. return parseUintList(val, maximum)
  36. }
  37. // ParseUintList parses and validates the specified string as the value
  38. // found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be
  39. // one of the formats below. Note that duplicates are actually allowed in the
  40. // input string. It returns a `map[int]bool` with available elements from `val`
  41. // set to `true`.
  42. // Supported formats:
  43. //
  44. // 7
  45. // 1-6
  46. // 0,3-4,7,8-10
  47. // 0-0,0,1-7
  48. // 03,1-3 <- this is gonna get parsed as [1,2,3]
  49. // 3,2,1
  50. // 0-2,3,1
  51. func ParseUintList(val string) (map[int]bool, error) {
  52. return parseUintList(val, 0)
  53. }
  54. func parseUintList(val string, maximum int) (map[int]bool, error) {
  55. if val == "" {
  56. return map[int]bool{}, nil
  57. }
  58. availableInts := make(map[int]bool)
  59. split := strings.Split(val, ",")
  60. errInvalidFormat := fmt.Errorf("invalid format: %s", val)
  61. for _, r := range split {
  62. if !strings.Contains(r, "-") {
  63. v, err := strconv.Atoi(r)
  64. if err != nil {
  65. return nil, errInvalidFormat
  66. }
  67. if maximum != 0 && v > maximum {
  68. return nil, fmt.Errorf("value of out range, maximum is %d", maximum)
  69. }
  70. availableInts[v] = true
  71. } else {
  72. minS, maxS, _ := strings.Cut(r, "-")
  73. min, err := strconv.Atoi(minS)
  74. if err != nil {
  75. return nil, errInvalidFormat
  76. }
  77. max, err := strconv.Atoi(maxS)
  78. if err != nil {
  79. return nil, errInvalidFormat
  80. }
  81. if max < min {
  82. return nil, errInvalidFormat
  83. }
  84. if maximum != 0 && max > maximum {
  85. return nil, fmt.Errorf("value of out range, maximum is %d", maximum)
  86. }
  87. for i := min; i <= max; i++ {
  88. availableInts[i] = true
  89. }
  90. }
  91. }
  92. return availableInts, nil
  93. }