~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/gopkg.in/ini.v1/section.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
33
func newSection(f *File, name string) *Section {
 
34
        return &Section{f, "", name, make(map[string]*Key), make([]string, 0, 10), make(map[string]string)}
 
35
}
 
36
 
 
37
// Name returns name of Section.
 
38
func (s *Section) Name() string {
 
39
        return s.name
 
40
}
 
41
 
 
42
// NewKey creates a new key to given section.
 
43
func (s *Section) NewKey(name, val string) (*Key, error) {
 
44
        if len(name) == 0 {
 
45
                return nil, errors.New("error creating new key: empty key name")
 
46
        }
 
47
 
 
48
        if s.f.BlockMode {
 
49
                s.f.lock.Lock()
 
50
                defer s.f.lock.Unlock()
 
51
        }
 
52
 
 
53
        if inSlice(name, s.keyList) {
 
54
                s.keys[name].value = val
 
55
                return s.keys[name], nil
 
56
        }
 
57
 
 
58
        s.keyList = append(s.keyList, name)
 
59
        s.keys[name] = &Key{s, "", name, val, false}
 
60
        s.keysHash[name] = val
 
61
        return s.keys[name], nil
 
62
}
 
63
 
 
64
// GetKey returns key in section by given name.
 
65
func (s *Section) GetKey(name string) (*Key, error) {
 
66
        // FIXME: change to section level lock?
 
67
        if s.f.BlockMode {
 
68
                s.f.lock.RLock()
 
69
        }
 
70
        key := s.keys[name]
 
71
        if s.f.BlockMode {
 
72
                s.f.lock.RUnlock()
 
73
        }
 
74
 
 
75
        if key == nil {
 
76
                // Check if it is a child-section.
 
77
                sname := s.name
 
78
                for {
 
79
                        if i := strings.LastIndex(sname, "."); i > -1 {
 
80
                                sname = sname[:i]
 
81
                                sec, err := s.f.GetSection(sname)
 
82
                                if err != nil {
 
83
                                        continue
 
84
                                }
 
85
                                return sec.GetKey(name)
 
86
                        } else {
 
87
                                break
 
88
                        }
 
89
                }
 
90
                return nil, fmt.Errorf("error when getting key of section '%s': key '%s' not exists", s.name, name)
 
91
        }
 
92
        return key, nil
 
93
}
 
94
 
 
95
// HasKey returns true if section contains a key with given name.
 
96
func (s *Section) HasKey(name string) bool {
 
97
        key, _ := s.GetKey(name)
 
98
        return key != nil
 
99
}
 
100
 
 
101
// Haskey is a backwards-compatible name for HasKey.
 
102
func (s *Section) Haskey(name string) bool {
 
103
        return s.HasKey(name)
 
104
}
 
105
 
 
106
// HasValue returns true if section contains given raw value.
 
107
func (s *Section) HasValue(value string) bool {
 
108
        if s.f.BlockMode {
 
109
                s.f.lock.RLock()
 
110
                defer s.f.lock.RUnlock()
 
111
        }
 
112
 
 
113
        for _, k := range s.keys {
 
114
                if value == k.value {
 
115
                        return true
 
116
                }
 
117
        }
 
118
        return false
 
119
}
 
120
 
 
121
// Key assumes named Key exists in section and returns a zero-value when not.
 
122
func (s *Section) Key(name string) *Key {
 
123
        key, err := s.GetKey(name)
 
124
        if err != nil {
 
125
                // It's OK here because the only possible error is empty key name,
 
126
                // but if it's empty, this piece of code won't be executed.
 
127
                key, _ = s.NewKey(name, "")
 
128
                return key
 
129
        }
 
130
        return key
 
131
}
 
132
 
 
133
// Keys returns list of keys of section.
 
134
func (s *Section) Keys() []*Key {
 
135
        keys := make([]*Key, len(s.keyList))
 
136
        for i := range s.keyList {
 
137
                keys[i] = s.Key(s.keyList[i])
 
138
        }
 
139
        return keys
 
140
}
 
141
 
 
142
// KeyStrings returns list of key names of section.
 
143
func (s *Section) KeyStrings() []string {
 
144
        list := make([]string, len(s.keyList))
 
145
        copy(list, s.keyList)
 
146
        return list
 
147
}
 
148
 
 
149
// KeysHash returns keys hash consisting of names and values.
 
150
func (s *Section) KeysHash() map[string]string {
 
151
        if s.f.BlockMode {
 
152
                s.f.lock.RLock()
 
153
                defer s.f.lock.RUnlock()
 
154
        }
 
155
 
 
156
        hash := map[string]string{}
 
157
        for key, value := range s.keysHash {
 
158
                hash[key] = value
 
159
        }
 
160
        return hash
 
161
}
 
162
 
 
163
// DeleteKey deletes a key from section.
 
164
func (s *Section) DeleteKey(name string) {
 
165
        if s.f.BlockMode {
 
166
                s.f.lock.Lock()
 
167
                defer s.f.lock.Unlock()
 
168
        }
 
169
 
 
170
        for i, k := range s.keyList {
 
171
                if k == name {
 
172
                        s.keyList = append(s.keyList[:i], s.keyList[i+1:]...)
 
173
                        delete(s.keys, name)
 
174
                        return
 
175
                }
 
176
        }
 
177
}