]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/go-ini/ini/section.go
Initial transfer of provider code
[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 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.
86 func (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.
120 func (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.
126 func (s *Section) Haskey(name string) bool {
127 return s.HasKey(name)
128 }
129
130 // HasValue returns true if section contains given raw value.
131 func (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.
146 func (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.
158 func (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.
167 func (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.
187 func (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.
194 func (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.
208 func (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 }