-
Notifications
You must be signed in to change notification settings - Fork 19
/
file.go
118 lines (93 loc) · 2.51 KB
/
file.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package config
import (
"bufio"
"fmt"
"os"
"reflect"
"strconv"
"strings"
)
// parseFile parses config.ini
// If config.ini doesn't exist, program will create file with default values.
// If there's an error, program will exit with code 2.
func parseFile() {
if _, err := os.Open("config.ini"); os.IsNotExist(err) {
// If we have to create a new file, we don't need to parse it
err = createFile()
if err != nil {
panic(err)
}
return
}
// Read data from the file
file, _ := os.Open("config.ini")
scanner := bufio.NewScanner(file)
opts := make(map[string]string)
for scanner.Scan() {
line := string(scanner.Bytes())
// Skip empty strings and comments
if line != "" && line[0] != '#' {
data := strings.Split(line, "=")
if len(data) == 2 {
opts[data[0]] = data[1]
}
}
}
file.Close()
// Set values
var values []field
t := reflect.TypeOf(Opts)
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
configName := f.Tag.Get("name")
fieldName := f.Name
// If there's no such name, skip
if _, ok := opts[configName]; !ok {
continue
}
switch f.Type.Kind() {
case reflect.Int:
v, _ := strconv.ParseInt(opts[configName], 10, 64)
values = append(values, field{name: fieldName, value: int(v)})
case reflect.String:
values = append(values, field{name: fieldName, value: opts[configName]})
case reflect.Bool:
v, _ := strconv.ParseBool(opts[configName])
values = append(values, field{name: fieldName, value: v})
default:
panicf("Bad type of a field of Opts. Type: %s", f.Type.Kind())
}
}
setValues(&Opts, values)
}
// createFile creates config.ini and writes Opts.
func createFile() error {
file, err := os.Create("config.ini")
if err != nil {
return err
}
// We can use Opts, because we already set default values by calling of setDefaultValues()
v := reflect.ValueOf(Opts) // for values
t := v.Type() // for tags
optsLits := "# List of all opts:\n" // contains list of all opts
opts := "" // contains useful payload
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
configName := f.Tag.Get("name")
optsLits += "# " + configName + "\n"
comment := f.Tag.Get("comment")
defValue := fmt.Sprint(v.Field(i).Interface())
var line string
if comment != "" {
line = "# " + comment + "\n"
}
line += configName + "=" + defValue + "\n"
opts += line
}
// For readability
optsLits += "\n"
// Write default values and comments
file.Write([]byte(optsLits))
file.Write([]byte(opts))
return file.Close()
}