2 recfile -- GNU recutils'es recfiles parser on pure Go
3 Copyright (C) 2020 Sergey Matveev <stargrave@stargrave.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, version 3 of the License.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 // GNU recutils'es recfiles parser on pure Go
29 var KeyValRe = regexp.MustCompile(`([a-zA-Z%][a-zA-Z0-9_]*):\s*(.*)$`)
32 scanner *bufio.Scanner
35 // Create Reader for iterating through the records. It uses
36 // bufio.Scanner, so can read more than currently parsed records take.
37 func NewReader(r io.Reader) *Reader {
38 return &Reader{bufio.NewScanner(r)}
41 // Get next record. Each record is just a collection of fields. io.EOF
42 // is returned if there is nothing to read more.
43 func (r *Reader) Next() ([]Field, error) {
44 fields := make([]Field, 0, 1)
48 lines := make([]string, 0)
52 if !r.scanner.Scan() {
53 if err := r.scanner.Err(); err != nil {
59 text = r.scanner.Text()
62 if text[len(text)-1] == '\\' {
63 lines = append(lines, text[:len(text)-1])
65 lines = append(lines, text)
66 fields = append(fields, Field{name, strings.Join(lines, "")})
67 lines = make([]string, 0)
73 if len(text) > 0 && text[0] == '#' {
77 if len(text) > 0 && text[0] == '+' {
78 lines = append(lines, "\n")
81 lines = append(lines, text[2:])
83 lines = append(lines, text[1:])
90 fields = append(fields, Field{name, strings.Join(lines, "")})
91 lines = make([]string, 0)
98 matches := KeyValRe.FindStringSubmatch(text)
99 if len(matches) == 0 {
100 return fields, errors.New("invalid field format")
105 if len(line) > 0 && line[len(line)-1] == '\\' {
107 lines = append(lines, line[:len(line)-1])
109 lines = append(lines, line)
113 return fields, errors.New("left continuation")
116 fields = append(fields, Field{name, strings.Join(lines, "")})
118 if len(fields) == 0 {