github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/encoding/ini/ini.go (about) 1 // Copyright 2012 <chaishushan{AT}gmail.com>. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package ini implements a simple INI file parser. 6 package ini 7 8 import ( 9 "bufio" 10 "bytes" 11 "errors" 12 "fmt" 13 "os" 14 "regexp" 15 "strings" 16 "unicode" 17 ) 18 19 var ( 20 regDoubleQuote = regexp.MustCompile("^([^= \t]+)[ \t]*=[ \t]*\"([^\"]*)\"$") 21 regSingleQuote = regexp.MustCompile("^([^= \t]+)[ \t]*=[ \t]*'([^']*)'$") 22 regNoQuote = regexp.MustCompile("^([^= \t]+)[ \t]*=[ \t]*([^#;]+)") 23 regNoValue = regexp.MustCompile("^([^= \t]+)[ \t]*=[ \t]*([#;].*)?") 24 ) 25 26 func LoadFile(filename string) (dict Dict, err error) { 27 file, err := os.Open(filename) 28 if err != nil { 29 return nil, err 30 } 31 defer file.Close() 32 33 reader := bufio.NewReader(file) 34 return load(reader, filename) 35 } 36 func LoadString(str string) (dict Dict, err error) { 37 reader := bufio.NewReader(bytes.NewReader([]byte(str))) 38 return load(reader, "[string]") 39 } 40 41 func load(reader *bufio.Reader, filename string) (dict Dict, err error) { 42 43 dict = newDict() 44 lineno := 0 45 section := "" 46 47 for err == nil { 48 l, _, err := reader.ReadLine() 49 if err != nil { 50 break 51 } 52 lineno++ 53 if len(l) == 0 { 54 continue 55 } 56 line := strings.TrimFunc(string(l), unicode.IsSpace) 57 58 for line[len(line)-1] == '\\' { 59 line = line[:len(line)-1] 60 l, _, err := reader.ReadLine() 61 if err != nil { 62 return nil, err 63 } 64 line += strings.TrimFunc(string(l), unicode.IsSpace) 65 } 66 67 section, err = parseLine(&dict, section, line) 68 if err != nil { 69 return nil, errors.New( 70 fmt.Sprintf("%v: '%s:%d'.", err, filename, lineno), 71 ) 72 } 73 } 74 75 return 76 } 77 78 func parseLine(dict *Dict, section, line string) (string, error) { 79 // commets 80 if line[0] == '#' || line[0] == ';' { 81 return section, nil 82 } 83 84 // section name 85 if line[0] == '[' && line[len(line)-1] == ']' { 86 section = strings.TrimFunc(line[1:len(line)-1], unicode.IsSpace) 87 dict.setSection(section) 88 return section, nil 89 } 90 91 // key = value 92 if section != "" { 93 if m := regDoubleQuote.FindAllStringSubmatch(line, 1); m != nil { 94 dict.setString(section, m[0][1], m[0][2]) 95 return section, nil 96 } else if m = regSingleQuote.FindAllStringSubmatch(line, 1); m != nil { 97 dict.setString(section, m[0][1], m[0][2]) 98 return section, nil 99 } else if m = regNoQuote.FindAllStringSubmatch(line, 1); m != nil { 100 dict.setString(section, m[0][1], strings.TrimFunc(m[0][2], unicode.IsSpace)) 101 return section, nil 102 } else if m = regNoValue.FindAllStringSubmatch(line, 1); m != nil { 103 dict.setString(section, m[0][1], "") 104 return section, nil 105 } 106 } 107 108 return section, errors.New("syntax error") 109 }