iniconf

package module
v0.0.0-...-50b0c5b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 21, 2016 License: MIT Imports: 13 Imported by: 0

README

IniConf

Overview

This Go library provides read/write support for .ini formatted configuration files.

It also provides support for reloading files and notifying observers of changes that have occurred.

Documentation

Overview

Read/Write settings from a .ini formatted configuration file.

This package allows for .ini text files to be created, loaded, reloaded, saved and updated. It also allows for notifications to be sent to observers when sections or keys change either explictly via calls to the instance, or via a call to Reload()

When saving/updating files it preserves the original order of entries that were in the file on disk at the point it's saved, along with any comments and spacing contained in it.

The IniConf type reads and writes .ini files and provides access to their contents.

The ChainConf type allows multiple .ini files (on disk or in memory) to be chained together, allowing for in-memory defaults to be overriden by an on-disk configuration file.

Index

Examples

Constants

View Source
const (
	ErrInvalidSection = iota
	ErrInvalidEntry
	ErrLineTooLong
	ErrNoSection
)

ParseError codes.

Variables

View Source
var (
	ErrDuplicateSection = errors.New("Duplicate section name")
	ErrInvalidEntryName = errors.New("Invalid name used for entry")
	ErrEntryNotFound    = errors.New("Entry not found in section")
	ErrSectionNotFound  = errors.New("Section not found")
	ErrReloadNoFilename = errors.New("Cannot reload; no filename specified")
	ErrSaveNoFilename   = errors.New("Cannot save; no filename specified")
	ErrEmptyEntryValue  = errors.New("Cannot assign empty string to an entry")
	ErrBadObserver      = errors.New("Attempted to register observer that does not implement an observer interface")
	ErrEmptyConfChain   = errors.New("ConfChain has no configuration files")
)
View Source
var (
	ErrInvalidType      = errors.New("target must be a pointer")
	ErrInvalidFieldType = errors.New("target must be a string, int or bool")
)

Functions

This section is empty.

Types

type ConfChain

type ConfChain struct {
	// contains filtered or unexported fields
}

A ConfChain reads sequentially from a list of IniConf configurations, returning a result from the first IniConf that has a value set for a requested setting.

Useful if you want a .ini file on disk to override an in-memory set of defaults.

Example

This example creates two configuration files (though could just as easily load one or more from file using LoadFile()) and chains them together so that calls to EntryString() will attempt to fetch a value from the primary config file first, and then fallback to reading from the default.

There's no limit to the number of config files you can have in a chain

package main

import (
	"fmt"

	"github.com/gwatts/iniconf"
)

func main() {
	var primaryConfText = `
[section one]
key1 = val1
`
	var defaultConfText = `
[section one]
key1 = default1
key2 = default2
`
	// Load our primary and default config files
	primaryConf, _ := iniconf.LoadString(primaryConfText, true)
	defaultConf, _ := iniconf.LoadString(defaultConfText, true)

	// create the chain
	chain := iniconf.NewConfChain(primaryConf, defaultConf)

	// key1 will be read from the primary
	key1, _ := chain.EntryString("section one", "key1")

	// primary doesn't have key2 set, so will read from default
	key2, _ := chain.EntryString("section one", "key2")

	fmt.Println("key1:", key1)
	fmt.Println("key2:", key2)

}
Output:

key1: val1
key2: default2

func NewConfChain

func NewConfChain(confSet ...*IniConf) *ConfChain

Create a new chain.

IniConfs will be read from in preference from first to last specified here ie. the IniConf holding the default values to fallback to should be the last argument to this function.

func (*ConfChain) AddConf

func (cc *ConfChain) AddConf(i *IniConf)

AddConf adds an additional IniConf file to the chain at a lower priority than those already configured.

func (*ConfChain) EntryBool

func (cc *ConfChain) EntryBool(sectionName, entryName string) (bool, error)

Fetch a boolean entry from a section from the first IniConf that returns a value.

func (*ConfChain) EntryBoolP

func (cc *ConfChain) EntryBoolP(sectionName, entryName string) bool

EntryBoolP fetches a boolean entry from a section from the first IniConf that returns a value.

Unlike EntryBool(), It panics if no IniConfs contain the setting.

func (*ConfChain) EntryInt

func (cc *ConfChain) EntryInt(sectionName, entryName string) (int64, error)

EntryInt fetches an integer entry from a section from the first IniConf that returns a value.

func (*ConfChain) EntryIntP

func (cc *ConfChain) EntryIntP(sectionName, entryName string) int64

EntryIntP fetches an integer entry from a section from the first IniConf that returns a value.

Unlike EntryInt(), It panics if no IniConfs contain the setting.

func (*ConfChain) EntryString

func (cc *ConfChain) EntryString(sectionName, entryName string) (string, error)

EntryString fetches a string entry from a section from the first IniConf that returns a value.

func (*ConfChain) EntryStringP

func (cc *ConfChain) EntryStringP(sectionName, entryName string) string

EntryStringP fetches a string entry from a section from the first IniConf that returns a value.

Unlike EntryString(), It panics if no IniConfs contain the setting.

func (*ConfChain) HasSection

func (cc *ConfChain) HasSection(sectionName string) bool

func (*ConfChain) ReadSection

func (cc *ConfChain) ReadSection(sectionName string, v interface{}) error

ReadSection maps an IniConf section into a struct

Each field in the struct to be read from the section should be tagged with `iniconf:"keyname"`

Only string, bool and int types are supported

Nested structs are flattened into the parent's namespace.

type DeleteSectionObserver

type DeleteSectionObserver interface {
	IniSectionDeleted(i *IniConf, sectionName string)
}

Types implementing the DeleteSectionObserver interface may be passed to RegisterGlobalObserver or RegisterSectionObserver to be advised of sections being deleted.

type EntryChangeObserver

type EntryChangeObserver interface {
	IniEntryChanged(i *IniConf, sectionName, entryName, oldValue, newValue string)
}

Types implementing the EntryChangeObserver interface may be passed to RegisterGlobalObserver or RegisterSectionObserver to be advised of entries within sections being added, removed or updated.

New entries will have an empty oldValue. Deleted entries will have an empty newValue.

type IniConf

type IniConf struct {
	// contains filtered or unexported fields
}

An IniConf holds configuration information read from a file in .ini format.

ini files are made up of sections containing entry keys and values.

All public methods of IniConf are safe to use from concurrent goroutines.

This implementation supports line comments beginning with a semi colon and multi-line values where the second and subsequent lines for the value begin with a space.

Keys and values may be any UTF8 strings.

Comments inline with a value are not supported.

Example
package main

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/gwatts/iniconf"
)

func main() {
	// create an example configuration file to work with
	var exampleConf = `
[section one]
key1 = val1
`

	tf, err := ioutil.TempFile(os.TempDir(), "iniconf")
	if err != nil {
		fmt.Println("Failed to create tempfile:", err)
	}
	defer os.Remove(tf.Name())
	tf.Write([]byte(exampleConf))
	tf.Close()

	// Load the configuration file
	conf, err := iniconf.LoadFile(tf.Name(), true)
	if err != nil {
		fmt.Println("Failed to load file:", err)
	}

	// Print the current value of section1, key1
	key1, err := conf.EntryString("section one", "key1")
	if err != nil {
		fmt.Println("Couldn't read key1:", err)
		return
	}
	fmt.Println("Key1 is currently set to", key1)

	// Update key1
	conf.SetEntry("section one", "key1", "new value")

	// Add another key in another section
	conf.SetEntry("new section", "some number", 42)

	// Save it
	err = conf.Save()
	if err != nil {
		fmt.Println("Failed to save configuration file:", err)
	}

	fmt.Println("File saved")

}
Output:

Key1 is currently set to val1
File saved

func LoadEnviron

func LoadEnviron(prefix string, caseSensitive bool) (*IniConf, error)

LoadEnviron loads a .ini file from environment variables.

Each environment variable must in the format: prefix__section__key=value

func LoadFile

func LoadFile(filename string, caseSensitive bool) (*IniConf, error)

LoadFile loads a .ini file from an existing file on disk. / Once loaded it can be edited and saved by calling Save().

func LoadReader

func LoadReader(r io.Reader, caseSensitive bool) (*IniConf, error)

LoadReader loads a .ini file from an io.Reader.

Use SaveToFilename() to save.

func LoadString

func LoadString(s string, caseSensitive bool) (*IniConf, error)

LoadString load a .ini file from a string.

Use SaveToFilename() to save.

func New

func New(caseSensitive bool) *IniConf

New creates a new unnamed .ini file.

Specifying caseSensitive=true causes section and entry names to be cAsE sensitive (ie. section1 and Section1 map to two different sections)

Use SaveToFilename() to save.

func NewFile

func NewFile(filename string, caseSensitive bool) *IniConf

NewFile creates a new .ini file with defined filename.

Use Save() to write the contents to disk.

func (*IniConf) DeleteEntry

func (i *IniConf) DeleteEntry(sectionName, entryName string) (err error)

DeleteEntry delets an entry from a section.

Will return a ErrEntryNotFound error if the entry doesn't exist.

func (*IniConf) DeleteSection

func (i *IniConf) DeleteSection(name string) error

DeleteSection deletes a section and all of its entries.

Will return ErrSectionNotFound if the section doesn't exist.

func (*IniConf) DisableObservers

func (i *IniConf) DisableObservers()

DisableObservers temporarily disables observer notifications. Any notifications that would of been generated after this call has been made will be discarded.

func (*IniConf) EnableObservers

func (i *IniConf) EnableObservers()

EnableObservers re-enables all observers.

func (*IniConf) EntryBool

func (i *IniConf) EntryBool(sectionName, entryName string) (bool, error)

EntryBool an entry from the section as a boolean.

Returns a ErrEntryNotFound error if the entry isn't in the section.

func (*IniConf) EntryInt

func (i *IniConf) EntryInt(sectionName, entryName string) (int64, error)

EntryInt fetches an entry from the section as integer.

Returns a ErrEntryNotFound error if the entry isn't in the section.

func (*IniConf) EntryNames

func (i *IniConf) EntryNames(sectionName string) (result []string)

EntryNames returns a list of the entry names defined in a section.

Returns nil if the section does not exist.

func (*IniConf) EntryString

func (i *IniConf) EntryString(sectionName, entryName string) (string, error)

EntryString fetches an entry from a section as a string.

Returns a ErrEntryNotFound error if the entry isn't in the section.

func (*IniConf) HasSection

func (i *IniConf) HasSection(sectionName string) bool

HasSection returns true if the section is defined in the configuration even if the section contains no entries.

func (*IniConf) NewSection

func (i *IniConf) NewSection(name string) (err error)

NewSection creates a new empty section. It returns ErrDuplicateSection if the section already exists.

Note: If you just want to add a new entry to a section that doesn't yet exist then you can just call SetEntry() directly and the section will be auto-created.

func (*IniConf) ReadSection

func (i *IniConf) ReadSection(sectionName string, v interface{}) error

ReadSection maps an IniConf section into a struct

Each field in the struct to be read from the section should be tagged with `iniconf:"keyname"`

Only string, bool and int types are supported

Nested structs are flattened into the parent's namespace.

Example
package main

import "fmt"
import "github.com/gwatts/iniconf"

var inifile = `
[mysection]
value1 = First value
num1 = 123
bool1 = true
subvalue = nested value
`

type section struct {
	Value1 string `iniconf:"value1"`
	Num1   int    `iniconf:"num1"`
	Bool1  bool   `iniconf:"bool1"`
	Sub    struct {
		SubValue string `iniconf:"subvalue"`
	}
}

func main() {
	var s section
	cfg, _ := iniconf.LoadString(inifile, false)
	if err := cfg.ReadSection("mysection", &s); err != nil {
		fmt.Println("Failed", err)
		return
	}

	fmt.Println("Value1:", s.Value1)
	fmt.Println("Num1:", s.Num1)
	fmt.Println("Bool1:", s.Bool1)
	fmt.Println("Sub:", s.Sub.SubValue)

}
Output:

Value1: First value
Num1: 123
Bool1: true
Sub: nested value

func (*IniConf) RegisterGlobalObserver

func (i *IniConf) RegisterGlobalObserver(ob interface{})

RegisterGlobalRegister registers an observer to be notified of all section and/or entry updates.

The observer must implement one or more of the NewSectionObserver, DeleteSectionObserver and EntryChangeObserver interfaces. Additionally you should pass a pointer to that observer to this method else UnregisterObserver will fail to remove the observer.

func (*IniConf) RegisterSectionObserver

func (i *IniConf) RegisterSectionObserver(sectionName string, ob interface{})

RegisterSectionObserver registers an observer to be notified of changes to a named section, whether or not it exists yet.

The observer must implement one or more of the NewSectionObserver, DeleteSectionObserver and EntryChangeObserver interfaces. Additionally you should pass a pointer to that observer to this method else UnregisterObserver will fail to remove the observer.

func (*IniConf) Reload

func (i *IniConf) Reload() error

Reload the configuration file by re-reading the file from disk. The .ini file must either have been created using LoadFile() or have been saved using SaveToFilename() for a reload to succeed.

Any unsaved changes will be lost.

func (*IniConf) Save

func (i *IniConf) Save() error

Save the .ini file by updating any existing version on disk.

This will attempt to preserve the order of the entries in the original file along with comment in sections that weren't deleted.

The file must either have been initially loaded from file using LoadFile() or already been saved to a file using SaveToFilename().

func (*IniConf) SaveToFilename

func (i *IniConf) SaveToFilename(filename string) error

SaveToFilename save the IniConf to a new filename - Future calls to Save() will utilize the filename passed to this method.

func (*IniConf) Sections

func (i *IniConf) Sections() []string

Sections returns a list of defined section names.

func (*IniConf) SetEntry

func (i *IniConf) SetEntry(sectionName, entryName string, value interface{}) (err error)

SetEntry creates or updates an entry in a section.

Non-string values will be converted to a string using the fmt package.

If a converted value, stripped of leading/trailing whitespace results in a string of length zero, then an ErrEmptyEntryValue error will be returned.

func (*IniConf) String

func (i *IniConf) String() string

String returns the IniConf file as a string.

func (*IniConf) UnregisterGlobalObserver

func (i *IniConf) UnregisterGlobalObserver(ob interface{})

UnregisterGlobalObserver unregisters a previously registered global observer.

func (*IniConf) UnregisterSectionObserver

func (i *IniConf) UnregisterSectionObserver(sectionName string, ob interface{})

UnregisterSectionObserver unregisters a previously registered section observer.

func (*IniConf) UpdateSection

func (i *IniConf) UpdateSection(sectionName string, v interface{}) error

UpdateSection takes a struct tagged with `iniconf:"keyname"` fields and loads those fields into the named section.

Nested structs are flattened into the parent's namespace.

Existing fields in the second that are not defined in the struct are left intact.

type NewSectionObserver

type NewSectionObserver interface {
	IniSectionAdded(i *IniConf, sectionName string)
}

Types implementing the RegisterSectionObserver interface may be passed to RegisterGlobalObserver or RegisterSectionObserver to be advised of new sections being created.

type ParseError

type ParseError struct {
	// contains filtered or unexported fields
}

A ParseError is created if a syntax error is found while reading an ini file.

Implements the error interface.

func (*ParseError) Code

func (p *ParseError) Code() int

func (ParseError) Error

func (pe ParseError) Error() string

Returns the error message including the line number.

func (*ParseError) LineNum

func (p *ParseError) LineNum() int

Return the line number of the source file the error refers to

func (ParseError) Msg

func (p ParseError) Msg() string

Return the base message of the error, excluding the line number use the Error() method to get a message that includes the line number.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL