Remove BPA from Makefile
[icn.git] / cmd / bpa-operator / vendor / gopkg.in / ini.v1 / struct.go
1 // Copyright 2014 Unknwon
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 // not use this file except in compliance with the License. You may obtain
5 // a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations
13 // under the License.
14
15 package ini
16
17 import (
18         "bytes"
19         "errors"
20         "fmt"
21         "reflect"
22         "strings"
23         "time"
24         "unicode"
25 )
26
27 // NameMapper represents a ini tag name mapper.
28 type NameMapper func(string) string
29
30 // Built-in name getters.
31 var (
32         // AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE.
33         AllCapsUnderscore NameMapper = func(raw string) string {
34                 newstr := make([]rune, 0, len(raw))
35                 for i, chr := range raw {
36                         if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
37                                 if i > 0 {
38                                         newstr = append(newstr, '_')
39                                 }
40                         }
41                         newstr = append(newstr, unicode.ToUpper(chr))
42                 }
43                 return string(newstr)
44         }
45         // TitleUnderscore converts to format title_underscore.
46         TitleUnderscore NameMapper = func(raw string) string {
47                 newstr := make([]rune, 0, len(raw))
48                 for i, chr := range raw {
49                         if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
50                                 if i > 0 {
51                                         newstr = append(newstr, '_')
52                                 }
53                                 chr -= ('A' - 'a')
54                         }
55                         newstr = append(newstr, chr)
56                 }
57                 return string(newstr)
58         }
59 )
60
61 func (s *Section) parseFieldName(raw, actual string) string {
62         if len(actual) > 0 {
63                 return actual
64         }
65         if s.f.NameMapper != nil {
66                 return s.f.NameMapper(raw)
67         }
68         return raw
69 }
70
71 func parseDelim(actual string) string {
72         if len(actual) > 0 {
73                 return actual
74         }
75         return ","
76 }
77
78 var reflectTime = reflect.TypeOf(time.Now()).Kind()
79
80 // setSliceWithProperType sets proper values to slice based on its type.
81 func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
82         var strs []string
83         if allowShadow {
84                 strs = key.StringsWithShadows(delim)
85         } else {
86                 strs = key.Strings(delim)
87         }
88
89         numVals := len(strs)
90         if numVals == 0 {
91                 return nil
92         }
93
94         var vals interface{}
95         var err error
96
97         sliceOf := field.Type().Elem().Kind()
98         switch sliceOf {
99         case reflect.String:
100                 vals = strs
101         case reflect.Int:
102                 vals, err = key.parseInts(strs, true, false)
103         case reflect.Int64:
104                 vals, err = key.parseInt64s(strs, true, false)
105         case reflect.Uint:
106                 vals, err = key.parseUints(strs, true, false)
107         case reflect.Uint64:
108                 vals, err = key.parseUint64s(strs, true, false)
109         case reflect.Float64:
110                 vals, err = key.parseFloat64s(strs, true, false)
111         case reflectTime:
112                 vals, err = key.parseTimesFormat(time.RFC3339, strs, true, false)
113         default:
114                 return fmt.Errorf("unsupported type '[]%s'", sliceOf)
115         }
116         if err != nil && isStrict {
117                 return err
118         }
119
120         slice := reflect.MakeSlice(field.Type(), numVals, numVals)
121         for i := 0; i < numVals; i++ {
122                 switch sliceOf {
123                 case reflect.String:
124                         slice.Index(i).Set(reflect.ValueOf(vals.([]string)[i]))
125                 case reflect.Int:
126                         slice.Index(i).Set(reflect.ValueOf(vals.([]int)[i]))
127                 case reflect.Int64:
128                         slice.Index(i).Set(reflect.ValueOf(vals.([]int64)[i]))
129                 case reflect.Uint:
130                         slice.Index(i).Set(reflect.ValueOf(vals.([]uint)[i]))
131                 case reflect.Uint64:
132                         slice.Index(i).Set(reflect.ValueOf(vals.([]uint64)[i]))
133                 case reflect.Float64:
134                         slice.Index(i).Set(reflect.ValueOf(vals.([]float64)[i]))
135                 case reflectTime:
136                         slice.Index(i).Set(reflect.ValueOf(vals.([]time.Time)[i]))
137                 }
138         }
139         field.Set(slice)
140         return nil
141 }
142
143 func wrapStrictError(err error, isStrict bool) error {
144         if isStrict {
145                 return err
146         }
147         return nil
148 }
149
150 // setWithProperType sets proper value to field based on its type,
151 // but it does not return error for failing parsing,
152 // because we want to use default value that is already assigned to struct.
153 func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
154         switch t.Kind() {
155         case reflect.String:
156                 if len(key.String()) == 0 {
157                         return nil
158                 }
159                 field.SetString(key.String())
160         case reflect.Bool:
161                 boolVal, err := key.Bool()
162                 if err != nil {
163                         return wrapStrictError(err, isStrict)
164                 }
165                 field.SetBool(boolVal)
166         case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
167                 durationVal, err := key.Duration()
168                 // Skip zero value
169                 if err == nil && int64(durationVal) > 0 {
170                         field.Set(reflect.ValueOf(durationVal))
171                         return nil
172                 }
173
174                 intVal, err := key.Int64()
175                 if err != nil {
176                         return wrapStrictError(err, isStrict)
177                 }
178                 field.SetInt(intVal)
179         //      byte is an alias for uint8, so supporting uint8 breaks support for byte
180         case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
181                 durationVal, err := key.Duration()
182                 // Skip zero value
183                 if err == nil && uint64(durationVal) > 0 {
184                         field.Set(reflect.ValueOf(durationVal))
185                         return nil
186                 }
187
188                 uintVal, err := key.Uint64()
189                 if err != nil {
190                         return wrapStrictError(err, isStrict)
191                 }
192                 field.SetUint(uintVal)
193
194         case reflect.Float32, reflect.Float64:
195                 floatVal, err := key.Float64()
196                 if err != nil {
197                         return wrapStrictError(err, isStrict)
198                 }
199                 field.SetFloat(floatVal)
200         case reflectTime:
201                 timeVal, err := key.Time()
202                 if err != nil {
203                         return wrapStrictError(err, isStrict)
204                 }
205                 field.Set(reflect.ValueOf(timeVal))
206         case reflect.Slice:
207                 return setSliceWithProperType(key, field, delim, allowShadow, isStrict)
208         case reflect.Ptr:
209                 switch t.Elem().Kind() {
210                 case reflect.Bool:
211                         boolVal, err := key.Bool()
212                         if err != nil {
213                                 return wrapStrictError(err, isStrict)
214                         }
215                         field.Set(reflect.ValueOf(&boolVal))
216                 default:
217                         return fmt.Errorf("unsupported type '%s'", t)
218                 }
219         default:
220                 return fmt.Errorf("unsupported type '%s'", t)
221         }
222         return nil
223 }
224
225 func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bool) {
226         opts := strings.SplitN(tag, ",", 3)
227         rawName = opts[0]
228         if len(opts) > 1 {
229                 omitEmpty = opts[1] == "omitempty"
230         }
231         if len(opts) > 2 {
232                 allowShadow = opts[2] == "allowshadow"
233         }
234         return rawName, omitEmpty, allowShadow
235 }
236
237 func (s *Section) mapTo(val reflect.Value, isStrict bool) error {
238         if val.Kind() == reflect.Ptr {
239                 val = val.Elem()
240         }
241         typ := val.Type()
242
243         for i := 0; i < typ.NumField(); i++ {
244                 field := val.Field(i)
245                 tpField := typ.Field(i)
246
247                 tag := tpField.Tag.Get("ini")
248                 if tag == "-" {
249                         continue
250                 }
251
252                 rawName, _, allowShadow := parseTagOptions(tag)
253                 fieldName := s.parseFieldName(tpField.Name, rawName)
254                 if len(fieldName) == 0 || !field.CanSet() {
255                         continue
256                 }
257
258                 isStruct := tpField.Type.Kind() == reflect.Struct
259                 isStructPtr := tpField.Type.Kind() == reflect.Ptr && tpField.Type.Elem().Kind() == reflect.Struct
260                 isAnonymous := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous
261                 if isAnonymous {
262                         field.Set(reflect.New(tpField.Type.Elem()))
263                 }
264
265                 if isAnonymous || isStruct || isStructPtr {
266                         if sec, err := s.f.GetSection(fieldName); err == nil {
267                                 // Only set the field to non-nil struct value if we have
268                                 // a section for it. Otherwise, we end up with a non-nil
269                                 // struct ptr even though there is no data.
270                                 if isStructPtr && field.IsNil() {
271                                         field.Set(reflect.New(tpField.Type.Elem()))
272                                 }
273                                 if err = sec.mapTo(field, isStrict); err != nil {
274                                         return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
275                                 }
276                                 continue
277                         }
278                 }
279
280                 if key, err := s.GetKey(fieldName); err == nil {
281                         delim := parseDelim(tpField.Tag.Get("delim"))
282                         if err = setWithProperType(tpField.Type, key, field, delim, allowShadow, isStrict); err != nil {
283                                 return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
284                         }
285                 }
286         }
287         return nil
288 }
289
290 // MapTo maps section to given struct.
291 func (s *Section) MapTo(v interface{}) error {
292         typ := reflect.TypeOf(v)
293         val := reflect.ValueOf(v)
294         if typ.Kind() == reflect.Ptr {
295                 typ = typ.Elem()
296                 val = val.Elem()
297         } else {
298                 return errors.New("cannot map to non-pointer struct")
299         }
300
301         return s.mapTo(val, false)
302 }
303
304 // StrictMapTo maps section to given struct in strict mode,
305 // which returns all possible error including value parsing error.
306 func (s *Section) StrictMapTo(v interface{}) error {
307         typ := reflect.TypeOf(v)
308         val := reflect.ValueOf(v)
309         if typ.Kind() == reflect.Ptr {
310                 typ = typ.Elem()
311                 val = val.Elem()
312         } else {
313                 return errors.New("cannot map to non-pointer struct")
314         }
315
316         return s.mapTo(val, true)
317 }
318
319 // MapTo maps file to given struct.
320 func (f *File) MapTo(v interface{}) error {
321         return f.Section("").MapTo(v)
322 }
323
324 // StrictMapTo maps file to given struct in strict mode,
325 // which returns all possible error including value parsing error.
326 func (f *File) StrictMapTo(v interface{}) error {
327         return f.Section("").StrictMapTo(v)
328 }
329
330 // MapToWithMapper maps data sources to given struct with name mapper.
331 func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
332         cfg, err := Load(source, others...)
333         if err != nil {
334                 return err
335         }
336         cfg.NameMapper = mapper
337         return cfg.MapTo(v)
338 }
339
340 // StrictMapToWithMapper maps data sources to given struct with name mapper in strict mode,
341 // which returns all possible error including value parsing error.
342 func StrictMapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
343         cfg, err := Load(source, others...)
344         if err != nil {
345                 return err
346         }
347         cfg.NameMapper = mapper
348         return cfg.StrictMapTo(v)
349 }
350
351 // MapTo maps data sources to given struct.
352 func MapTo(v, source interface{}, others ...interface{}) error {
353         return MapToWithMapper(v, nil, source, others...)
354 }
355
356 // StrictMapTo maps data sources to given struct in strict mode,
357 // which returns all possible error including value parsing error.
358 func StrictMapTo(v, source interface{}, others ...interface{}) error {
359         return StrictMapToWithMapper(v, nil, source, others...)
360 }
361
362 // reflectSliceWithProperType does the opposite thing as setSliceWithProperType.
363 func reflectSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow bool) error {
364         slice := field.Slice(0, field.Len())
365         if field.Len() == 0 {
366                 return nil
367         }
368         sliceOf := field.Type().Elem().Kind()
369
370         if allowShadow {
371                 var keyWithShadows *Key
372                 for i := 0; i < field.Len(); i++ {
373                         var val string
374                         switch sliceOf {
375                         case reflect.String:
376                                 val = slice.Index(i).String()
377                         case reflect.Int, reflect.Int64:
378                                 val = fmt.Sprint(slice.Index(i).Int())
379                         case reflect.Uint, reflect.Uint64:
380                                 val = fmt.Sprint(slice.Index(i).Uint())
381                         case reflect.Float64:
382                                 val = fmt.Sprint(slice.Index(i).Float())
383                         case reflectTime:
384                                 val = slice.Index(i).Interface().(time.Time).Format(time.RFC3339)
385                         default:
386                                 return fmt.Errorf("unsupported type '[]%s'", sliceOf)
387                         }
388
389                         if i == 0 {
390                                 keyWithShadows = newKey(key.s, key.name, val)
391                         } else {
392                                 keyWithShadows.AddShadow(val)
393                         }
394                 }
395                 key = keyWithShadows
396                 return nil
397         }
398
399         var buf bytes.Buffer
400         for i := 0; i < field.Len(); i++ {
401                 switch sliceOf {
402                 case reflect.String:
403                         buf.WriteString(slice.Index(i).String())
404                 case reflect.Int, reflect.Int64:
405                         buf.WriteString(fmt.Sprint(slice.Index(i).Int()))
406                 case reflect.Uint, reflect.Uint64:
407                         buf.WriteString(fmt.Sprint(slice.Index(i).Uint()))
408                 case reflect.Float64:
409                         buf.WriteString(fmt.Sprint(slice.Index(i).Float()))
410                 case reflectTime:
411                         buf.WriteString(slice.Index(i).Interface().(time.Time).Format(time.RFC3339))
412                 default:
413                         return fmt.Errorf("unsupported type '[]%s'", sliceOf)
414                 }
415                 buf.WriteString(delim)
416         }
417         key.SetValue(buf.String()[:buf.Len()-len(delim)])
418         return nil
419 }
420
421 // reflectWithProperType does the opposite thing as setWithProperType.
422 func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow bool) error {
423         switch t.Kind() {
424         case reflect.String:
425                 key.SetValue(field.String())
426         case reflect.Bool:
427                 key.SetValue(fmt.Sprint(field.Bool()))
428         case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
429                 key.SetValue(fmt.Sprint(field.Int()))
430         case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
431                 key.SetValue(fmt.Sprint(field.Uint()))
432         case reflect.Float32, reflect.Float64:
433                 key.SetValue(fmt.Sprint(field.Float()))
434         case reflectTime:
435                 key.SetValue(fmt.Sprint(field.Interface().(time.Time).Format(time.RFC3339)))
436         case reflect.Slice:
437                 return reflectSliceWithProperType(key, field, delim, allowShadow)
438         case reflect.Ptr:
439                 if !field.IsNil() {
440                         return reflectWithProperType(t.Elem(), key, field.Elem(), delim, allowShadow)
441                 }
442         default:
443                 return fmt.Errorf("unsupported type '%s'", t)
444         }
445         return nil
446 }
447
448 // CR: copied from encoding/json/encode.go with modifications of time.Time support.
449 // TODO: add more test coverage.
450 func isEmptyValue(v reflect.Value) bool {
451         switch v.Kind() {
452         case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
453                 return v.Len() == 0
454         case reflect.Bool:
455                 return !v.Bool()
456         case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
457                 return v.Int() == 0
458         case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
459                 return v.Uint() == 0
460         case reflect.Float32, reflect.Float64:
461                 return v.Float() == 0
462         case reflect.Interface, reflect.Ptr:
463                 return v.IsNil()
464         case reflectTime:
465                 t, ok := v.Interface().(time.Time)
466                 return ok && t.IsZero()
467         }
468         return false
469 }
470
471 func (s *Section) reflectFrom(val reflect.Value) error {
472         if val.Kind() == reflect.Ptr {
473                 val = val.Elem()
474         }
475         typ := val.Type()
476
477         for i := 0; i < typ.NumField(); i++ {
478                 field := val.Field(i)
479                 tpField := typ.Field(i)
480
481                 tag := tpField.Tag.Get("ini")
482                 if tag == "-" {
483                         continue
484                 }
485
486                 rawName, omitEmpty, allowShadow := parseTagOptions(tag)
487                 if omitEmpty && isEmptyValue(field) {
488                         continue
489                 }
490
491                 fieldName := s.parseFieldName(tpField.Name, rawName)
492                 if len(fieldName) == 0 || !field.CanSet() {
493                         continue
494                 }
495
496                 if (tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous) ||
497                         (tpField.Type.Kind() == reflect.Struct && tpField.Type.Name() != "Time") {
498                         // Note: The only error here is section doesn't exist.
499                         sec, err := s.f.GetSection(fieldName)
500                         if err != nil {
501                                 // Note: fieldName can never be empty here, ignore error.
502                                 sec, _ = s.f.NewSection(fieldName)
503                         }
504
505                         // Add comment from comment tag
506                         if len(sec.Comment) == 0 {
507                                 sec.Comment = tpField.Tag.Get("comment")
508                         }
509
510                         if err = sec.reflectFrom(field); err != nil {
511                                 return fmt.Errorf("error reflecting field (%s): %v", fieldName, err)
512                         }
513                         continue
514                 }
515
516                 // Note: Same reason as secion.
517                 key, err := s.GetKey(fieldName)
518                 if err != nil {
519                         key, _ = s.NewKey(fieldName, "")
520                 }
521
522                 // Add comment from comment tag
523                 if len(key.Comment) == 0 {
524                         key.Comment = tpField.Tag.Get("comment")
525                 }
526
527                 if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim")), allowShadow); err != nil {
528                         return fmt.Errorf("error reflecting field (%s): %v", fieldName, err)
529                 }
530
531         }
532         return nil
533 }
534
535 // ReflectFrom reflects secion from given struct.
536 func (s *Section) ReflectFrom(v interface{}) error {
537         typ := reflect.TypeOf(v)
538         val := reflect.ValueOf(v)
539         if typ.Kind() == reflect.Ptr {
540                 typ = typ.Elem()
541                 val = val.Elem()
542         } else {
543                 return errors.New("cannot reflect from non-pointer struct")
544         }
545
546         return s.reflectFrom(val)
547 }
548
549 // ReflectFrom reflects file from given struct.
550 func (f *File) ReflectFrom(v interface{}) error {
551         return f.Section("").ReflectFrom(v)
552 }
553
554 // ReflectFromWithMapper reflects data sources from given struct with name mapper.
555 func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error {
556         cfg.NameMapper = mapper
557         return cfg.ReflectFrom(v)
558 }
559
560 // ReflectFrom reflects data sources from given struct.
561 func ReflectFrom(cfg *File, v interface{}) error {
562         return ReflectFromWithMapper(cfg, v, nil)
563 }