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