瀏覽代碼

bump(github.com/ccding/go-config-reader): 8b6c2b50197f20da3b1c5944c274c173634dc056

Brandon Philips 12 年之前
父節點
當前提交
2662b3c559

+ 120 - 20
third_party/github.com/ccding/go-config-reader/config/config.go

@@ -13,23 +13,60 @@
 // limitations under the License.
 //
 // author: Cong Ding <dinggnu@gmail.com>
-//
+
 package config
 
 import (
 	"bufio"
 	"errors"
+	"fmt"
+	"io/ioutil"
 	"os"
 	"strings"
 )
 
 var commentPrefix = []string{"//", "#", ";"}
 
-func Read(filename string) (map[string]string, error) {
-	var res = map[string]string{}
-	in, err := os.Open(filename)
+// Config struct constructs a new configuration handler.
+type Config struct {
+	filename string
+	config   map[string]map[string]string
+}
+
+// NewConfig function cnstructs a new Config struct with filename. You have to
+// call Read() function to let it read from the file. Otherwise you will get
+// empty string (i.e., "") when you are calling Get() function. Another usage
+// is that you call NewConfig() function and then call Add()/Set() function to
+// add new key-values to the configuration. Finally you can call Write()
+// function to write the new configuration to the file.
+func NewConfig(filename string) *Config {
+	c := new(Config)
+	c.filename = filename
+	c.config = make(map[string]map[string]string)
+	return c
+}
+
+// Filename function returns the filename of the configuration.
+func (c *Config) Filename() string {
+	return c.filename
+}
+
+// SetFilename function sets the filename of the configuration.
+func (c *Config) SetFilename(filename string) {
+	c.filename = filename
+}
+
+// Reset function reset the map in the configuration.
+func (c *Config) Reset() {
+	c.config = make(map[string]map[string]string)
+}
+
+// Read function reads configurations from the file defined in
+// Config.filename.
+func (c *Config) Read() error {
+	in, err := os.Open(c.filename)
 	if err != nil {
-		return res, err
+		return err
 	}
 	defer in.Close()
 	scanner := bufio.NewScanner(in)
@@ -40,9 +77,9 @@ func Read(filename string) (map[string]string, error) {
 			continue
 		}
 		if line == "" {
-			sec := checkSection(scanner.Text())
-			if sec != "" {
-				section = sec + "."
+			sec, ok := checkSection(scanner.Text())
+			if ok {
+				section = sec
 				continue
 			}
 		}
@@ -54,40 +91,103 @@ func Read(filename string) (map[string]string, error) {
 			line = line[:len(line)-1]
 			continue
 		}
-		key, value, err := checkLine(line)
-		if err != nil {
-			return res, errors.New("WRONG: " + line)
+		key, value, ok := checkLine(line)
+		if !ok {
+			return errors.New("WRONG: " + line)
 		}
-		res[section+key] = value
+		c.Set(section, key, value)
 		line = ""
 	}
-	return res, nil
+	return nil
+}
+
+// Get function returns the value of a key in the configuration. If the key
+// does not exist, it returns empty string (i.e., "").
+func (c *Config) Get(section string, key string) string {
+	value, ok := c.config[section][key]
+	if !ok {
+		return ""
+	}
+	return value
 }
 
-func checkSection(line string) string {
+// Set function updates the value of a key in the configuration. Function
+// Set() is exactly the same as function Add().
+func (c *Config) Set(section string, key string, value string) {
+	_, ok := c.config[section]
+	if !ok {
+		c.config[section] = make(map[string]string)
+	}
+	c.config[section][key] = value
+}
+
+// Add function adds a new key to the configuration. Function Add() is exactly
+// the same as function Set().
+func (c *Config) Add(section string, key string, value string) {
+	c.Set(section, key, value)
+}
+
+// Del function deletes a key from the configuration.
+func (c *Config) Del(section string, key string) {
+	_, ok := c.config[section]
+	if ok {
+		delete(c.config[section], key)
+		if len(c.config[section]) == 0 {
+			delete(c.config, section)
+		}
+	}
+}
+
+// Write function writes the updated configuration back.
+func (c *Config) Write() error {
+	return nil
+}
+
+// WriteTo function writes the configuration to a new file. This function
+// re-organizes the configuration and deletes all the comments.
+func (c *Config) WriteTo(filename string) error {
+	content := ""
+	for k, v := range c.config {
+		format := "%v = %v\n"
+		if k != "" {
+			content += fmt.Sprintf("[%v]\n", k)
+			format = "\t" + format
+		}
+		for key, value := range v {
+			content += fmt.Sprintf(format, key, value)
+		}
+	}
+	return ioutil.WriteFile(filename, []byte(content), 0644)
+}
+
+// To check this line is a section or not. If it is not a section, it returns
+// "".
+func checkSection(line string) (string, bool) {
 	line = strings.TrimSpace(line)
 	lineLen := len(line)
 	if lineLen < 2 {
-		return ""
+		return "", false
 	}
 	if line[0] == '[' && line[lineLen-1] == ']' {
-		return line[1 : lineLen-1]
+		return line[1 : lineLen-1], true
 	}
-	return ""
+	return "", false
 }
 
-func checkLine(line string) (string, string, error) {
+// To check this line is a valid key-value pair or not.
+func checkLine(line string) (string, string, bool) {
 	key := ""
 	value := ""
 	sp := strings.SplitN(line, "=", 2)
 	if len(sp) != 2 {
-		return key, value, errors.New("WRONG: " + line)
+		return key, value, false
 	}
 	key = strings.TrimSpace(sp[0])
 	value = strings.TrimSpace(sp[1])
-	return key, value, nil
+	return key, value, true
 }
 
+// To check this line is a whole line comment or not.
 func checkComment(line string) bool {
 	line = strings.TrimSpace(line)
 	for p := range commentPrefix {

+ 7 - 5
third_party/github.com/ccding/go-config-reader/example.go

@@ -13,7 +13,7 @@
 // limitations under the License.
 //
 // author: Cong Ding <dinggnu@gmail.com>
-//
+
 package main
 
 import (
@@ -22,9 +22,11 @@ import (
 )
 
 func main() {
-	res, err := config.Read("example.conf")
+	c := config.NewConfig("example.conf")
+	err := c.Read()
 	fmt.Println(err)
-	fmt.Println(res)
-	fmt.Println(res["test.a"])
-	fmt.Println(res["dd"])
+	fmt.Println(c)
+	fmt.Println(c.Get("test", "a"))
+	fmt.Println(c.Get("", "dd"))
+	c.WriteTo("example2.conf")
 }