just unfold everything beforehand and use a scanner
This commit is contained in:
parent
0e4994ee56
commit
102fc57c2a
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -11,10 +12,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func complain(s string) {
|
|
||||||
fmt.Fprintln(os.Stderr, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func optExit(err error) {
|
func optExit(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
@ -22,46 +19,8 @@ func optExit(err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the vCard RFC says, a single logical line can be "folded" to multiple physical lines,
|
func unfold(s string) string {
|
||||||
// so this shit must be done
|
return strings.ReplaceAll(strings.ReplaceAll(s, "\r\n ", ""), "\r\n\t", "")
|
||||||
type UnfoldingReader struct {
|
|
||||||
buf []byte
|
|
||||||
i int
|
|
||||||
j int
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewUnfoldingReader(buf []byte) *UnfoldingReader {
|
|
||||||
return &UnfoldingReader{buf, 0, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func replaceFold(s string) string {
|
|
||||||
// Yes, I know and I don't care
|
|
||||||
return strings.TrimSpace(strings.ReplaceAll(strings.ReplaceAll(s, "\r\n ", ""), "\r\n\t", ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *UnfoldingReader) ReadLine() (string, bool) {
|
|
||||||
readCR := false
|
|
||||||
readCRLF := false
|
|
||||||
for r.j = r.i; r.j < len(r.buf); r.j++ {
|
|
||||||
if r.buf[r.j] == '\r' {
|
|
||||||
readCR = true
|
|
||||||
} else if readCR && r.buf[r.j] == '\n' {
|
|
||||||
readCRLF = true
|
|
||||||
} else if readCRLF && r.buf[r.j] != ' ' && r.buf[r.j] != '\t' {
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
readCRLF = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var s string
|
|
||||||
if r.i < len(r.buf) {
|
|
||||||
s = replaceFold(string(r.buf[r.i:r.j]))
|
|
||||||
} else {
|
|
||||||
s = ""
|
|
||||||
}
|
|
||||||
notEOB := (r.i < len(r.buf))
|
|
||||||
r.i = r.j
|
|
||||||
return s, notEOB
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func vCardValue(line string) string {
|
func vCardValue(line string) string {
|
||||||
|
@ -185,9 +144,11 @@ func (n *Number) WriteFritzboxXML(s io.Writer, i int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetContacts(buf []byte) (c ContactSet) {
|
func GetContacts(buf []byte) (c ContactSet) {
|
||||||
r := NewUnfoldingReader(buf)
|
s := unfold(string(buf))
|
||||||
|
scanner := bufio.NewScanner(strings.NewReader(s))
|
||||||
var current *Contact
|
var current *Contact
|
||||||
for l, ok := r.ReadLine(); ok; l, ok = r.ReadLine() {
|
for scanner.Scan() {
|
||||||
|
l := strings.TrimSpace(scanner.Text())
|
||||||
if l == "BEGIN:VCARD" {
|
if l == "BEGIN:VCARD" {
|
||||||
current = &Contact{}
|
current = &Contact{}
|
||||||
} else if l == "END:VCARD" {
|
} else if l == "END:VCARD" {
|
||||||
|
@ -197,6 +158,7 @@ func GetContacts(buf []byte) (c ContactSet) {
|
||||||
current.setValue(l)
|
current.setValue(l)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
optExit(scanner.Err())
|
||||||
if current != nil {
|
if current != nil {
|
||||||
c = append(c, *current)
|
c = append(c, *current)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user