-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreader.go
More file actions
124 lines (109 loc) · 2.42 KB
/
Copy pathreader.go
File metadata and controls
124 lines (109 loc) · 2.42 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
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
118
119
120
121
122
123
124
package klon
import (
"io"
"github.com/ProCode-Software/klar/internal/lexer"
"github.com/ProCode-Software/klar/pkg/klon/ast"
"github.com/ProCode-Software/klar/pkg/klon/klonflags"
)
const BufferSize = 64
type bailout struct{}
type reader struct {
buffer []byte
reader io.Reader
pos int // Buffer position
offset lexer.Position
curr *Token
peek *Token
parseFlags uint8
depth int
lastDashes int
vars map[string]ast.Value
ctx *Context
flags klonflags.Flags
errs []error
comments []*ast.Comment
}
func newBufferReader(buf []byte, f ...klonflags.Flags) *reader {
return &reader{
buffer: buf,
offset: lexer.Position{1, 1},
flags: parseFlags(f...),
lastDashes: -1,
}
}
func newStreamReader(r io.Reader, f ...klonflags.Flags) *reader {
return &reader{
buffer: make([]byte, 0, BufferSize),
reader: r,
offset: lexer.Position{1, 1},
flags: parseFlags(f...),
lastDashes: -1,
}
}
// Rune reader
// ===============
func (rd *reader) needsMore() bool {
return rd.pos >= len(rd.buffer)-1
}
// Refill fills the buffer to full capacity if needed. Refill returns an error
// if another byte cannot be read.
func (rd *reader) refill() error {
if rd.reader == nil {
if rd.pos >= len(rd.buffer) {
return io.EOF
}
return nil
}
if rd.pos < len(rd.buffer) {
// Copy remaining bytes to the beginning of the buffer
copy(rd.buffer, rd.buffer[rd.pos:])
rd.buffer = rd.buffer[:len(rd.buffer)-rd.pos]
rd.pos = 0
} else {
rd.buffer = rd.buffer[:0]
rd.pos = 0
}
n, err := rd.reader.Read(rd.buffer[len(rd.buffer):cap(rd.buffer)])
if n > 0 {
rd.buffer = rd.buffer[:len(rd.buffer)+n]
}
if err != nil && err != io.EOF {
return err
}
if len(rd.buffer) == 0 {
return io.EOF
}
return nil
}
// tryRefill refills the buffer if needed. If the buffer can't be refilled,
// tryRefil returns eof if err == io.EOF, otherwise it panics.
func (rd *reader) tryRefill() (eof error) {
if rd.needsMore() {
if err := rd.refill(); err != nil {
if err == io.EOF {
return io.EOF
}
panic(ReadError{err})
}
}
return nil
}
func handlePanic(e *error) {
switch err := recover().(type) {
case nil:
return
case bailout:
return
case ReadError:
*e = err
default:
panic(err)
}
}
func parseFlags(flags ...klonflags.Flags) klonflags.Flags {
var f klonflags.Flags
for _, flag := range flags {
f |= flag
}
return f
}