ran gofmt
This commit is contained in:
parent
5817e58bf8
commit
4cea74d15d
120
conf.go
120
conf.go
|
@ -39,7 +39,7 @@ import (
|
||||||
// ConfigFile is the representation of configuration settings.
|
// ConfigFile is the representation of configuration settings.
|
||||||
// The public interface is entirely through methods.
|
// The public interface is entirely through methods.
|
||||||
type ConfigFile struct {
|
type ConfigFile struct {
|
||||||
data map[string]map[string]string; // Maps sections to options to values.
|
data map[string]map[string]string // Maps sections to options to values.
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -56,61 +56,61 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DefaultSection = "default"; // Default section name (must be lower-case).
|
DefaultSection = "default" // Default section name (must be lower-case).
|
||||||
DepthValues = 200; // Maximum allowed depth when recursively substituing variable names.
|
DepthValues = 200 // Maximum allowed depth when recursively substituing variable names.
|
||||||
|
|
||||||
// Strings accepted as bool.
|
// Strings accepted as bool.
|
||||||
BoolStrings = map[string]bool{
|
BoolStrings = map[string]bool{
|
||||||
"t": true,
|
"t": true,
|
||||||
"true": true,
|
"true": true,
|
||||||
"y": true,
|
"y": true,
|
||||||
"yes": true,
|
"yes": true,
|
||||||
"on": true,
|
"on": true,
|
||||||
"1": true,
|
"1": true,
|
||||||
"f": false,
|
"f": false,
|
||||||
"false": false,
|
"false": false,
|
||||||
"n": false,
|
"n": false,
|
||||||
"no": false,
|
"no": false,
|
||||||
"off": false,
|
"off": false,
|
||||||
"0": false,
|
"0": false,
|
||||||
};
|
}
|
||||||
|
|
||||||
varRegExp = regexp.MustCompile(`%\(([a-zA-Z0-9_.\-]+)\)s`);
|
varRegExp = regexp.MustCompile(`%\(([a-zA-Z0-9_.\-]+)\)s`)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
// AddSection adds a new section to the configuration.
|
// AddSection adds a new section to the configuration.
|
||||||
// It returns true if the new section was inserted, and false if the section already existed.
|
// It returns true if the new section was inserted, and false if the section already existed.
|
||||||
func (c *ConfigFile) AddSection(section string) bool {
|
func (c *ConfigFile) AddSection(section string) bool {
|
||||||
section = strings.ToLower(section);
|
section = strings.ToLower(section)
|
||||||
|
|
||||||
if _, ok := c.data[section]; ok {
|
if _, ok := c.data[section]; ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
c.data[section] = make(map[string]string);
|
c.data[section] = make(map[string]string)
|
||||||
|
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// RemoveSection removes a section from the configuration.
|
// RemoveSection removes a section from the configuration.
|
||||||
// It returns true if the section was removed, and false if section did not exist.
|
// It returns true if the section was removed, and false if section did not exist.
|
||||||
func (c *ConfigFile) RemoveSection(section string) bool {
|
func (c *ConfigFile) RemoveSection(section string) bool {
|
||||||
section = strings.ToLower(section);
|
section = strings.ToLower(section)
|
||||||
|
|
||||||
switch _, ok := c.data[section]; {
|
switch _, ok := c.data[section]; {
|
||||||
case !ok:
|
case !ok:
|
||||||
return false
|
return false
|
||||||
case section == DefaultSection:
|
case section == DefaultSection:
|
||||||
return false // default section cannot be removed
|
return false // default section cannot be removed
|
||||||
default:
|
default:
|
||||||
for o, _ := range c.data[section] {
|
for o, _ := range c.data[section] {
|
||||||
c.data[section][o] = "", false
|
c.data[section][o] = "", false
|
||||||
}
|
}
|
||||||
c.data[section] = nil, false;
|
c.data[section] = nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,15 +118,15 @@ func (c *ConfigFile) RemoveSection(section string) bool {
|
||||||
// It returns true if the option and value were inserted, and false if the value was overwritten.
|
// It returns true if the option and value were inserted, and false if the value was overwritten.
|
||||||
// If the section does not exist in advance, it is created.
|
// If the section does not exist in advance, it is created.
|
||||||
func (c *ConfigFile) AddOption(section string, option string, value string) bool {
|
func (c *ConfigFile) AddOption(section string, option string, value string) bool {
|
||||||
c.AddSection(section); // make sure section exists
|
c.AddSection(section) // make sure section exists
|
||||||
|
|
||||||
section = strings.ToLower(section);
|
section = strings.ToLower(section)
|
||||||
option = strings.ToLower(option);
|
option = strings.ToLower(option)
|
||||||
|
|
||||||
_, ok := c.data[section][option];
|
_, ok := c.data[section][option]
|
||||||
c.data[section][option] = value;
|
c.data[section][option] = value
|
||||||
|
|
||||||
return !ok;
|
return !ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -134,17 +134,17 @@ func (c *ConfigFile) AddOption(section string, option string, value string) bool
|
||||||
// It returns true if the option and value were removed, and false otherwise,
|
// It returns true if the option and value were removed, and false otherwise,
|
||||||
// including if the section did not exist.
|
// including if the section did not exist.
|
||||||
func (c *ConfigFile) RemoveOption(section string, option string) bool {
|
func (c *ConfigFile) RemoveOption(section string, option string) bool {
|
||||||
section = strings.ToLower(section);
|
section = strings.ToLower(section)
|
||||||
option = strings.ToLower(option);
|
option = strings.ToLower(option)
|
||||||
|
|
||||||
if _, ok := c.data[section]; !ok {
|
if _, ok := c.data[section]; !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
_, ok := c.data[section][option];
|
_, ok := c.data[section][option]
|
||||||
c.data[section][option] = "", false;
|
c.data[section][option] = "", false
|
||||||
|
|
||||||
return ok;
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,12 +152,12 @@ func (c *ConfigFile) RemoveOption(section string, option string) bool {
|
||||||
// This representation can be filled with AddSection and AddOption and then
|
// This representation can be filled with AddSection and AddOption and then
|
||||||
// saved to a file using WriteConfigFile.
|
// saved to a file using WriteConfigFile.
|
||||||
func NewConfigFile() *ConfigFile {
|
func NewConfigFile() *ConfigFile {
|
||||||
c := new(ConfigFile);
|
c := new(ConfigFile)
|
||||||
c.data = make(map[string]map[string]string);
|
c.data = make(map[string]map[string]string)
|
||||||
|
|
||||||
c.AddSection(DefaultSection); // default section always exists
|
c.AddSection(DefaultSection) // default section always exists
|
||||||
|
|
||||||
return c;
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ func stripComments(l string) string {
|
||||||
l = l[0:i]
|
l = l[0:i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return l;
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -180,44 +180,44 @@ func firstIndex(s string, delim []byte) int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetError struct {
|
type GetError struct {
|
||||||
Reason int
|
Reason int
|
||||||
ValueType string
|
ValueType string
|
||||||
Value string
|
Value string
|
||||||
Section string
|
Section string
|
||||||
Option string
|
Option string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err GetError) String() string {
|
func (err GetError) String() string {
|
||||||
switch err.Reason {
|
switch err.Reason {
|
||||||
case SectionNotFound:
|
case SectionNotFound:
|
||||||
return fmt.Sprintf("section '%s' not found", err.Section)
|
return fmt.Sprintf("section '%s' not found", err.Section)
|
||||||
case OptionNotFound:
|
case OptionNotFound:
|
||||||
return fmt.Sprintf("option '%s' not found in section '%s'", err.Option, err.Section)
|
return fmt.Sprintf("option '%s' not found in section '%s'", err.Option, err.Section)
|
||||||
case CouldNotParse:
|
case CouldNotParse:
|
||||||
return fmt.Sprintf("could not parse %s value '%s'", err.ValueType, err.Value)
|
return fmt.Sprintf("could not parse %s value '%s'", err.ValueType, err.Value)
|
||||||
case MaxDepthReached:
|
case MaxDepthReached:
|
||||||
return fmt.Sprintf("possible cycle while unfolding variables: max depth of %d reached", DepthValues)
|
return fmt.Sprintf("possible cycle while unfolding variables: max depth of %d reached", DepthValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
return "invalid get error"
|
return "invalid get error"
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReadError struct {
|
type ReadError struct {
|
||||||
Reason int
|
Reason int
|
||||||
Line string
|
Line string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err ReadError) String() string {
|
func (err ReadError) String() string {
|
||||||
switch err.Reason {
|
switch err.Reason {
|
||||||
case BlankSection:
|
case BlankSection:
|
||||||
return "empty section name not allowed"
|
return "empty section name not allowed"
|
||||||
case CouldNotParse:
|
case CouldNotParse:
|
||||||
return fmt.Sprintf("could not parse line: %s", err.Line)
|
return fmt.Sprintf("could not parse line: %s", err.Line)
|
||||||
}
|
}
|
||||||
|
|
||||||
return "invalid read error"
|
return "invalid read error"
|
||||||
}
|
}
|
||||||
|
|
70
conf_test.go
70
conf_test.go
|
@ -1,6 +1,6 @@
|
||||||
package conf_test
|
package conf_test
|
||||||
|
|
||||||
import(
|
import (
|
||||||
. "conf"
|
. "conf"
|
||||||
"testing"
|
"testing"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -19,23 +19,23 @@ url = http://%(host)s/something`
|
||||||
|
|
||||||
type stringtest struct {
|
type stringtest struct {
|
||||||
section string
|
section string
|
||||||
option string
|
option string
|
||||||
answer string
|
answer string
|
||||||
}
|
}
|
||||||
|
|
||||||
type inttest struct {
|
type inttest struct {
|
||||||
section string
|
section string
|
||||||
option string
|
option string
|
||||||
answer int
|
answer int
|
||||||
}
|
}
|
||||||
|
|
||||||
type booltest struct {
|
type booltest struct {
|
||||||
section string
|
section string
|
||||||
option string
|
option string
|
||||||
answer bool
|
answer bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var testSet = []interface{} {
|
var testSet = []interface{}{
|
||||||
stringtest{"", "host", "example.com"},
|
stringtest{"", "host", "example.com"},
|
||||||
inttest{"default", "port", 43},
|
inttest{"default", "port", 43},
|
||||||
booltest{"default", "compression", true},
|
booltest{"default", "compression", true},
|
||||||
|
@ -52,33 +52,33 @@ func TestBuild(t *testing.T) {
|
||||||
|
|
||||||
for _, element := range testSet {
|
for _, element := range testSet {
|
||||||
switch i := element.(type) {
|
switch i := element.(type) {
|
||||||
case stringtest:
|
case stringtest:
|
||||||
e := element.(stringtest)
|
e := element.(stringtest)
|
||||||
ans, err := c.GetString(e.section, e.option)
|
ans, err := c.GetString(e.section, e.option)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("c.GetString(\"" + e.section + "\",\"" + e.option + "\") returned error: " + err.String())
|
t.Error("c.GetString(\"" + e.section + "\",\"" + e.option + "\") returned error: " + err.String())
|
||||||
}
|
}
|
||||||
if ans != e.answer {
|
if ans != e.answer {
|
||||||
t.Error("c.GetString(\"" + e.section + "\",\"" + e.option + "\") returned incorrect answer: " + ans)
|
t.Error("c.GetString(\"" + e.section + "\",\"" + e.option + "\") returned incorrect answer: " + ans)
|
||||||
}
|
}
|
||||||
case inttest:
|
case inttest:
|
||||||
e := element.(inttest)
|
e := element.(inttest)
|
||||||
ans, err := c.GetInt(e.section, e.option)
|
ans, err := c.GetInt(e.section, e.option)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("c.GetInt(\"" + e.section + "\",\"" + e.option + "\") returned error: " + err.String())
|
t.Error("c.GetInt(\"" + e.section + "\",\"" + e.option + "\") returned error: " + err.String())
|
||||||
}
|
}
|
||||||
if ans != e.answer {
|
if ans != e.answer {
|
||||||
t.Error("c.GetInt(\"" + e.section + "\",\"" + e.option + "\") returned incorrect answer: " + strconv.Itoa(ans))
|
t.Error("c.GetInt(\"" + e.section + "\",\"" + e.option + "\") returned incorrect answer: " + strconv.Itoa(ans))
|
||||||
}
|
}
|
||||||
case booltest:
|
case booltest:
|
||||||
e := element.(booltest)
|
e := element.(booltest)
|
||||||
ans, err := c.GetBool(e.section, e.option)
|
ans, err := c.GetBool(e.section, e.option)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("c.GetBool(\"" + e.section + "\",\"" + e.option + "\") returned error: " + err.String())
|
t.Error("c.GetBool(\"" + e.section + "\",\"" + e.option + "\") returned error: " + err.String())
|
||||||
}
|
}
|
||||||
if ans != e.answer {
|
if ans != e.answer {
|
||||||
t.Error("c.GetBool(\"" + e.section + "\",\"" + e.option + "\") returned incorrect answer")
|
t.Error("c.GetBool(\"" + e.section + "\",\"" + e.option + "\") returned incorrect answer")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
100
get.go
100
get.go
|
@ -9,24 +9,26 @@ import (
|
||||||
// GetSections returns the list of sections in the configuration.
|
// GetSections returns the list of sections in the configuration.
|
||||||
// (The default section always exists.)
|
// (The default section always exists.)
|
||||||
func (c *ConfigFile) GetSections() (sections []string) {
|
func (c *ConfigFile) GetSections() (sections []string) {
|
||||||
sections = make([]string, len(c.data));
|
sections = make([]string, len(c.data))
|
||||||
|
|
||||||
i := 0;
|
i := 0
|
||||||
for s, _ := range c.data {
|
for s, _ := range c.data {
|
||||||
sections[i] = s;
|
sections[i] = s
|
||||||
i++;
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
return sections;
|
return sections
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasSection checks if the configuration has the given section.
|
// HasSection checks if the configuration has the given section.
|
||||||
// (The default section always exists.)
|
// (The default section always exists.)
|
||||||
func (c *ConfigFile) HasSection(section string) bool {
|
func (c *ConfigFile) HasSection(section string) bool {
|
||||||
if section == "" {section = "default"}
|
if section == "" {
|
||||||
_, ok := c.data[strings.ToLower(section)];
|
section = "default"
|
||||||
|
}
|
||||||
|
_, ok := c.data[strings.ToLower(section)]
|
||||||
|
|
||||||
return ok;
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,43 +36,47 @@ func (c *ConfigFile) HasSection(section string) bool {
|
||||||
// It returns an error if the section does not exist and an empty list if the section is empty.
|
// It returns an error if the section does not exist and an empty list if the section is empty.
|
||||||
// Options within the default section are also included.
|
// Options within the default section are also included.
|
||||||
func (c *ConfigFile) GetOptions(section string) (options []string, err os.Error) {
|
func (c *ConfigFile) GetOptions(section string) (options []string, err os.Error) {
|
||||||
if section == "" {section = "default"}
|
if section == "" {
|
||||||
section = strings.ToLower(section);
|
section = "default"
|
||||||
|
}
|
||||||
|
section = strings.ToLower(section)
|
||||||
|
|
||||||
if _, ok := c.data[section]; !ok {
|
if _, ok := c.data[section]; !ok {
|
||||||
return nil, GetError{SectionNotFound, "", "", section, ""}
|
return nil, GetError{SectionNotFound, "", "", section, ""}
|
||||||
}
|
}
|
||||||
|
|
||||||
options = make([]string, len(c.data[DefaultSection])+len(c.data[section]));
|
options = make([]string, len(c.data[DefaultSection])+len(c.data[section]))
|
||||||
i := 0;
|
i := 0
|
||||||
for s, _ := range c.data[DefaultSection] {
|
for s, _ := range c.data[DefaultSection] {
|
||||||
options[i] = s;
|
options[i] = s
|
||||||
i++;
|
i++
|
||||||
}
|
}
|
||||||
for s, _ := range c.data[section] {
|
for s, _ := range c.data[section] {
|
||||||
options[i] = s;
|
options[i] = s
|
||||||
i++;
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
return options, nil;
|
return options, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// HasOption checks if the configuration has the given option in the section.
|
// HasOption checks if the configuration has the given option in the section.
|
||||||
// It returns false if either the option or section do not exist.
|
// It returns false if either the option or section do not exist.
|
||||||
func (c *ConfigFile) HasOption(section string, option string) bool {
|
func (c *ConfigFile) HasOption(section string, option string) bool {
|
||||||
if section == "" {section = "default"}
|
if section == "" {
|
||||||
section = strings.ToLower(section);
|
section = "default"
|
||||||
option = strings.ToLower(option);
|
}
|
||||||
|
section = strings.ToLower(section)
|
||||||
|
option = strings.ToLower(option)
|
||||||
|
|
||||||
if _, ok := c.data[section]; !ok {
|
if _, ok := c.data[section]; !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
_, okd := c.data[DefaultSection][option];
|
_, okd := c.data[DefaultSection][option]
|
||||||
_, oknd := c.data[section][option];
|
_, oknd := c.data[section][option]
|
||||||
|
|
||||||
return okd || oknd;
|
return okd || oknd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,18 +84,20 @@ func (c *ConfigFile) HasOption(section string, option string) bool {
|
||||||
// The raw string value is not subjected to unfolding, which was illustrated in the beginning of this documentation.
|
// The raw string value is not subjected to unfolding, which was illustrated in the beginning of this documentation.
|
||||||
// It returns an error if either the section or the option do not exist.
|
// It returns an error if either the section or the option do not exist.
|
||||||
func (c *ConfigFile) GetRawString(section string, option string) (value string, err os.Error) {
|
func (c *ConfigFile) GetRawString(section string, option string) (value string, err os.Error) {
|
||||||
if section == "" {section = "default"}
|
if section == "" {
|
||||||
|
section = "default"
|
||||||
section = strings.ToLower(section);
|
}
|
||||||
option = strings.ToLower(option);
|
|
||||||
|
section = strings.ToLower(section)
|
||||||
|
option = strings.ToLower(option)
|
||||||
|
|
||||||
if _, ok := c.data[section]; ok {
|
if _, ok := c.data[section]; ok {
|
||||||
if value, ok = c.data[section][option]; ok {
|
if value, ok = c.data[section][option]; ok {
|
||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
return "", GetError{OptionNotFound, "", "", section, option};
|
return "", GetError{OptionNotFound, "", "", section, option}
|
||||||
}
|
}
|
||||||
return "", GetError{SectionNotFound, "", "", section, option};
|
return "", GetError{SectionNotFound, "", "", section, option}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,25 +106,25 @@ func (c *ConfigFile) GetRawString(section string, option string) (value string,
|
||||||
// then GetString does this unfolding automatically, up to DepthValues number of iterations.
|
// then GetString does this unfolding automatically, up to DepthValues number of iterations.
|
||||||
// It returns an error if either the section or the option do not exist, or the unfolding cycled.
|
// It returns an error if either the section or the option do not exist, or the unfolding cycled.
|
||||||
func (c *ConfigFile) GetString(section string, option string) (value string, err os.Error) {
|
func (c *ConfigFile) GetString(section string, option string) (value string, err os.Error) {
|
||||||
value, err = c.GetRawString(section, option);
|
value, err = c.GetRawString(section, option)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
section = strings.ToLower(section);
|
section = strings.ToLower(section)
|
||||||
|
|
||||||
var i int;
|
var i int
|
||||||
|
|
||||||
for i = 0; i < DepthValues; i++ { // keep a sane depth
|
for i = 0; i < DepthValues; i++ { // keep a sane depth
|
||||||
vr := varRegExp.ExecuteString(value);
|
vr := varRegExp.ExecuteString(value)
|
||||||
if len(vr) == 0 {
|
if len(vr) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
noption := value[vr[2]:vr[3]];
|
noption := value[vr[2]:vr[3]]
|
||||||
noption = strings.ToLower(noption);
|
noption = strings.ToLower(noption)
|
||||||
|
|
||||||
nvalue, _ := c.data[DefaultSection][noption]; // search variable in default section
|
nvalue, _ := c.data[DefaultSection][noption] // search variable in default section
|
||||||
if _, ok := c.data[section][noption]; ok {
|
if _, ok := c.data[section][noption]; ok {
|
||||||
nvalue = c.data[section][noption]
|
nvalue = c.data[section][noption]
|
||||||
}
|
}
|
||||||
|
@ -125,20 +133,20 @@ func (c *ConfigFile) GetString(section string, option string) (value string, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// substitute by new value and take off leading '%(' and trailing ')s'
|
// substitute by new value and take off leading '%(' and trailing ')s'
|
||||||
value = value[0:vr[2]-2] + nvalue + value[vr[3]+2:];
|
value = value[0:vr[2]-2] + nvalue + value[vr[3]+2:]
|
||||||
}
|
}
|
||||||
|
|
||||||
if i == DepthValues {
|
if i == DepthValues {
|
||||||
return "", GetError{MaxDepthReached, "", "", section, option}
|
return "", GetError{MaxDepthReached, "", "", section, option}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value, nil;
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// GetInt has the same behaviour as GetString but converts the response to int.
|
// GetInt has the same behaviour as GetString but converts the response to int.
|
||||||
func (c *ConfigFile) GetInt(section string, option string) (value int, err os.Error) {
|
func (c *ConfigFile) GetInt(section string, option string) (value int, err os.Error) {
|
||||||
sv, err := c.GetString(section, option);
|
sv, err := c.GetString(section, option)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
value, err = strconv.Atoi(sv)
|
value, err = strconv.Atoi(sv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -146,13 +154,13 @@ func (c *ConfigFile) GetInt(section string, option string) (value int, err os.Er
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value, err;
|
return value, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// GetFloat has the same behaviour as GetString but converts the response to float.
|
// GetFloat has the same behaviour as GetString but converts the response to float.
|
||||||
func (c *ConfigFile) GetFloat(section string, option string) (value float, err os.Error) {
|
func (c *ConfigFile) GetFloat(section string, option string) (value float, err os.Error) {
|
||||||
sv, err := c.GetString(section, option);
|
sv, err := c.GetString(section, option)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
value, err = strconv.Atof(sv)
|
value, err = strconv.Atof(sv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -160,22 +168,22 @@ func (c *ConfigFile) GetFloat(section string, option string) (value float, err o
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value, err;
|
return value, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// GetBool has the same behaviour as GetString but converts the response to bool.
|
// GetBool has the same behaviour as GetString but converts the response to bool.
|
||||||
// See constant BoolStrings for string values converted to bool.
|
// See constant BoolStrings for string values converted to bool.
|
||||||
func (c *ConfigFile) GetBool(section string, option string) (value bool, err os.Error) {
|
func (c *ConfigFile) GetBool(section string, option string) (value bool, err os.Error) {
|
||||||
sv, err := c.GetString(section, option);
|
sv, err := c.GetString(section, option)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
value, ok := BoolStrings[strings.ToLower(sv)];
|
value, ok := BoolStrings[strings.ToLower(sv)]
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, GetError{CouldNotParse, "bool", sv, section, option}
|
return false, GetError{CouldNotParse, "bool", sv, section, option}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value, nil;
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
64
read.go
64
read.go
|
@ -11,13 +11,13 @@ import (
|
||||||
// ReadConfigFile reads a file and returns a new configuration representation.
|
// ReadConfigFile reads a file and returns a new configuration representation.
|
||||||
// This representation can be queried with GetString, etc.
|
// This representation can be queried with GetString, etc.
|
||||||
func ReadConfigFile(fname string) (c *ConfigFile, err os.Error) {
|
func ReadConfigFile(fname string) (c *ConfigFile, err os.Error) {
|
||||||
var file *os.File;
|
var file *os.File
|
||||||
|
|
||||||
if file, err = os.Open(fname, os.O_RDONLY, 0); err != nil {
|
if file, err = os.Open(fname, os.O_RDONLY, 0); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c = NewConfigFile();
|
c = NewConfigFile()
|
||||||
if err = c.Read(file); err != nil {
|
if err = c.Read(file); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -31,12 +31,12 @@ func ReadConfigFile(fname string) (c *ConfigFile, err os.Error) {
|
||||||
|
|
||||||
func ReadConfigBytes(conf []byte) (c *ConfigFile, err os.Error) {
|
func ReadConfigBytes(conf []byte) (c *ConfigFile, err os.Error) {
|
||||||
buf := bytes.NewBuffer(conf)
|
buf := bytes.NewBuffer(conf)
|
||||||
|
|
||||||
c = NewConfigFile();
|
c = NewConfigFile()
|
||||||
if err = c.Read(buf); err != nil {
|
if err = c.Read(buf); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,61 +44,61 @@ func ReadConfigBytes(conf []byte) (c *ConfigFile, err os.Error) {
|
||||||
// representation can be queried with GetString, etc.
|
// representation can be queried with GetString, etc.
|
||||||
func (c *ConfigFile) Read(reader io.Reader) (err os.Error) {
|
func (c *ConfigFile) Read(reader io.Reader) (err os.Error) {
|
||||||
buf := bufio.NewReader(reader)
|
buf := bufio.NewReader(reader)
|
||||||
|
|
||||||
var section, option string;
|
var section, option string
|
||||||
section = "default"
|
section = "default"
|
||||||
for {
|
for {
|
||||||
l, buferr := buf.ReadString('\n'); // parse line-by-line
|
l, buferr := buf.ReadString('\n') // parse line-by-line
|
||||||
if buferr != nil && buferr != os.EOF {
|
if buferr != nil && buferr != os.EOF {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
l = strings.TrimSpace(l);
|
l = strings.TrimSpace(l)
|
||||||
// switch written for readability (not performance)
|
// switch written for readability (not performance)
|
||||||
switch {
|
switch {
|
||||||
case len(l) == 0: // empty line
|
case len(l) == 0: // empty line
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case l[0] == '#': // comment
|
case l[0] == '#': // comment
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case l[0] == ';': // comment
|
case l[0] == ';': // comment
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case len(l) >= 3 && strings.ToLower(l[0:3]) == "rem": // comment (for windows users)
|
case len(l) >= 3 && strings.ToLower(l[0:3]) == "rem": // comment (for windows users)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case l[0] == '[' && l[len(l)-1] == ']': // new section
|
case l[0] == '[' && l[len(l)-1] == ']': // new section
|
||||||
option = ""; // reset multi-line value
|
option = "" // reset multi-line value
|
||||||
section = strings.TrimSpace(l[1 : len(l)-1]);
|
section = strings.TrimSpace(l[1 : len(l)-1])
|
||||||
c.AddSection(section);
|
c.AddSection(section)
|
||||||
|
|
||||||
case section == "": // not new section and no section defined so far
|
case section == "": // not new section and no section defined so far
|
||||||
return ReadError{BlankSection, l}
|
return ReadError{BlankSection, l}
|
||||||
|
|
||||||
default: // other alternatives
|
default: // other alternatives
|
||||||
i := firstIndex(l, []byte{'=', ':'});
|
i := firstIndex(l, []byte{'=', ':'})
|
||||||
switch {
|
switch {
|
||||||
case i > 0: // option and value
|
case i > 0: // option and value
|
||||||
i := firstIndex(l, []byte{'=', ':'});
|
i := firstIndex(l, []byte{'=', ':'})
|
||||||
option = strings.TrimSpace(l[0:i]);
|
option = strings.TrimSpace(l[0:i])
|
||||||
value := strings.TrimSpace(stripComments(l[i+1:]));
|
value := strings.TrimSpace(stripComments(l[i+1:]))
|
||||||
c.AddOption(section, option, value);
|
c.AddOption(section, option, value)
|
||||||
|
|
||||||
case section != "" && option != "": // continuation of multi-line value
|
case section != "" && option != "": // continuation of multi-line value
|
||||||
prev, _ := c.GetRawString(section, option);
|
prev, _ := c.GetRawString(section, option)
|
||||||
value := strings.TrimSpace(stripComments(l));
|
value := strings.TrimSpace(stripComments(l))
|
||||||
c.AddOption(section, option, prev+"\n"+value);
|
c.AddOption(section, option, prev+"\n"+value)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return ReadError{CouldNotParse, l}
|
return ReadError{CouldNotParse, l}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reached end of file
|
// Reached end of file
|
||||||
if buferr == os.EOF {
|
if buferr == os.EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
16
write.go
16
write.go
|
@ -10,7 +10,7 @@ import (
|
||||||
// The desired file permissions must be passed as in os.Open.
|
// The desired file permissions must be passed as in os.Open.
|
||||||
// The header is a string that is saved as a comment in the first line of the file.
|
// The header is a string that is saved as a comment in the first line of the file.
|
||||||
func (c *ConfigFile) WriteConfigFile(fname string, perm int, header string) (err os.Error) {
|
func (c *ConfigFile) WriteConfigFile(fname string, perm int, header string) (err os.Error) {
|
||||||
var file *os.File;
|
var file *os.File
|
||||||
|
|
||||||
if file, err = os.Open(fname, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, perm); err != nil {
|
if file, err = os.Open(fname, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, perm); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -19,22 +19,22 @@ func (c *ConfigFile) WriteConfigFile(fname string, perm int, header string) (err
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return file.Close();
|
return file.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteConfigBytes returns the configuration file.
|
// WriteConfigBytes returns the configuration file.
|
||||||
func (c *ConfigFile) WriteConfigBytes(header string) (config []byte) {
|
func (c *ConfigFile) WriteConfigBytes(header string) (config []byte) {
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
|
|
||||||
c.Write(buf, header)
|
c.Write(buf, header)
|
||||||
|
|
||||||
return buf.Bytes()
|
return buf.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes the configuration file to the io.Writer.
|
// Writes the configuration file to the io.Writer.
|
||||||
func (c *ConfigFile) Write(writer io.Writer, header string) (err os.Error) {
|
func (c *ConfigFile) Write(writer io.Writer, header string) (err os.Error) {
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
|
|
||||||
if header != "" {
|
if header != "" {
|
||||||
if _, err = buf.WriteString("# " + header + "\n"); err != nil {
|
if _, err = buf.WriteString("# " + header + "\n"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -43,7 +43,7 @@ func (c *ConfigFile) Write(writer io.Writer, header string) (err os.Error) {
|
||||||
|
|
||||||
for section, sectionmap := range c.data {
|
for section, sectionmap := range c.data {
|
||||||
if section == DefaultSection && len(sectionmap) == 0 {
|
if section == DefaultSection && len(sectionmap) == 0 {
|
||||||
continue // skip default section if empty
|
continue // skip default section if empty
|
||||||
}
|
}
|
||||||
if _, err = buf.WriteString("[" + section + "]\n"); err != nil {
|
if _, err = buf.WriteString("[" + section + "]\n"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -57,8 +57,8 @@ func (c *ConfigFile) Write(writer io.Writer, header string) (err os.Error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.WriteTo(writer)
|
buf.WriteTo(writer)
|
||||||
|
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue