-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathreader.go
More file actions
90 lines (78 loc) · 1.72 KB
/
reader.go
File metadata and controls
90 lines (78 loc) · 1.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package pgpass
import (
"bufio"
"errors"
"io"
)
// ErrNotEnoughFields indicates line doesn't contain enough fields
var ErrNotEnoughFields = errors.New("Not enough fields")
// Entry represents single entry in pgpass file
type Entry struct {
Hostname, Port, Database, Username, Password string
}
// EntryReader reads entries from pgpass file
type EntryReader struct {
s *bufio.Scanner
entry Entry
err error
}
// NewEntryReader returns new entry reader from provided r
func NewEntryReader(r io.Reader) *EntryReader {
return &EntryReader{s: bufio.NewScanner(r)}
}
// Next reads in next entry and returns true on success
func (er *EntryReader) Next() (ok bool) {
// Get next line, but skip comments and empty lines
var line string
for {
if !er.s.Scan() {
return
}
line = er.s.Text()
if len(line) > 0 && line[0] != '#' {
break
}
}
fs := getFields(line)
if len(fs) < 5 {
er.err = ErrNotEnoughFields
return
}
er.entry = Entry{fs[0], fs[1], fs[2], fs[3], fs[4]}
return true
}
// Entry returns last read entry
func (er *EntryReader) Entry() Entry {
return er.entry
}
// Err returns underlying error if any.
// Should be checked after unsuccessful call to Next().
func (er *EntryReader) Err() error {
err := er.err
if err == nil {
err = er.s.Err()
}
return err
}
// getFields splits line into fields delimited by colon (:).
// All fields are properly unescaped.
func getFields(s string) []string {
fs := make([]string, 0, 5)
f := make([]rune, 0, len(s))
var esc bool
for _, c := range s {
switch {
case esc:
f = append(f, c)
esc = false
case c == '\\':
esc = true
case c == ':':
fs = append(fs, string(f))
f = f[:0]
default:
f = append(f, c)
}
}
return append(fs, string(f))
}