vendor/gopkg.in/ini.v1/section.go
changeset 251 1c52a0eeb952
child 256 6d9efbef00a9
equal deleted inserted replaced
250:c040f992052f 251:1c52a0eeb952
       
     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 // SetBody updates body content only if section is raw.
       
    58 func (s *Section) SetBody(body string) {
       
    59 	if !s.isRawSection {
       
    60 		return
       
    61 	}
       
    62 	s.rawBody = body
       
    63 }
       
    64 
       
    65 // NewKey creates a new key to given section.
       
    66 func (s *Section) NewKey(name, val string) (*Key, error) {
       
    67 	if len(name) == 0 {
       
    68 		return nil, errors.New("error creating new key: empty key name")
       
    69 	} else if s.f.options.Insensitive {
       
    70 		name = strings.ToLower(name)
       
    71 	}
       
    72 
       
    73 	if s.f.BlockMode {
       
    74 		s.f.lock.Lock()
       
    75 		defer s.f.lock.Unlock()
       
    76 	}
       
    77 
       
    78 	if inSlice(name, s.keyList) {
       
    79 		if s.f.options.AllowShadows {
       
    80 			if err := s.keys[name].addShadow(val); err != nil {
       
    81 				return nil, err
       
    82 			}
       
    83 		} else {
       
    84 			s.keys[name].value = val
       
    85 			s.keysHash[name] = val
       
    86 		}
       
    87 		return s.keys[name], nil
       
    88 	}
       
    89 
       
    90 	s.keyList = append(s.keyList, name)
       
    91 	s.keys[name] = newKey(s, name, val)
       
    92 	s.keysHash[name] = val
       
    93 	return s.keys[name], nil
       
    94 }
       
    95 
       
    96 // NewBooleanKey creates a new boolean type key to given section.
       
    97 func (s *Section) NewBooleanKey(name string) (*Key, error) {
       
    98 	key, err := s.NewKey(name, "true")
       
    99 	if err != nil {
       
   100 		return nil, err
       
   101 	}
       
   102 
       
   103 	key.isBooleanType = true
       
   104 	return key, nil
       
   105 }
       
   106 
       
   107 // GetKey returns key in section by given name.
       
   108 func (s *Section) GetKey(name string) (*Key, error) {
       
   109 	if s.f.BlockMode {
       
   110 		s.f.lock.RLock()
       
   111 	}
       
   112 	if s.f.options.Insensitive {
       
   113 		name = strings.ToLower(name)
       
   114 	}
       
   115 	key := s.keys[name]
       
   116 	if s.f.BlockMode {
       
   117 		s.f.lock.RUnlock()
       
   118 	}
       
   119 
       
   120 	if key == nil {
       
   121 		// Check if it is a child-section.
       
   122 		sname := s.name
       
   123 		for {
       
   124 			if i := strings.LastIndex(sname, "."); i > -1 {
       
   125 				sname = sname[:i]
       
   126 				sec, err := s.f.GetSection(sname)
       
   127 				if err != nil {
       
   128 					continue
       
   129 				}
       
   130 				return sec.GetKey(name)
       
   131 			}
       
   132 			break
       
   133 		}
       
   134 		return nil, fmt.Errorf("error when getting key of section '%s': key '%s' not exists", s.name, name)
       
   135 	}
       
   136 	return key, nil
       
   137 }
       
   138 
       
   139 // HasKey returns true if section contains a key with given name.
       
   140 func (s *Section) HasKey(name string) bool {
       
   141 	key, _ := s.GetKey(name)
       
   142 	return key != nil
       
   143 }
       
   144 
       
   145 // Deprecated: Use "HasKey" instead.
       
   146 func (s *Section) Haskey(name string) bool {
       
   147 	return s.HasKey(name)
       
   148 }
       
   149 
       
   150 // HasValue returns true if section contains given raw value.
       
   151 func (s *Section) HasValue(value string) bool {
       
   152 	if s.f.BlockMode {
       
   153 		s.f.lock.RLock()
       
   154 		defer s.f.lock.RUnlock()
       
   155 	}
       
   156 
       
   157 	for _, k := range s.keys {
       
   158 		if value == k.value {
       
   159 			return true
       
   160 		}
       
   161 	}
       
   162 	return false
       
   163 }
       
   164 
       
   165 // Key assumes named Key exists in section and returns a zero-value when not.
       
   166 func (s *Section) Key(name string) *Key {
       
   167 	key, err := s.GetKey(name)
       
   168 	if err != nil {
       
   169 		// It's OK here because the only possible error is empty key name,
       
   170 		// but if it's empty, this piece of code won't be executed.
       
   171 		key, _ = s.NewKey(name, "")
       
   172 		return key
       
   173 	}
       
   174 	return key
       
   175 }
       
   176 
       
   177 // Keys returns list of keys of section.
       
   178 func (s *Section) Keys() []*Key {
       
   179 	keys := make([]*Key, len(s.keyList))
       
   180 	for i := range s.keyList {
       
   181 		keys[i] = s.Key(s.keyList[i])
       
   182 	}
       
   183 	return keys
       
   184 }
       
   185 
       
   186 // ParentKeys returns list of keys of parent section.
       
   187 func (s *Section) ParentKeys() []*Key {
       
   188 	var parentKeys []*Key
       
   189 	sname := s.name
       
   190 	for {
       
   191 		if i := strings.LastIndex(sname, "."); i > -1 {
       
   192 			sname = sname[:i]
       
   193 			sec, err := s.f.GetSection(sname)
       
   194 			if err != nil {
       
   195 				continue
       
   196 			}
       
   197 			parentKeys = append(parentKeys, sec.Keys()...)
       
   198 		} else {
       
   199 			break
       
   200 		}
       
   201 
       
   202 	}
       
   203 	return parentKeys
       
   204 }
       
   205 
       
   206 // KeyStrings returns list of key names of section.
       
   207 func (s *Section) KeyStrings() []string {
       
   208 	list := make([]string, len(s.keyList))
       
   209 	copy(list, s.keyList)
       
   210 	return list
       
   211 }
       
   212 
       
   213 // KeysHash returns keys hash consisting of names and values.
       
   214 func (s *Section) KeysHash() map[string]string {
       
   215 	if s.f.BlockMode {
       
   216 		s.f.lock.RLock()
       
   217 		defer s.f.lock.RUnlock()
       
   218 	}
       
   219 
       
   220 	hash := map[string]string{}
       
   221 	for key, value := range s.keysHash {
       
   222 		hash[key] = value
       
   223 	}
       
   224 	return hash
       
   225 }
       
   226 
       
   227 // DeleteKey deletes a key from section.
       
   228 func (s *Section) DeleteKey(name string) {
       
   229 	if s.f.BlockMode {
       
   230 		s.f.lock.Lock()
       
   231 		defer s.f.lock.Unlock()
       
   232 	}
       
   233 
       
   234 	for i, k := range s.keyList {
       
   235 		if k == name {
       
   236 			s.keyList = append(s.keyList[:i], s.keyList[i+1:]...)
       
   237 			delete(s.keys, name)
       
   238 			delete(s.keysHash, name)
       
   239 			return
       
   240 		}
       
   241 	}
       
   242 }
       
   243 
       
   244 // ChildSections returns a list of child sections of current section.
       
   245 // For example, "[parent.child1]" and "[parent.child12]" are child sections
       
   246 // of section "[parent]".
       
   247 func (s *Section) ChildSections() []*Section {
       
   248 	prefix := s.name + "."
       
   249 	children := make([]*Section, 0, 3)
       
   250 	for _, name := range s.f.sectionList {
       
   251 		if strings.HasPrefix(name, prefix) {
       
   252 			children = append(children, s.f.sections[name])
       
   253 		}
       
   254 	}
       
   255 	return children
       
   256 }