You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

set.go 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. package gcfg
  2. import (
  3. "bytes"
  4. "encoding/gob"
  5. "fmt"
  6. "math/big"
  7. "reflect"
  8. "strings"
  9. "unicode"
  10. "unicode/utf8"
  11. "github.com/src-d/gcfg/types"
  12. "gopkg.in/warnings.v0"
  13. )
  14. type tag struct {
  15. ident string
  16. intMode string
  17. }
  18. func newTag(ts string) tag {
  19. t := tag{}
  20. s := strings.Split(ts, ",")
  21. t.ident = s[0]
  22. for _, tse := range s[1:] {
  23. if strings.HasPrefix(tse, "int=") {
  24. t.intMode = tse[len("int="):]
  25. }
  26. }
  27. return t
  28. }
  29. func fieldFold(v reflect.Value, name string) (reflect.Value, tag) {
  30. var n string
  31. r0, _ := utf8.DecodeRuneInString(name)
  32. if unicode.IsLetter(r0) && !unicode.IsLower(r0) && !unicode.IsUpper(r0) {
  33. n = "X"
  34. }
  35. n += strings.Replace(name, "-", "_", -1)
  36. f, ok := v.Type().FieldByNameFunc(func(fieldName string) bool {
  37. if !v.FieldByName(fieldName).CanSet() {
  38. return false
  39. }
  40. f, _ := v.Type().FieldByName(fieldName)
  41. t := newTag(f.Tag.Get("gcfg"))
  42. if t.ident != "" {
  43. return strings.EqualFold(t.ident, name)
  44. }
  45. return strings.EqualFold(n, fieldName)
  46. })
  47. if !ok {
  48. return reflect.Value{}, tag{}
  49. }
  50. return v.FieldByName(f.Name), newTag(f.Tag.Get("gcfg"))
  51. }
  52. type setter func(destp interface{}, blank bool, val string, t tag) error
  53. var errUnsupportedType = fmt.Errorf("unsupported type")
  54. var errBlankUnsupported = fmt.Errorf("blank value not supported for type")
  55. var setters = []setter{
  56. typeSetter, textUnmarshalerSetter, kindSetter, scanSetter,
  57. }
  58. func textUnmarshalerSetter(d interface{}, blank bool, val string, t tag) error {
  59. dtu, ok := d.(textUnmarshaler)
  60. if !ok {
  61. return errUnsupportedType
  62. }
  63. if blank {
  64. return errBlankUnsupported
  65. }
  66. return dtu.UnmarshalText([]byte(val))
  67. }
  68. func boolSetter(d interface{}, blank bool, val string, t tag) error {
  69. if blank {
  70. reflect.ValueOf(d).Elem().Set(reflect.ValueOf(true))
  71. return nil
  72. }
  73. b, err := types.ParseBool(val)
  74. if err == nil {
  75. reflect.ValueOf(d).Elem().Set(reflect.ValueOf(b))
  76. }
  77. return err
  78. }
  79. func intMode(mode string) types.IntMode {
  80. var m types.IntMode
  81. if strings.ContainsAny(mode, "dD") {
  82. m |= types.Dec
  83. }
  84. if strings.ContainsAny(mode, "hH") {
  85. m |= types.Hex
  86. }
  87. if strings.ContainsAny(mode, "oO") {
  88. m |= types.Oct
  89. }
  90. return m
  91. }
  92. var typeModes = map[reflect.Type]types.IntMode{
  93. reflect.TypeOf(int(0)): types.Dec | types.Hex,
  94. reflect.TypeOf(int8(0)): types.Dec | types.Hex,
  95. reflect.TypeOf(int16(0)): types.Dec | types.Hex,
  96. reflect.TypeOf(int32(0)): types.Dec | types.Hex,
  97. reflect.TypeOf(int64(0)): types.Dec | types.Hex,
  98. reflect.TypeOf(uint(0)): types.Dec | types.Hex,
  99. reflect.TypeOf(uint8(0)): types.Dec | types.Hex,
  100. reflect.TypeOf(uint16(0)): types.Dec | types.Hex,
  101. reflect.TypeOf(uint32(0)): types.Dec | types.Hex,
  102. reflect.TypeOf(uint64(0)): types.Dec | types.Hex,
  103. // use default mode (allow dec/hex/oct) for uintptr type
  104. reflect.TypeOf(big.Int{}): types.Dec | types.Hex,
  105. }
  106. func intModeDefault(t reflect.Type) types.IntMode {
  107. m, ok := typeModes[t]
  108. if !ok {
  109. m = types.Dec | types.Hex | types.Oct
  110. }
  111. return m
  112. }
  113. func intSetter(d interface{}, blank bool, val string, t tag) error {
  114. if blank {
  115. return errBlankUnsupported
  116. }
  117. mode := intMode(t.intMode)
  118. if mode == 0 {
  119. mode = intModeDefault(reflect.TypeOf(d).Elem())
  120. }
  121. return types.ParseInt(d, val, mode)
  122. }
  123. func stringSetter(d interface{}, blank bool, val string, t tag) error {
  124. if blank {
  125. return errBlankUnsupported
  126. }
  127. dsp, ok := d.(*string)
  128. if !ok {
  129. return errUnsupportedType
  130. }
  131. *dsp = val
  132. return nil
  133. }
  134. var kindSetters = map[reflect.Kind]setter{
  135. reflect.String: stringSetter,
  136. reflect.Bool: boolSetter,
  137. reflect.Int: intSetter,
  138. reflect.Int8: intSetter,
  139. reflect.Int16: intSetter,
  140. reflect.Int32: intSetter,
  141. reflect.Int64: intSetter,
  142. reflect.Uint: intSetter,
  143. reflect.Uint8: intSetter,
  144. reflect.Uint16: intSetter,
  145. reflect.Uint32: intSetter,
  146. reflect.Uint64: intSetter,
  147. reflect.Uintptr: intSetter,
  148. }
  149. var typeSetters = map[reflect.Type]setter{
  150. reflect.TypeOf(big.Int{}): intSetter,
  151. }
  152. func typeSetter(d interface{}, blank bool, val string, tt tag) error {
  153. t := reflect.ValueOf(d).Type().Elem()
  154. setter, ok := typeSetters[t]
  155. if !ok {
  156. return errUnsupportedType
  157. }
  158. return setter(d, blank, val, tt)
  159. }
  160. func kindSetter(d interface{}, blank bool, val string, tt tag) error {
  161. k := reflect.ValueOf(d).Type().Elem().Kind()
  162. setter, ok := kindSetters[k]
  163. if !ok {
  164. return errUnsupportedType
  165. }
  166. return setter(d, blank, val, tt)
  167. }
  168. func scanSetter(d interface{}, blank bool, val string, tt tag) error {
  169. if blank {
  170. return errBlankUnsupported
  171. }
  172. return types.ScanFully(d, val, 'v')
  173. }
  174. func newValue(c *warnings.Collector, sect string, vCfg reflect.Value,
  175. vType reflect.Type) (reflect.Value, error) {
  176. //
  177. pv := reflect.New(vType)
  178. dfltName := "default-" + sect
  179. dfltField, _ := fieldFold(vCfg, dfltName)
  180. var err error
  181. if dfltField.IsValid() {
  182. b := bytes.NewBuffer(nil)
  183. ge := gob.NewEncoder(b)
  184. if err = c.Collect(ge.EncodeValue(dfltField)); err != nil {
  185. return pv, err
  186. }
  187. gd := gob.NewDecoder(bytes.NewReader(b.Bytes()))
  188. if err = c.Collect(gd.DecodeValue(pv.Elem())); err != nil {
  189. return pv, err
  190. }
  191. }
  192. return pv, nil
  193. }
  194. func set(c *warnings.Collector, cfg interface{}, sect, sub, name string,
  195. value string, blankValue bool, subsectPass bool) error {
  196. //
  197. vPCfg := reflect.ValueOf(cfg)
  198. if vPCfg.Kind() != reflect.Ptr || vPCfg.Elem().Kind() != reflect.Struct {
  199. panic(fmt.Errorf("config must be a pointer to a struct"))
  200. }
  201. vCfg := vPCfg.Elem()
  202. vSect, _ := fieldFold(vCfg, sect)
  203. if !vSect.IsValid() {
  204. err := extraData{section: sect}
  205. return c.Collect(err)
  206. }
  207. isSubsect := vSect.Kind() == reflect.Map
  208. if subsectPass != isSubsect {
  209. return nil
  210. }
  211. if isSubsect {
  212. vst := vSect.Type()
  213. if vst.Key().Kind() != reflect.String ||
  214. vst.Elem().Kind() != reflect.Ptr ||
  215. vst.Elem().Elem().Kind() != reflect.Struct {
  216. panic(fmt.Errorf("map field for section must have string keys and "+
  217. " pointer-to-struct values: section %q", sect))
  218. }
  219. if vSect.IsNil() {
  220. vSect.Set(reflect.MakeMap(vst))
  221. }
  222. k := reflect.ValueOf(sub)
  223. pv := vSect.MapIndex(k)
  224. if !pv.IsValid() {
  225. vType := vSect.Type().Elem().Elem()
  226. var err error
  227. if pv, err = newValue(c, sect, vCfg, vType); err != nil {
  228. return err
  229. }
  230. vSect.SetMapIndex(k, pv)
  231. }
  232. vSect = pv.Elem()
  233. } else if vSect.Kind() != reflect.Struct {
  234. panic(fmt.Errorf("field for section must be a map or a struct: "+
  235. "section %q", sect))
  236. } else if sub != "" {
  237. err := extraData{section: sect, subsection: &sub}
  238. return c.Collect(err)
  239. }
  240. // Empty name is a special value, meaning that only the
  241. // section/subsection object is to be created, with no values set.
  242. if name == "" {
  243. return nil
  244. }
  245. vVar, t := fieldFold(vSect, name)
  246. if !vVar.IsValid() {
  247. var err error
  248. if isSubsect {
  249. err = extraData{section: sect, subsection: &sub, variable: &name}
  250. } else {
  251. err = extraData{section: sect, variable: &name}
  252. }
  253. return c.Collect(err)
  254. }
  255. // vVal is either single-valued var, or newly allocated value within multi-valued var
  256. var vVal reflect.Value
  257. // multi-value if unnamed slice type
  258. isMulti := vVar.Type().Name() == "" && vVar.Kind() == reflect.Slice ||
  259. vVar.Type().Name() == "" && vVar.Kind() == reflect.Ptr && vVar.Type().Elem().Name() == "" && vVar.Type().Elem().Kind() == reflect.Slice
  260. if isMulti && vVar.Kind() == reflect.Ptr {
  261. if vVar.IsNil() {
  262. vVar.Set(reflect.New(vVar.Type().Elem()))
  263. }
  264. vVar = vVar.Elem()
  265. }
  266. if isMulti && blankValue {
  267. vVar.Set(reflect.Zero(vVar.Type()))
  268. return nil
  269. }
  270. if isMulti {
  271. vVal = reflect.New(vVar.Type().Elem()).Elem()
  272. } else {
  273. vVal = vVar
  274. }
  275. isDeref := vVal.Type().Name() == "" && vVal.Type().Kind() == reflect.Ptr
  276. isNew := isDeref && vVal.IsNil()
  277. // vAddr is address of value to set (dereferenced & allocated as needed)
  278. var vAddr reflect.Value
  279. switch {
  280. case isNew:
  281. vAddr = reflect.New(vVal.Type().Elem())
  282. case isDeref && !isNew:
  283. vAddr = vVal
  284. default:
  285. vAddr = vVal.Addr()
  286. }
  287. vAddrI := vAddr.Interface()
  288. err, ok := error(nil), false
  289. for _, s := range setters {
  290. err = s(vAddrI, blankValue, value, t)
  291. if err == nil {
  292. ok = true
  293. break
  294. }
  295. if err != errUnsupportedType {
  296. return err
  297. }
  298. }
  299. if !ok {
  300. // in case all setters returned errUnsupportedType
  301. return err
  302. }
  303. if isNew { // set reference if it was dereferenced and newly allocated
  304. vVal.Set(vAddr)
  305. }
  306. if isMulti { // append if multi-valued
  307. vVar.Set(reflect.Append(vVar, vVal))
  308. }
  309. return nil
  310. }