]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/go-ini/ini/section.go
Merge pull request #27 from terraform-providers/go-modules-2019-02-22
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / go-ini / ini / section.go
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
15 package ini
16
17 import (
18 "errors"
19 "fmt"
20 "strings"
21 )
22
23 // Section represents a config section.
24 type 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
36 func 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.
47 func (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.
53 func (s *Section) Body() string {
54 return strings.TrimSpace(s.rawBody)
55 }
56
57 // NewKey creates a new key to given section.
58 func (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 if s.f.options.AllowShadows {
72 if err := s.keys[name].addShadow(val); err != nil {
73 return nil, err
74 }
75 } else {
76 s.keys[name].value = val
77 }
78 return s.keys[name], nil
79 }
80
81 s.keyList = append(s.keyList, name)
82 s.keys[name] = newKey(s, name, val)
83 s.keysHash[name] = val
84 return s.keys[name], nil
85 }
86
87 // NewBooleanKey creates a new boolean type key to given section.
88 func (s *Section) NewBooleanKey(name string) (*Key, error) {
89 key, err := s.NewKey(name, "true")
90 if err != nil {
91 return nil, err
92 }
93
94 key.isBooleanType = true
95 return key, nil
96 }
97
98 // GetKey returns key in section by given name.
99 func (s *Section) GetKey(name string) (*Key, error) {
100 // FIXME: change to section level lock?
101 if s.f.BlockMode {
102 s.f.lock.RLock()
103 }
104 if s.f.options.Insensitive {
105 name = strings.ToLower(name)
106 }
107 key := s.keys[name]
108 if s.f.BlockMode {
109 s.f.lock.RUnlock()
110 }
111
112 if key == nil {
113 // Check if it is a child-section.
114 sname := s.name
115 for {
116 if i := strings.LastIndex(sname, "."); i > -1 {
117 sname = sname[:i]
118 sec, err := s.f.GetSection(sname)
119 if err != nil {
120 continue
121 }
122 return sec.GetKey(name)
123 } else {
124 break
125 }
126 }
127 return nil, fmt.Errorf("error when getting key of section '%s': key '%s' not exists", s.name, name)
128 }
129 return key, nil
130 }
131
132 // HasKey returns true if section contains a key with given name.
133 func (s *Section) HasKey(name string) bool {
134 key, _ := s.GetKey(name)
135 return key != nil
136 }
137
138 // Haskey is a backwards-compatible name for HasKey.
139 func (s *Section) Haskey(name string) bool {
140 return s.HasKey(name)
141 }
142
143 // HasValue returns true if section contains given raw value.
144 func (s *Section) HasValue(value string) bool {
145 if s.f.BlockMode {
146 s.f.lock.RLock()
147 defer s.f.lock.RUnlock()
148 }
149
150 for _, k := range s.keys {
151 if value == k.value {
152 return true
153 }
154 }
155 return false
156 }
157
158 // Key assumes named Key exists in section and returns a zero-value when not.
159 func (s *Section) Key(name string) *Key {
160 key, err := s.GetKey(name)
161 if err != nil {
162 // It's OK here because the only possible error is empty key name,
163 // but if it's empty, this piece of code won't be executed.
164 key, _ = s.NewKey(name, "")
165 return key
166 }
167 return key
168 }
169
170 // Keys returns list of keys of section.
171 func (s *Section) Keys() []*Key {
172 keys := make([]*Key, len(s.keyList))
173 for i := range s.keyList {
174 keys[i] = s.Key(s.keyList[i])
175 }
176 return keys
177 }
178
179 // ParentKeys returns list of keys of parent section.
180 func (s *Section) ParentKeys() []*Key {
181 var parentKeys []*Key
182 sname := s.name
183 for {
184 if i := strings.LastIndex(sname, "."); i > -1 {
185 sname = sname[:i]
186 sec, err := s.f.GetSection(sname)
187 if err != nil {
188 continue
189 }
190 parentKeys = append(parentKeys, sec.Keys()...)
191 } else {
192 break
193 }
194
195 }
196 return parentKeys
197 }
198
199 // KeyStrings returns list of key names of section.
200 func (s *Section) KeyStrings() []string {
201 list := make([]string, len(s.keyList))
202 copy(list, s.keyList)
203 return list
204 }
205
206 // KeysHash returns keys hash consisting of names and values.
207 func (s *Section) KeysHash() map[string]string {
208 if s.f.BlockMode {
209 s.f.lock.RLock()
210 defer s.f.lock.RUnlock()
211 }
212
213 hash := map[string]string{}
214 for key, value := range s.keysHash {
215 hash[key] = value
216 }
217 return hash
218 }
219
220 // DeleteKey deletes a key from section.
221 func (s *Section) DeleteKey(name string) {
222 if s.f.BlockMode {
223 s.f.lock.Lock()
224 defer s.f.lock.Unlock()
225 }
226
227 for i, k := range s.keyList {
228 if k == name {
229 s.keyList = append(s.keyList[:i], s.keyList[i+1:]...)
230 delete(s.keys, name)
231 return
232 }
233 }
234 }