You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

section.go 4.5KB

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