mirror of
https://github.com/astaxie/beego.git
synced 2024-11-22 15:00:54 +00:00
support section
if iniconf.String("demo.key1") != "asta" { + t.Fatal("get demo.key1 error") + } + if iniconf.String("demo.key2") != "xie" { + t.Fatal("get demo.key2 error") + }
This commit is contained in:
parent
ba5e393e99
commit
63b82c438d
108
config/ini.go
108
config/ini.go
@ -13,10 +13,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
DEFAULT_SECTION = "DEFAULT"
|
||||||
bComment = []byte{'#'}
|
bComment = []byte{'#'}
|
||||||
|
alterComment = []byte{';'}
|
||||||
bEmpty = []byte{}
|
bEmpty = []byte{}
|
||||||
bEqual = []byte{'='}
|
bEqual = []byte{'='}
|
||||||
bDQuote = []byte{'"'}
|
bDQuote = []byte{'"'}
|
||||||
|
sectionStart = []byte{'['}
|
||||||
|
sectionEnd = []byte{']'}
|
||||||
)
|
)
|
||||||
|
|
||||||
type IniConfig struct {
|
type IniConfig struct {
|
||||||
@ -32,9 +36,9 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) {
|
|||||||
|
|
||||||
cfg := &IniConfigContainer{
|
cfg := &IniConfigContainer{
|
||||||
file.Name(),
|
file.Name(),
|
||||||
make(map[int][]string),
|
make(map[string]map[string]string),
|
||||||
|
make(map[string]string),
|
||||||
make(map[string]string),
|
make(map[string]string),
|
||||||
make(map[string]int64),
|
|
||||||
sync.RWMutex{},
|
sync.RWMutex{},
|
||||||
}
|
}
|
||||||
cfg.Lock()
|
cfg.Lock()
|
||||||
@ -43,8 +47,8 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) {
|
|||||||
|
|
||||||
var comment bytes.Buffer
|
var comment bytes.Buffer
|
||||||
buf := bufio.NewReader(file)
|
buf := bufio.NewReader(file)
|
||||||
|
section := DEFAULT_SECTION
|
||||||
for nComment, off := 0, int64(1); ; {
|
for {
|
||||||
line, _, err := buf.ReadLine()
|
line, _, err := buf.ReadLine()
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
@ -52,8 +56,7 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) {
|
|||||||
if bytes.Equal(line, bEmpty) {
|
if bytes.Equal(line, bEmpty) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
line = bytes.TrimSpace(line)
|
||||||
off += int64(len(line))
|
|
||||||
|
|
||||||
if bytes.HasPrefix(line, bComment) {
|
if bytes.HasPrefix(line, bComment) {
|
||||||
line = bytes.TrimLeft(line, "#")
|
line = bytes.TrimLeft(line, "#")
|
||||||
@ -62,21 +65,40 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) {
|
|||||||
comment.WriteByte('\n')
|
comment.WriteByte('\n')
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if comment.Len() != 0 {
|
if bytes.HasPrefix(line, alterComment) {
|
||||||
cfg.comment[nComment] = []string{comment.String()}
|
line = bytes.TrimLeft(line, ";")
|
||||||
|
line = bytes.TrimLeftFunc(line, unicode.IsSpace)
|
||||||
|
comment.Write(line)
|
||||||
|
comment.WriteByte('\n')
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if bytes.HasPrefix(line, sectionStart) && bytes.HasSuffix(line, sectionEnd) {
|
||||||
|
section = string(line[1 : len(line)-1])
|
||||||
|
if comment.Len() > 0 {
|
||||||
|
cfg.sectionComment[section] = comment.String()
|
||||||
comment.Reset()
|
comment.Reset()
|
||||||
nComment++
|
}
|
||||||
|
if _, ok := cfg.data[section]; !ok {
|
||||||
|
cfg.data[section] = make(map[string]string)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if _, ok := cfg.data[section]; !ok {
|
||||||
|
cfg.data[section] = make(map[string]string)
|
||||||
|
}
|
||||||
|
keyval := bytes.SplitN(line, bEqual, 2)
|
||||||
|
val := bytes.TrimSpace(keyval[1])
|
||||||
|
if bytes.HasPrefix(val, bDQuote) {
|
||||||
|
val = bytes.Trim(val, `"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
val := bytes.SplitN(line, bEqual, 2)
|
key := string(bytes.TrimSpace(keyval[0]))
|
||||||
if bytes.HasPrefix([]byte(strings.TrimSpace(string(val[1]))), bDQuote) {
|
cfg.data[section][key] = string(val)
|
||||||
val[1] = bytes.Trim([]byte(strings.TrimSpace(string(val[1]))), `"`)
|
if comment.Len() > 0 {
|
||||||
|
cfg.keycomment[section+"."+key] = comment.String()
|
||||||
|
comment.Reset()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
key := strings.TrimSpace(string(val[0]))
|
|
||||||
cfg.comment[nComment-1] = append(cfg.comment[nComment-1], key)
|
|
||||||
cfg.data[key] = strings.TrimSpace(string(val[1]))
|
|
||||||
cfg.offset[key] = off
|
|
||||||
}
|
}
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
@ -84,41 +106,53 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) {
|
|||||||
// A Config represents the configuration.
|
// A Config represents the configuration.
|
||||||
type IniConfigContainer struct {
|
type IniConfigContainer struct {
|
||||||
filename string
|
filename string
|
||||||
comment map[int][]string // id: []{comment, key...}; id 1 is for main comment.
|
data map[string]map[string]string //section=> key:val
|
||||||
data map[string]string // key: value
|
sectionComment map[string]string //sction : comment
|
||||||
offset map[string]int64 // key: offset; for editing.
|
keycomment map[string]string // id: []{comment, key...}; id 1 is for main comment.
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bool returns the boolean value for a given key.
|
// Bool returns the boolean value for a given key.
|
||||||
func (c *IniConfigContainer) Bool(key string) (bool, error) {
|
func (c *IniConfigContainer) Bool(key string) (bool, error) {
|
||||||
return strconv.ParseBool(c.data[key])
|
return strconv.ParseBool(c.getdata(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int returns the integer value for a given key.
|
// Int returns the integer value for a given key.
|
||||||
func (c *IniConfigContainer) Int(key string) (int, error) {
|
func (c *IniConfigContainer) Int(key string) (int, error) {
|
||||||
return strconv.Atoi(c.data[key])
|
return strconv.Atoi(c.getdata(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *IniConfigContainer) Int64(key string) (int64, error) {
|
func (c *IniConfigContainer) Int64(key string) (int64, error) {
|
||||||
return strconv.ParseInt(c.data[key], 10, 64)
|
return strconv.ParseInt(c.getdata(key), 10, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float returns the float value for a given key.
|
// Float returns the float value for a given key.
|
||||||
func (c *IniConfigContainer) Float(key string) (float64, error) {
|
func (c *IniConfigContainer) Float(key string) (float64, error) {
|
||||||
return strconv.ParseFloat(c.data[key], 64)
|
return strconv.ParseFloat(c.getdata(key), 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the string value for a given key.
|
// String returns the string value for a given key.
|
||||||
func (c *IniConfigContainer) String(key string) string {
|
func (c *IniConfigContainer) String(key string) string {
|
||||||
return c.data[key]
|
return c.getdata(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteValue writes a new value for key.
|
// WriteValue writes a new value for key.
|
||||||
func (c *IniConfigContainer) Set(key, value string) error {
|
func (c *IniConfigContainer) Set(key, value string) error {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
c.data[key] = value
|
if len(key) == 0 {
|
||||||
|
return errors.New("key is empty")
|
||||||
|
}
|
||||||
|
var section, k string
|
||||||
|
sectionkey := strings.Split(key, ".")
|
||||||
|
if len(sectionkey) >= 2 {
|
||||||
|
section = sectionkey[0]
|
||||||
|
k = sectionkey[1]
|
||||||
|
} else {
|
||||||
|
section = DEFAULT_SECTION
|
||||||
|
k = sectionkey[0]
|
||||||
|
}
|
||||||
|
c.data[section][k] = value
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,6 +163,30 @@ func (c *IniConfigContainer) DIY(key string) (v interface{}, err error) {
|
|||||||
return v, errors.New("key not find")
|
return v, errors.New("key not find")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//section.key or key
|
||||||
|
func (c *IniConfigContainer) getdata(key string) string {
|
||||||
|
c.RLock()
|
||||||
|
defer c.RUnlock()
|
||||||
|
if len(key) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
var section, k string
|
||||||
|
sectionkey := strings.Split(key, ".")
|
||||||
|
if len(sectionkey) >= 2 {
|
||||||
|
section = sectionkey[0]
|
||||||
|
k = sectionkey[1]
|
||||||
|
} else {
|
||||||
|
section = DEFAULT_SECTION
|
||||||
|
k = sectionkey[0]
|
||||||
|
}
|
||||||
|
if v, ok := c.data[section]; ok {
|
||||||
|
if vv, o := v[k]; o {
|
||||||
|
return vv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Register("ini", &IniConfig{})
|
Register("ini", &IniConfig{})
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var inicontext = `
|
var inicontext = `
|
||||||
|
;comment one
|
||||||
|
#comment two
|
||||||
appname = beeapi
|
appname = beeapi
|
||||||
httpport = 8080
|
httpport = 8080
|
||||||
mysqlport = 3600
|
mysqlport = 3600
|
||||||
@ -13,6 +15,9 @@ PI = 3.1415976
|
|||||||
runmode = "dev"
|
runmode = "dev"
|
||||||
autorender = false
|
autorender = false
|
||||||
copyrequestbody = true
|
copyrequestbody = true
|
||||||
|
[demo]
|
||||||
|
key1="asta"
|
||||||
|
key2 = "xie"
|
||||||
`
|
`
|
||||||
|
|
||||||
func TestIni(t *testing.T) {
|
func TestIni(t *testing.T) {
|
||||||
@ -63,4 +68,10 @@ func TestIni(t *testing.T) {
|
|||||||
if iniconf.String("name") != "astaxie" {
|
if iniconf.String("name") != "astaxie" {
|
||||||
t.Fatal("get name error")
|
t.Fatal("get name error")
|
||||||
}
|
}
|
||||||
|
if iniconf.String("demo.key1") != "asta" {
|
||||||
|
t.Fatal("get demo.key1 error")
|
||||||
|
}
|
||||||
|
if iniconf.String("demo.key2") != "xie" {
|
||||||
|
t.Fatal("get demo.key2 error")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user