Codebase list golang-github-go-ini-ini / c5b79860-e682-46aa-b39d-83ad17b52ee0/main ini.go
c5b79860-e682-46aa-b39d-83ad17b52ee0/main

Tree @c5b79860-e682-46aa-b39d-83ad17b52ee0/main (Download .tar.gz)

ini.go @c5b79860-e682-46aa-b39d-83ad17b52ee0/main

fa6ee69
 
9193b9a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5cf4342
9193b9a
 
91a7cdb
9193b9a
 
91a7cdb
9193b9a
 
 
d79353d
f461e76
ece0e89
f461e76
9193b9a
ece0e89
9193b9a
 
 
d79353d
 
9193b9a
 
 
8fe4743
c51d513
d79353d
30c8783
4090f13
d79353d
458858a
8fe4743
 
 
 
 
 
 
 
 
9193b9a
 
91a7cdb
 
9193b9a
91a7cdb
9193b9a
 
 
 
d79353d
2cd302a
d84ec27
2cd302a
 
 
f1d9ab1
 
 
 
d84ec27
 
1730955
 
af26abd
 
fcd0515
 
a2610b3
 
 
6a67acc
 
32e4c1e
 
 
ecf7343
 
 
 
 
7af1ffd
 
 
 
 
a343d98
 
7a6f455
a343d98
 
 
 
af26abd
9a250b4
4b84ed0
8d6d083
 
61b7223
8e0f5b3
29f972a
 
c856070
8b99162
0f135c9
 
 
 
faf04e2
 
2cd302a
 
0f135c9
 
 
d79353d
2cd302a
9193b9a
 
 
 
 
 
 
 
 
 
 
2cd302a
03e0e7d
 
 
 
9193b9a
 
7e829a0
 
 
 
2cd302a
7e829a0
 
 
 
 
2cd302a
 
 
 
 
 
 
7e829a0
 
d58d458
74bdc99
 
 
 
// +build go1.6

// Copyright 2014 Unknwon
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

// Package ini provides INI file read and write functionality in Go.
package ini

import (
	"os"
	"regexp"
	"runtime"
	"strings"
)

const (
	// DefaultSection is the name of default section. You can use this constant or the string literal.
	// In most of cases, an empty string is all you need to access the section.
	DefaultSection = "DEFAULT"

	// Maximum allowed depth when recursively substituing variable names.
	depthValues = 99
)

var (
	// LineBreak is the delimiter to determine or compose a new line.
	// This variable will be changed to "\r\n" automatically on Windows at package init time.
	LineBreak = "\n"

	// Variable regexp pattern: %(variable)s
	varPattern = regexp.MustCompile(`%\(([^)]+)\)s`)

	// DefaultHeader explicitly writes default section header.
	DefaultHeader = false

	// PrettySection indicates whether to put a line between sections.
	PrettySection = true
	// PrettyFormat indicates whether to align "=" sign with spaces to produce pretty output
	// or reduce all possible spaces for compact format.
	PrettyFormat = true
	// PrettyEqual places spaces around "=" sign even when PrettyFormat is false.
	PrettyEqual = false
	// DefaultFormatLeft places custom spaces on the left when PrettyFormat and PrettyEqual are both disabled.
	DefaultFormatLeft = ""
	// DefaultFormatRight places custom spaces on the right when PrettyFormat and PrettyEqual are both disabled.
	DefaultFormatRight = ""
)

var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test")

func init() {
	if runtime.GOOS == "windows" && !inTest {
		LineBreak = "\r\n"
	}
}

// LoadOptions contains all customized options used for load data source(s).
type LoadOptions struct {
	// Loose indicates whether the parser should ignore nonexistent files or return error.
	Loose bool
	// Insensitive indicates whether the parser forces all section and key names to lowercase.
	Insensitive bool
	// InsensitiveSections indicates whether the parser forces all section to lowercase.
	InsensitiveSections bool
	// InsensitiveKeys indicates whether the parser forces all key names to lowercase.
	InsensitiveKeys bool
	// IgnoreContinuation indicates whether to ignore continuation lines while parsing.
	IgnoreContinuation bool
	// IgnoreInlineComment indicates whether to ignore comments at the end of value and treat it as part of value.
	IgnoreInlineComment bool
	// SkipUnrecognizableLines indicates whether to skip unrecognizable lines that do not conform to key/value pairs.
	SkipUnrecognizableLines bool
	// ShortCircuit indicates whether to ignore other configuration sources after loaded the first available configuration source.
	ShortCircuit bool
	// AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing.
	// This type of keys are mostly used in my.cnf.
	AllowBooleanKeys bool
	// AllowShadows indicates whether to keep track of keys with same name under same section.
	AllowShadows bool
	// AllowNestedValues indicates whether to allow AWS-like nested values.
	// Docs: http://docs.aws.amazon.com/cli/latest/topic/config-vars.html#nested-values
	AllowNestedValues bool
	// AllowPythonMultilineValues indicates whether to allow Python-like multi-line values.
	// Docs: https://docs.python.org/3/library/configparser.html#supported-ini-file-structure
	// Relevant quote:  Values can also span multiple lines, as long as they are indented deeper
	// than the first line of the value.
	AllowPythonMultilineValues bool
	// SpaceBeforeInlineComment indicates whether to allow comment symbols (\# and \;) inside value.
	// Docs: https://docs.python.org/2/library/configparser.html
	// Quote: Comments may appear on their own in an otherwise empty line, or may be entered in lines holding values or section names.
	// In the latter case, they need to be preceded by a whitespace character to be recognized as a comment.
	SpaceBeforeInlineComment bool
	// UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format
	// when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value"
	UnescapeValueDoubleQuotes bool
	// UnescapeValueCommentSymbols indicates to unescape comment symbols (\# and \;) inside value to regular format
	// when value is NOT surrounded by any quotes.
	// Note: UNSTABLE, behavior might change to only unescape inside double quotes but may noy necessary at all.
	UnescapeValueCommentSymbols bool
	// UnparseableSections stores a list of blocks that are allowed with raw content which do not otherwise
	// conform to key/value pairs. Specify the names of those blocks here.
	UnparseableSections []string
	// KeyValueDelimiters is the sequence of delimiters that are used to separate key and value. By default, it is "=:".
	KeyValueDelimiters string
	// KeyValueDelimiterOnWrite is the delimiter that are used to separate key and value output. By default, it is "=".
	KeyValueDelimiterOnWrite string
	// ChildSectionDelimiter is the delimiter that is used to separate child sections. By default, it is ".".
	ChildSectionDelimiter string
	// PreserveSurroundedQuote indicates whether to preserve surrounded quote (single and double quotes).
	PreserveSurroundedQuote bool
	// DebugFunc is called to collect debug information (currently only useful to debug parsing Python-style multiline values).
	DebugFunc DebugFunc
	// ReaderBufferSize is the buffer size of the reader in bytes.
	ReaderBufferSize int
	// AllowNonUniqueSections indicates whether to allow sections with the same name multiple times.
	AllowNonUniqueSections bool
}

// DebugFunc is the type of function called to log parse events.
type DebugFunc func(message string)

// LoadSources allows caller to apply customized options for loading from data source(s).
func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) {
	sources := make([]dataSource, len(others)+1)
	sources[0], err = parseDataSource(source)
	if err != nil {
		return nil, err
	}
	for i := range others {
		sources[i+1], err = parseDataSource(others[i])
		if err != nil {
			return nil, err
		}
	}
	f := newFile(sources, opts)
	if err = f.Reload(); err != nil {
		return nil, err
	}
	return f, nil
}

// Load loads and parses from INI data sources.
// Arguments can be mixed of file name with string type, or raw data in []byte.
// It will return error if list contains nonexistent files.
func Load(source interface{}, others ...interface{}) (*File, error) {
	return LoadSources(LoadOptions{}, source, others...)
}

// LooseLoad has exactly same functionality as Load function
// except it ignores nonexistent files instead of returning error.
func LooseLoad(source interface{}, others ...interface{}) (*File, error) {
	return LoadSources(LoadOptions{Loose: true}, source, others...)
}

// InsensitiveLoad has exactly same functionality as Load function
// except it forces all section and key names to be lowercased.
func InsensitiveLoad(source interface{}, others ...interface{}) (*File, error) {
	return LoadSources(LoadOptions{Insensitive: true}, source, others...)
}

// ShadowLoad has exactly same functionality as Load function
// except it allows have shadow keys.
func ShadowLoad(source interface{}, others ...interface{}) (*File, error) {
	return LoadSources(LoadOptions{AllowShadows: true}, source, others...)
}