Newer
Older
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package core
import (
"bufio"
"fmt"
"io"
"log"
)
// Middleware Importer that (1) fixes all IRIs by escaping them quite
// aggressively and then (2) forward them all to another Importer.
type IriFixImporter struct {
Next Importer
}
// Implements io.Reader for use in IriFixImporter.
type irifixreader struct {
// We read bytes from this Reader.
source io.Reader
// We put converted bytes into this ch.
ch chan byte
}
func (ifi IriFixImporter) Import(rdf io.Reader) error {
proxy := &irifixreader{
source: rdf,
ch: make(chan byte, 1024),
}
go proxy.writeToChan()
return ifi.Next.Import(proxy)
}
// Implement io.Reader
func (ifr *irifixreader) Read(p []byte) (nbytes int, err error) {
for nbytes = 0; nbytes < len(p); nbytes += 1 {
if b, ok := <-ifr.ch; !ok {
break
} else {
p[nbytes] = b
}
}
if nbytes == 0 {
return 0, io.EOF
}
return nbytes, nil
}
// Fill ifr.ch with with a fixed version of ifr.source.
func (ifr *irifixreader) writeToChan() {
br := bufio.NewReader(ifr.source)
insideQuotes := false
for {
r, _, err := br.ReadRune()
// error handling
if err == io.EOF {
close(ifr.ch)
break
}
if err != nil {
close(ifr.ch)
log.Print(err)
break
}
// state machine
if r == '"' {
insideQuotes = !insideQuotes
}
var bs []byte
if insideQuotes {
bs = ifr.fixed(r)
} else {
bs = []byte(string(r))
}
// Write out to channel (where it will eventually
// be consumed by Read).
for _, b := range bs {
ifr.ch <- b
}
}
}
func (ifr *irifixreader) fixed(r rune) []byte {
bads := []rune{
'|', '\n', ' ', '^', '\\',
}
for _, bad := range bads {
if r == bad {
return []byte(fmt.Sprintf("%%%X", r))
}
}
return []byte(string(r))
}