forked from robfig/config
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathread.go
110 lines (92 loc) · 2.8 KB
/
read.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
// Copyright 2009 The "config" Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"bufio"
"errors"
"io"
"os"
"strings"
)
// _read is the base to read a file and get the configuration representation.
// That representation can be queried with GetString, etc.
func _read(fname string, c *Config) (*Config, error) {
file, err := os.Open(fname)
if err != nil {
return nil, err
}
if err = c.read(bufio.NewReader(file)); err != nil {
return nil, err
}
if err = file.Close(); err != nil {
return nil, err
}
return c, nil
}
// Read reads a configuration file and returns its representation.
// All arguments, except `fname`, are related to `New()`
func Read(fname string, comment, separator string, preSpace, postSpace bool) (*Config, error) {
return _read(fname, New(comment, separator, preSpace, postSpace))
}
// ReadDefault reads a configuration file and returns its representation.
// It uses values by default.
func ReadDefault(fname string) (*Config, error) {
return _read(fname, NewDefault())
}
// * * *
func (c *Config) read(buf *bufio.Reader) (err error) {
var section, option string
for {
l, err := buf.ReadString('\n') // parse line-by-line
if err == io.EOF {
break
} else if err != nil {
return err
}
l = strings.TrimSpace(l)
// Switch written for readability (not performance)
switch {
// Empty line and comments
case len(l) == 0, l[0] == '#', l[0] == ';':
continue
// New section
case l[0] == '[' && l[len(l)-1] == ']':
option = "" // reset multi-line value
section = strings.TrimSpace(l[1 : len(l)-1])
c.AddSection(section)
// No new section and no section defined so
//case section == "":
//return os.NewError("no section defined")
// Other alternatives
default:
i := strings.IndexAny(l, "=:")
switch {
// Option and value
case i > 0:
i := strings.IndexAny(l, "=:")
option = strings.TrimSpace(l[0:i])
value := strings.TrimSpace(stripComments(l[i+1:]))
c.AddOption(section, option, value)
// Continuation of multi-line value
case section != "" && option != "":
prev, _ := c.RawString(section, option)
value := strings.TrimSpace(stripComments(l))
c.AddOption(section, option, prev+"\n"+value)
default:
return errors.New("could not parse line: " + l)
}
}
}
return nil
}