-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathcomment_skipper.go
117 lines (98 loc) · 1.89 KB
/
comment_skipper.go
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
110
111
112
113
114
115
116
117
package main
import "io"
import "bufio"
type comment_skipper struct {
r *bufio.Reader
}
func new_comment_skipper(r io.Reader) *comment_skipper {
return &comment_skipper{bufio.NewReader(r)}
}
// advance to str and consume it or return error if it's not possible
func (cs *comment_skipper) advance_to(str string) error {
if len(str) == 0 {
panic("zero-length string is not acceptable")
}
cur := 0
for {
b, err := cs.r.ReadByte()
if err != nil {
return err
}
for {
// check if we have match with cur
if str[cur] != b {
break
}
// got match, see if there are other
// symbols to match with and continue if so
if len(str)-1 > cur {
cur++
b, err = cs.r.ReadByte()
if err != nil {
return err
}
continue
}
return nil
}
}
panic("unreachable")
return nil
}
// advance to str, consume it, read and return the next byte if possible
func (cs *comment_skipper) advance_to_and_read_byte(str string) (byte, error) {
err := cs.advance_to(str)
if err != nil {
return 0, err
}
b, err := cs.r.ReadByte()
if err != nil {
return 0, err
}
return b, nil
}
func (cs *comment_skipper) Read(data []byte) (int, error) {
read := 0
for {
// check if we're done here
if read == len(data) {
return read, nil
}
b, err := cs.r.ReadByte()
if err != nil {
return read, err
}
// skip possible comments
if b == '/' {
b, err = cs.r.ReadByte()
if err != nil {
return read, err
}
switch b {
case '/':
// C++ comment
err = cs.advance_to("\n")
if err != nil {
return read, err
}
b = '\n'
case '*':
// C comment
b, err = cs.advance_to_and_read_byte("*/")
if err != nil {
return read, err
}
default:
err = cs.r.UnreadByte()
if err != nil {
panic("shouldn't ever happen")
}
b = '/'
}
}
data[read] = b
read++
}
panic("unreachable")
return 0, nil
}