1 package ini
2
3 import (
4 "errors"
5 "fmt"
6 "strings"
7 )
8
9
10 type Section struct {
11 f *File
12 Comment string
13 name string
14 keys map[string]*Key
15 keyList []string
16 keysHash map[string]string
17
18 isRawSection bool
19 rawBody string
20 }
21
22 func newSection(f *File, name string) *Section {
23 return &Section{
24 f: f,
25 name: name,
26 keys: make(map[string]*Key),
27 keyList: make([]string, 0, 10),
28 keysHash: make(map[string]string),
29 }
30 }
31
32
33 func (s *Section) Name() string {
34 return s.name
35 }
36
37
38
39 func (s *Section) Body() string {
40 return strings.TrimSpace(s.rawBody)
41 }
42
43
44 func (s *Section) SetBody(body string) {
45 if !s.isRawSection {
46 return
47 }
48 s.rawBody = body
49 }
50
51
52 func (s *Section) NewKey(name, val string) (*Key, error) {
53 if len(name) == 0 {
54 return nil, errors.New("error creating new key: empty key name")
55 } else if s.f.options.Insensitive || s.f.options.InsensitiveKeys {
56 name = strings.ToLower(name)
57 }
58
59 if s.f.BlockMode {
60 s.f.lock.Lock()
61 defer s.f.lock.Unlock()
62 }
63
64 if inSlice(name, s.keyList) {
65 if s.f.options.AllowShadows {
66 if err := s.keys[name].addShadow(val); err != nil {
67 return nil, err
68 }
69 } else {
70 s.keys[name].value = val
71 s.keysHash[name] = val
72 }
73 return s.keys[name], nil
74 }
75
76 s.keyList = append(s.keyList, name)
77 s.keys[name] = newKey(s, name, val)
78 s.keysHash[name] = val
79 return s.keys[name], nil
80 }
81
82
83 func (s *Section) NewBooleanKey(name string) (*Key, error) {
84 key, err := s.NewKey(name, "true")
85 if err != nil {
86 return nil, err
87 }
88
89 key.isBooleanType = true
90 return key, nil
91 }
92
93
94 func (s *Section) GetKey(name string) (*Key, error) {
95 if s.f.BlockMode {
96 s.f.lock.RLock()
97 }
98 if s.f.options.Insensitive || s.f.options.InsensitiveKeys {
99 name = strings.ToLower(name)
100 }
101 key := s.keys[name]
102 if s.f.BlockMode {
103 s.f.lock.RUnlock()
104 }
105
106 if key == nil {
107
108 sname := s.name
109 for {
110 if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 {
111 sname = sname[:i]
112 sec, err := s.f.GetSection(sname)
113 if err != nil {
114 continue
115 }
116 return sec.GetKey(name)
117 }
118 break
119 }
120 return nil, fmt.Errorf("error when getting key of section %q: key %q not exists", s.name, name)
121 }
122 return key, nil
123 }
124
125
126 func (s *Section) HasKey(name string) bool {
127 key, _ := s.GetKey(name)
128 return key != nil
129 }
130
131
132 func (s *Section) Haskey(name string) bool {
133 return s.HasKey(name)
134 }
135
136
137 func (s *Section) HasValue(value string) bool {
138 if s.f.BlockMode {
139 s.f.lock.RLock()
140 defer s.f.lock.RUnlock()
141 }
142
143 for _, k := range s.keys {
144 if value == k.value {
145 return true
146 }
147 }
148 return false
149 }
150
151
152 func (s *Section) Key(name string) *Key {
153 key, err := s.GetKey(name)
154 if err != nil {
155
156
157 key, _ = s.NewKey(name, "")
158 return key
159 }
160 return key
161 }
162
163
164 func (s *Section) Keys() []*Key {
165 keys := make([]*Key, len(s.keyList))
166 for i := range s.keyList {
167 keys[i] = s.Key(s.keyList[i])
168 }
169 return keys
170 }
171
172
173 func (s *Section) ParentKeys() []*Key {
174 var parentKeys []*Key
175 sname := s.name
176 for {
177 if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 {
178 sname = sname[:i]
179 sec, err := s.f.GetSection(sname)
180 if err != nil {
181 continue
182 }
183 parentKeys = append(parentKeys, sec.Keys()...)
184 } else {
185 break
186 }
187
188 }
189 return parentKeys
190 }
191
192
193 func (s *Section) KeyStrings() []string {
194 list := make([]string, len(s.keyList))
195 copy(list, s.keyList)
196 return list
197 }
198
199
200 func (s *Section) KeysHash() map[string]string {
201 if s.f.BlockMode {
202 s.f.lock.RLock()
203 defer s.f.lock.RUnlock()
204 }
205
206 hash := make(map[string]string, len(s.keysHash))
207 for key, value := range s.keysHash {
208 hash[key] = value
209 }
210 return hash
211 }
212
213
214 func (s *Section) DeleteKey(name string) {
215 if s.f.BlockMode {
216 s.f.lock.Lock()
217 defer s.f.lock.Unlock()
218 }
219
220 for i, k := range s.keyList {
221 if k == name {
222 s.keyList = append(s.keyList[:i], s.keyList[i+1:]...)
223 delete(s.keys, name)
224 delete(s.keysHash, name)
225 return
226 }
227 }
228 }
229
230
231
232
233 func (s *Section) ChildSections() []*Section {
234 prefix := s.name + s.f.options.ChildSectionDelimiter
235 children := make([]*Section, 0, 3)
236 for _, name := range s.f.sectionList {
237 if strings.HasPrefix(name, prefix) {
238 children = append(children, s.f.sections[name]...)
239 }
240 }
241 return children
242 }
243
View as plain text