string_to_string.go raw

   1  package pflag
   2  
   3  import (
   4  	"bytes"
   5  	"encoding/csv"
   6  	"fmt"
   7  	"strings"
   8  )
   9  
  10  // -- stringToString Value
  11  type stringToStringValue struct {
  12  	value   *map[string]string
  13  	changed bool
  14  }
  15  
  16  func newStringToStringValue(val map[string]string, p *map[string]string) *stringToStringValue {
  17  	ssv := new(stringToStringValue)
  18  	ssv.value = p
  19  	*ssv.value = val
  20  	return ssv
  21  }
  22  
  23  // Format: a=1,b=2
  24  func (s *stringToStringValue) Set(val string) error {
  25  	var ss []string
  26  	n := strings.Count(val, "=")
  27  	switch n {
  28  	case 0:
  29  		return fmt.Errorf("%s must be formatted as key=value", val)
  30  	case 1:
  31  		ss = append(ss, strings.Trim(val, `"`))
  32  	default:
  33  		r := csv.NewReader(strings.NewReader(val))
  34  		var err error
  35  		ss, err = r.Read()
  36  		if err != nil {
  37  			return err
  38  		}
  39  	}
  40  
  41  	out := make(map[string]string, len(ss))
  42  	for _, pair := range ss {
  43  		kv := strings.SplitN(pair, "=", 2)
  44  		if len(kv) != 2 {
  45  			return fmt.Errorf("%s must be formatted as key=value", pair)
  46  		}
  47  		out[kv[0]] = kv[1]
  48  	}
  49  	if !s.changed {
  50  		*s.value = out
  51  	} else {
  52  		for k, v := range out {
  53  			(*s.value)[k] = v
  54  		}
  55  	}
  56  	s.changed = true
  57  	return nil
  58  }
  59  
  60  func (s *stringToStringValue) Type() string {
  61  	return "stringToString"
  62  }
  63  
  64  func (s *stringToStringValue) String() string {
  65  	records := make([]string, 0, len(*s.value)>>1)
  66  	for k, v := range *s.value {
  67  		records = append(records, k+"="+v)
  68  	}
  69  
  70  	var buf bytes.Buffer
  71  	w := csv.NewWriter(&buf)
  72  	if err := w.Write(records); err != nil {
  73  		panic(err)
  74  	}
  75  	w.Flush()
  76  	return "[" + strings.TrimSpace(buf.String()) + "]"
  77  }
  78  
  79  func stringToStringConv(val string) (interface{}, error) {
  80  	val = strings.Trim(val, "[]")
  81  	// An empty string would cause an empty map
  82  	if len(val) == 0 {
  83  		return map[string]string{}, nil
  84  	}
  85  	r := csv.NewReader(strings.NewReader(val))
  86  	ss, err := r.Read()
  87  	if err != nil {
  88  		return nil, err
  89  	}
  90  	out := make(map[string]string, len(ss))
  91  	for _, pair := range ss {
  92  		kv := strings.SplitN(pair, "=", 2)
  93  		if len(kv) != 2 {
  94  			return nil, fmt.Errorf("%s must be formatted as key=value", pair)
  95  		}
  96  		out[kv[0]] = kv[1]
  97  	}
  98  	return out, nil
  99  }
 100  
 101  // GetStringToString return the map[string]string value of a flag with the given name
 102  func (f *FlagSet) GetStringToString(name string) (map[string]string, error) {
 103  	val, err := f.getFlagType(name, "stringToString", stringToStringConv)
 104  	if err != nil {
 105  		return map[string]string{}, err
 106  	}
 107  	return val.(map[string]string), nil
 108  }
 109  
 110  // StringToStringVar defines a string flag with specified name, default value, and usage string.
 111  // The argument p points to a map[string]string variable in which to store the values of the multiple flags.
 112  // The value of each argument will not try to be separated by comma
 113  func (f *FlagSet) StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
 114  	f.VarP(newStringToStringValue(value, p), name, "", usage)
 115  }
 116  
 117  // StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
 118  func (f *FlagSet) StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
 119  	f.VarP(newStringToStringValue(value, p), name, shorthand, usage)
 120  }
 121  
 122  // StringToStringVar defines a string flag with specified name, default value, and usage string.
 123  // The argument p points to a map[string]string variable in which to store the value of the flag.
 124  // The value of each argument will not try to be separated by comma
 125  func StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
 126  	CommandLine.VarP(newStringToStringValue(value, p), name, "", usage)
 127  }
 128  
 129  // StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
 130  func StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
 131  	CommandLine.VarP(newStringToStringValue(value, p), name, shorthand, usage)
 132  }
 133  
 134  // StringToString defines a string flag with specified name, default value, and usage string.
 135  // The return value is the address of a map[string]string variable that stores the value of the flag.
 136  // The value of each argument will not try to be separated by comma
 137  func (f *FlagSet) StringToString(name string, value map[string]string, usage string) *map[string]string {
 138  	p := map[string]string{}
 139  	f.StringToStringVarP(&p, name, "", value, usage)
 140  	return &p
 141  }
 142  
 143  // StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
 144  func (f *FlagSet) StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
 145  	p := map[string]string{}
 146  	f.StringToStringVarP(&p, name, shorthand, value, usage)
 147  	return &p
 148  }
 149  
 150  // StringToString defines a string flag with specified name, default value, and usage string.
 151  // The return value is the address of a map[string]string variable that stores the value of the flag.
 152  // The value of each argument will not try to be separated by comma
 153  func StringToString(name string, value map[string]string, usage string) *map[string]string {
 154  	return CommandLine.StringToStringP(name, "", value, usage)
 155  }
 156  
 157  // StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
 158  func StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
 159  	return CommandLine.StringToStringP(name, shorthand, value, usage)
 160  }
 161