parse.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. package filters
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "regexp"
  6. "strings"
  7. )
  8. type Args map[string][]string
  9. // Parse the argument to the filter flag. Like
  10. //
  11. // `docker ps -f 'created=today' -f 'image.name=ubuntu*'`
  12. //
  13. // If prev map is provided, then it is appended to, and returned. By default a new
  14. // map is created.
  15. func ParseFlag(arg string, prev Args) (Args, error) {
  16. var filters Args = prev
  17. if prev == nil {
  18. filters = Args{}
  19. }
  20. if len(arg) == 0 {
  21. return filters, nil
  22. }
  23. if !strings.Contains(arg, "=") {
  24. return filters, ErrorBadFormat
  25. }
  26. f := strings.SplitN(arg, "=", 2)
  27. name := strings.ToLower(strings.TrimSpace(f[0]))
  28. value := strings.TrimSpace(f[1])
  29. filters[name] = append(filters[name], value)
  30. return filters, nil
  31. }
  32. var ErrorBadFormat = errors.New("bad format of filter (expected name=value)")
  33. // packs the Args into an string for easy transport from client to server
  34. func ToParam(a Args) (string, error) {
  35. // this way we don't URL encode {}, just empty space
  36. if len(a) == 0 {
  37. return "", nil
  38. }
  39. buf, err := json.Marshal(a)
  40. if err != nil {
  41. return "", err
  42. }
  43. return string(buf), nil
  44. }
  45. // unpacks the filter Args
  46. func FromParam(p string) (Args, error) {
  47. args := Args{}
  48. if len(p) == 0 {
  49. return args, nil
  50. }
  51. err := json.Unmarshal([]byte(p), &args)
  52. if err != nil {
  53. return nil, err
  54. }
  55. return args, nil
  56. }
  57. func (filters Args) Match(field, source string) bool {
  58. fieldValues := filters[field]
  59. //do not filter if there is no filter set or cannot determine filter
  60. if len(fieldValues) == 0 {
  61. return true
  62. }
  63. for _, name2match := range fieldValues {
  64. match, err := regexp.MatchString(name2match, source)
  65. if err != nil {
  66. continue
  67. }
  68. if match {
  69. return true
  70. }
  71. }
  72. return false
  73. }