...
1
2
3
4
5
6
7
8
9
10
11 package viper
12
13 import (
14 "fmt"
15 "os"
16 "path/filepath"
17 "runtime"
18 "strings"
19 "unicode"
20
21 "github.com/spf13/afero"
22 "github.com/spf13/cast"
23 jww "github.com/spf13/jwalterweatherman"
24 )
25
26
27 type ConfigParseError struct {
28 err error
29 }
30
31
32 func (pe ConfigParseError) Error() string {
33 return fmt.Sprintf("While parsing config: %s", pe.err.Error())
34 }
35
36
37
38 func toCaseInsensitiveValue(value interface{}) interface{} {
39 switch v := value.(type) {
40 case map[interface{}]interface{}:
41 value = copyAndInsensitiviseMap(cast.ToStringMap(v))
42 case map[string]interface{}:
43 value = copyAndInsensitiviseMap(v)
44 }
45
46 return value
47 }
48
49
50
51 func copyAndInsensitiviseMap(m map[string]interface{}) map[string]interface{} {
52 nm := make(map[string]interface{})
53
54 for key, val := range m {
55 lkey := strings.ToLower(key)
56 switch v := val.(type) {
57 case map[interface{}]interface{}:
58 nm[lkey] = copyAndInsensitiviseMap(cast.ToStringMap(v))
59 case map[string]interface{}:
60 nm[lkey] = copyAndInsensitiviseMap(v)
61 default:
62 nm[lkey] = v
63 }
64 }
65
66 return nm
67 }
68
69 func insensitiviseMap(m map[string]interface{}) {
70 for key, val := range m {
71 switch val.(type) {
72 case map[interface{}]interface{}:
73
74 val = cast.ToStringMap(val)
75 insensitiviseMap(val.(map[string]interface{}))
76 case map[string]interface{}:
77
78 insensitiviseMap(val.(map[string]interface{}))
79 }
80
81 lower := strings.ToLower(key)
82 if key != lower {
83
84 delete(m, key)
85 }
86
87 m[lower] = val
88 }
89 }
90
91 func absPathify(inPath string) string {
92 jww.INFO.Println("Trying to resolve absolute path to", inPath)
93
94 if strings.HasPrefix(inPath, "$HOME") {
95 inPath = userHomeDir() + inPath[5:]
96 }
97
98 if strings.HasPrefix(inPath, "$") {
99 end := strings.Index(inPath, string(os.PathSeparator))
100 inPath = os.Getenv(inPath[1:end]) + inPath[end:]
101 }
102
103 if filepath.IsAbs(inPath) {
104 return filepath.Clean(inPath)
105 }
106
107 p, err := filepath.Abs(inPath)
108 if err == nil {
109 return filepath.Clean(p)
110 }
111
112 jww.ERROR.Println("Couldn't discover absolute path")
113 jww.ERROR.Println(err)
114 return ""
115 }
116
117
118 func exists(fs afero.Fs, path string) (bool, error) {
119 stat, err := fs.Stat(path)
120 if err == nil {
121 return !stat.IsDir(), nil
122 }
123 if os.IsNotExist(err) {
124 return false, nil
125 }
126 return false, err
127 }
128
129 func stringInSlice(a string, list []string) bool {
130 for _, b := range list {
131 if b == a {
132 return true
133 }
134 }
135 return false
136 }
137
138 func userHomeDir() string {
139 if runtime.GOOS == "windows" {
140 home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
141 if home == "" {
142 home = os.Getenv("USERPROFILE")
143 }
144 return home
145 }
146 return os.Getenv("HOME")
147 }
148
149 func safeMul(a, b uint) uint {
150 c := a * b
151 if a > 1 && b > 1 && c/b != a {
152 return 0
153 }
154 return c
155 }
156
157
158 func parseSizeInBytes(sizeStr string) uint {
159 sizeStr = strings.TrimSpace(sizeStr)
160 lastChar := len(sizeStr) - 1
161 multiplier := uint(1)
162
163 if lastChar > 0 {
164 if sizeStr[lastChar] == 'b' || sizeStr[lastChar] == 'B' {
165 if lastChar > 1 {
166 switch unicode.ToLower(rune(sizeStr[lastChar-1])) {
167 case 'k':
168 multiplier = 1 << 10
169 sizeStr = strings.TrimSpace(sizeStr[:lastChar-1])
170 case 'm':
171 multiplier = 1 << 20
172 sizeStr = strings.TrimSpace(sizeStr[:lastChar-1])
173 case 'g':
174 multiplier = 1 << 30
175 sizeStr = strings.TrimSpace(sizeStr[:lastChar-1])
176 default:
177 multiplier = 1
178 sizeStr = strings.TrimSpace(sizeStr[:lastChar])
179 }
180 }
181 }
182 }
183
184 size := cast.ToInt(sizeStr)
185 if size < 0 {
186 size = 0
187 }
188
189 return safeMul(uint(size), multiplier)
190 }
191
192
193
194
195
196
197
198
199 func deepSearch(m map[string]interface{}, path []string) map[string]interface{} {
200 for _, k := range path {
201 m2, ok := m[k]
202 if !ok {
203
204
205 m3 := make(map[string]interface{})
206 m[k] = m3
207 m = m3
208 continue
209 }
210 m3, ok := m2.(map[string]interface{})
211 if !ok {
212
213
214 m3 = make(map[string]interface{})
215 m[k] = m3
216 }
217
218 m = m3
219 }
220 return m
221 }
222
223
224
225 func toMapStringInterface(in interface{}) interface{} {
226 switch t := in.(type) {
227 case map[string]interface{}:
228 for k, v := range t {
229 t[k] = toMapStringInterface(v)
230 }
231 return t
232 case map[interface{}]interface{}:
233 nt := make(map[string]interface{})
234 for k, v := range t {
235 nt[fmt.Sprintf("%s", k)] = toMapStringInterface(v)
236 }
237 return nt
238 case []interface{}:
239 for k, v := range t {
240 t[k] = toMapStringInterface(v)
241 }
242 return t
243 default:
244 return in
245 }
246 }
247
View as plain text