aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/go-ini/ini/section.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/go-ini/ini/section.go')
-rw-r--r--vendor/github.com/go-ini/ini/section.go221
1 files changed, 221 insertions, 0 deletions
diff --git a/vendor/github.com/go-ini/ini/section.go b/vendor/github.com/go-ini/ini/section.go
new file mode 100644
index 0000000..45d2f3b
--- /dev/null
+++ b/vendor/github.com/go-ini/ini/section.go
@@ -0,0 +1,221 @@
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
15package ini
16
17import (
18 "errors"
19 "fmt"
20 "strings"
21)
22
23// Section represents a config section.
24type Section struct {
25 f *File
26 Comment string
27 name string
28 keys map[string]*Key
29 keyList []string
30 keysHash map[string]string
31
32 isRawSection bool
33 rawBody string
34}
35
36func newSection(f *File, name string) *Section {
37 return &Section{
38 f: f,
39 name: name,
40 keys: make(map[string]*Key),
41 keyList: make([]string, 0, 10),
42 keysHash: make(map[string]string),
43 }
44}
45
46// Name returns name of Section.
47func (s *Section) Name() string {
48 return s.name
49}
50
51// Body returns rawBody of Section if the section was marked as unparseable.
52// It still follows the other rules of the INI format surrounding leading/trailing whitespace.
53func (s *Section) Body() string {
54 return strings.TrimSpace(s.rawBody)
55}
56
57// NewKey creates a new key to given section.
58func (s *Section) NewKey(name, val string) (*Key, error) {
59 if len(name) == 0 {
60 return nil, errors.New("error creating new key: empty key name")
61 } else if s.f.options.Insensitive {
62 name = strings.ToLower(name)
63 }
64
65 if s.f.BlockMode {
66 s.f.lock.Lock()
67 defer s.f.lock.Unlock()
68 }
69
70 if inSlice(name, s.keyList) {
71 s.keys[name].value = val
72 return s.keys[name], nil
73 }
74
75 s.keyList = append(s.keyList, name)
76 s.keys[name] = &Key{
77 s: s,
78 name: name,
79 value: val,
80 }
81 s.keysHash[name] = val
82 return s.keys[name], nil
83}
84
85// GetKey returns key in section by given name.
86func (s *Section) GetKey(name string) (*Key, error) {
87 // FIXME: change to section level lock?
88 if s.f.BlockMode {
89 s.f.lock.RLock()
90 }
91 if s.f.options.Insensitive {
92 name = strings.ToLower(name)
93 }
94 key := s.keys[name]
95 if s.f.BlockMode {
96 s.f.lock.RUnlock()
97 }
98
99 if key == nil {
100 // Check if it is a child-section.
101 sname := s.name
102 for {
103 if i := strings.LastIndex(sname, "."); i > -1 {
104 sname = sname[:i]
105 sec, err := s.f.GetSection(sname)
106 if err != nil {
107 continue
108 }
109 return sec.GetKey(name)
110 } else {
111 break
112 }
113 }
114 return nil, fmt.Errorf("error when getting key of section '%s': key '%s' not exists", s.name, name)
115 }
116 return key, nil
117}
118
119// HasKey returns true if section contains a key with given name.
120func (s *Section) HasKey(name string) bool {
121 key, _ := s.GetKey(name)
122 return key != nil
123}
124
125// Haskey is a backwards-compatible name for HasKey.
126func (s *Section) Haskey(name string) bool {
127 return s.HasKey(name)
128}
129
130// HasValue returns true if section contains given raw value.
131func (s *Section) HasValue(value string) bool {
132 if s.f.BlockMode {
133 s.f.lock.RLock()
134 defer s.f.lock.RUnlock()
135 }
136
137 for _, k := range s.keys {
138 if value == k.value {
139 return true
140 }
141 }
142 return false
143}
144
145// Key assumes named Key exists in section and returns a zero-value when not.
146func (s *Section) Key(name string) *Key {
147 key, err := s.GetKey(name)
148 if err != nil {
149 // It's OK here because the only possible error is empty key name,
150 // but if it's empty, this piece of code won't be executed.
151 key, _ = s.NewKey(name, "")
152 return key
153 }
154 return key
155}
156
157// Keys returns list of keys of section.
158func (s *Section) Keys() []*Key {
159 keys := make([]*Key, len(s.keyList))
160 for i := range s.keyList {
161 keys[i] = s.Key(s.keyList[i])
162 }
163 return keys
164}
165
166// ParentKeys returns list of keys of parent section.
167func (s *Section) ParentKeys() []*Key {
168 var parentKeys []*Key
169 sname := s.name
170 for {
171 if i := strings.LastIndex(sname, "."); i > -1 {
172 sname = sname[:i]
173 sec, err := s.f.GetSection(sname)
174 if err != nil {
175 continue
176 }
177 parentKeys = append(parentKeys, sec.Keys()...)
178 } else {
179 break
180 }
181
182 }
183 return parentKeys
184}
185
186// KeyStrings returns list of key names of section.
187func (s *Section) KeyStrings() []string {
188 list := make([]string, len(s.keyList))
189 copy(list, s.keyList)
190 return list
191}
192
193// KeysHash returns keys hash consisting of names and values.
194func (s *Section) KeysHash() map[string]string {
195 if s.f.BlockMode {
196 s.f.lock.RLock()
197 defer s.f.lock.RUnlock()
198 }
199
200 hash := map[string]string{}
201 for key, value := range s.keysHash {
202 hash[key] = value
203 }
204 return hash
205}
206
207// DeleteKey deletes a key from section.
208func (s *Section) DeleteKey(name string) {
209 if s.f.BlockMode {
210 s.f.lock.Lock()
211 defer s.f.lock.Unlock()
212 }
213
214 for i, k := range s.keyList {
215 if k == name {
216 s.keyList = append(s.keyList[:i], s.keyList[i+1:]...)
217 delete(s.keys, name)
218 return
219 }
220 }
221}