1// +build go1.6 2 3// Copyright 2014 Unknwon 4// 5// Licensed under the Apache License, Version 2.0 (the "License"): you may 6// not use this file except in compliance with the License. You may obtain 7// a copy of the License at 8// 9// http://www.apache.org/licenses/LICENSE-2.0 10// 11// Unless required by applicable law or agreed to in writing, software 12// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14// License for the specific language governing permissions and limitations 15// under the License. 16 17// Package ini provides INI file read and write functionality in Go. 18package ini 19 20import ( 21 "regexp" 22 "runtime" 23) 24 25const ( 26 // DefaultSection is the name of default section. You can use this constant or the string literal. 27 // In most of cases, an empty string is all you need to access the section. 28 DefaultSection = "DEFAULT" 29 30 // Maximum allowed depth when recursively substituing variable names. 31 depthValues = 99 32 version = "1.51.1" 33) 34 35// Version returns current package version literal. 36func Version() string { 37 return version 38} 39 40var ( 41 // LineBreak is the delimiter to determine or compose a new line. 42 // This variable will be changed to "\r\n" automatically on Windows at package init time. 43 LineBreak = "\n" 44 45 // Variable regexp pattern: %(variable)s 46 varPattern = regexp.MustCompile(`%\(([^)]+)\)s`) 47 48 // DefaultHeader explicitly writes default section header. 49 DefaultHeader = false 50 51 // PrettySection indicates whether to put a line between sections. 52 PrettySection = true 53 // PrettyFormat indicates whether to align "=" sign with spaces to produce pretty output 54 // or reduce all possible spaces for compact format. 55 PrettyFormat = true 56 // PrettyEqual places spaces around "=" sign even when PrettyFormat is false. 57 PrettyEqual = false 58 // DefaultFormatLeft places custom spaces on the left when PrettyFormat and PrettyEqual are both disabled. 59 DefaultFormatLeft = "" 60 // DefaultFormatRight places custom spaces on the right when PrettyFormat and PrettyEqual are both disabled. 61 DefaultFormatRight = "" 62) 63 64func init() { 65 if runtime.GOOS == "windows" { 66 LineBreak = "\r\n" 67 } 68} 69 70// LoadOptions contains all customized options used for load data source(s). 71type LoadOptions struct { 72 // Loose indicates whether the parser should ignore nonexistent files or return error. 73 Loose bool 74 // Insensitive indicates whether the parser forces all section and key names to lowercase. 75 Insensitive bool 76 // IgnoreContinuation indicates whether to ignore continuation lines while parsing. 77 IgnoreContinuation bool 78 // IgnoreInlineComment indicates whether to ignore comments at the end of value and treat it as part of value. 79 IgnoreInlineComment bool 80 // SkipUnrecognizableLines indicates whether to skip unrecognizable lines that do not conform to key/value pairs. 81 SkipUnrecognizableLines bool 82 // AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing. 83 // This type of keys are mostly used in my.cnf. 84 AllowBooleanKeys bool 85 // AllowShadows indicates whether to keep track of keys with same name under same section. 86 AllowShadows bool 87 // AllowNestedValues indicates whether to allow AWS-like nested values. 88 // Docs: http://docs.aws.amazon.com/cli/latest/topic/config-vars.html#nested-values 89 AllowNestedValues bool 90 // AllowPythonMultilineValues indicates whether to allow Python-like multi-line values. 91 // Docs: https://docs.python.org/3/library/configparser.html#supported-ini-file-structure 92 // Relevant quote: Values can also span multiple lines, as long as they are indented deeper 93 // than the first line of the value. 94 AllowPythonMultilineValues bool 95 // SpaceBeforeInlineComment indicates whether to allow comment symbols (\# and \;) inside value. 96 // Docs: https://docs.python.org/2/library/configparser.html 97 // Quote: Comments may appear on their own in an otherwise empty line, or may be entered in lines holding values or section names. 98 // In the latter case, they need to be preceded by a whitespace character to be recognized as a comment. 99 SpaceBeforeInlineComment bool 100 // UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format 101 // when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value" 102 UnescapeValueDoubleQuotes bool 103 // UnescapeValueCommentSymbols indicates to unescape comment symbols (\# and \;) inside value to regular format 104 // when value is NOT surrounded by any quotes. 105 // Note: UNSTABLE, behavior might change to only unescape inside double quotes but may noy necessary at all. 106 UnescapeValueCommentSymbols bool 107 // UnparseableSections stores a list of blocks that are allowed with raw content which do not otherwise 108 // conform to key/value pairs. Specify the names of those blocks here. 109 UnparseableSections []string 110 // KeyValueDelimiters is the sequence of delimiters that are used to separate key and value. By default, it is "=:". 111 KeyValueDelimiters string 112 // PreserveSurroundedQuote indicates whether to preserve surrounded quote (single and double quotes). 113 PreserveSurroundedQuote bool 114 // DebugFunc is called to collect debug information (currently only useful to debug parsing Python-style multiline values). 115 DebugFunc DebugFunc 116 // ReaderBufferSize is the buffer size of the reader in bytes. 117 ReaderBufferSize int 118} 119 120// DebugFunc is the type of function called to log parse events. 121type DebugFunc func(message string) 122 123// LoadSources allows caller to apply customized options for loading from data source(s). 124func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) { 125 sources := make([]dataSource, len(others)+1) 126 sources[0], err = parseDataSource(source) 127 if err != nil { 128 return nil, err 129 } 130 for i := range others { 131 sources[i+1], err = parseDataSource(others[i]) 132 if err != nil { 133 return nil, err 134 } 135 } 136 f := newFile(sources, opts) 137 if err = f.Reload(); err != nil { 138 return nil, err 139 } 140 return f, nil 141} 142 143// Load loads and parses from INI data sources. 144// Arguments can be mixed of file name with string type, or raw data in []byte. 145// It will return error if list contains nonexistent files. 146func Load(source interface{}, others ...interface{}) (*File, error) { 147 return LoadSources(LoadOptions{}, source, others...) 148} 149 150// LooseLoad has exactly same functionality as Load function 151// except it ignores nonexistent files instead of returning error. 152func LooseLoad(source interface{}, others ...interface{}) (*File, error) { 153 return LoadSources(LoadOptions{Loose: true}, source, others...) 154} 155 156// InsensitiveLoad has exactly same functionality as Load function 157// except it forces all section and key names to be lowercased. 158func InsensitiveLoad(source interface{}, others ...interface{}) (*File, error) { 159 return LoadSources(LoadOptions{Insensitive: true}, source, others...) 160} 161 162// ShadowLoad has exactly same functionality as Load function 163// except it allows have shadow keys. 164func ShadowLoad(source interface{}, others ...interface{}) (*File, error) { 165 return LoadSources(LoadOptions{AllowShadows: true}, source, others...) 166} 167