golang实现ConfigParser, 解析ini

Usage:

  • Init(rc_file1, rc_file2...) 后面的会覆盖前面的
  • Get(section)

在配置文件中可以使用COMMENT_FLAG 默认 #来写注解.

package config

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"strings"
)

var CONFIG map[string]map[string]string = make(map[string]map[string]string)

const COMMENT_FLAG = "#"

var RE_SESSION *regexp.Regexp = regexp.MustCompile("^\\[.+\\]$")
var RE_KV *regexp.Regexp = regexp.MustCompile("^.+\\=.+$")

func exists(file string) bool {
	if f, err := os.Open(file); err != nil && os.IsNotExist(err) {
		defer f.Close()
		return false

	}
	return true
}

func parse_line(line string) (string, interface{}) {
	comment_index := strings.Index(line, COMMENT_FLAG)
	if comment_index != -1 {
		line = line[0:comment_index]
	}
	if RE_SESSION.MatchString(line) {
		return "section", line[1 : len(line)-1]
	}

	if RE_KV.MatchString(line) {
		parts := strings.SplitN(line, "=", 2)
		return "kv", map[string]string{strings.TrimSpace(parts[0]): strings.TrimSpace(parts[1])}
	}

	fmt.Fprintf(os.Stderr, "%s format error!\n", line)
	return "other", nil
}

func Get(section string) (map[string]string, error) {
	config, ok := CONFIG[section]
	if ok {
		return config, nil
	}
	return nil, fmt.Errorf("section %s not found", section)
}

func Sections() (sections []string) {
	for section, _ := range CONFIG {
		sections = append(sections, section)
	}
	return sections
}

func parse_rc_content(content string) map[string]map[string]string {
	config := make(map[string]map[string]string)
	lines := strings.FieldsFunc(content, func(char rune) bool {
		return strings.ContainsRune("\r\n", char)
	})

	last_section := ""

	for _, line := range lines {
		line = strings.TrimSpace(line)
		if line == "" {
			continue
		}
		line_type, line_value := parse_line(line)
		switch {
		case line_type == "section":
			section := line_value.(string)
			if _, ok := config[section]; ok == false {
				config[section] = make(map[string]string)
			}
			last_section = section

		case line_type == "kv" && last_section != "":
			kv := line_value.(map[string]string)
			for k, v := range kv {
				config[last_section][k] = v
			}
		}
	}

	return config
}

func Init(rc_files ...string) {
	for _, rc_file := range rc_files {
		if !exists(rc_file) {
			continue
		}
		content_bytes, err := ioutil.ReadFile(rc_file)
		if err != nil {
			log.Fatalln(err)
		}
		content := string(content_bytes)
		for section, configs := range parse_rc_content(content) {
			_, ok := CONFIG[section]
			if ok == false {
				CONFIG[section] = make(map[string]string)
			}
			for name, value := range configs {
				CONFIG[section][name] = value
			}
		}
	}
}

转载于:https://my.oschina.net/tuxpy/blog/768438

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值