1package parse
2
3import (
4 "io"
5 "io/ioutil"
6)
7
8var nullBuffer = []byte{0}
9
10// Input is a buffered reader that allows peeking forward and shifting, taking an io.Input.
11// It keeps data in-memory until Free, taking a byte length, is called to move beyond the data.
12type Input struct {
13 buf []byte
14 pos int // index in buf
15 start int // index in buf
16 err error
17
18 restore func()
19}
20
21// NewInput returns a new Input for a given io.Input and uses ioutil.ReadAll to read it into a byte slice.
22// If the io.Input implements Bytes, that is used instead. It will append a NULL at the end of the buffer.
23func NewInput(r io.Reader) *Input {
24 var b []byte
25 if r != nil {
26 if buffer, ok := r.(interface {
27 Bytes() []byte
28 }); ok {
29 b = buffer.Bytes()
30 } else {
31 var err error
32 b, err = ioutil.ReadAll(r)
33 if err != nil {
34 return &Input{
35 buf: nullBuffer,
36 err: err,
37 }
38 }
39 }
40 }
41 return NewInputBytes(b)
42}
43
44// NewInputString returns a new Input for a given string and appends NULL at the end.
45func NewInputString(s string) *Input {
46 return NewInputBytes([]byte(s))
47}
48
49// NewInputBytes returns a new Input for a given byte slice and appends NULL at the end.
50// To avoid reallocation, make sure the capacity has room for one more byte.
51func NewInputBytes(b []byte) *Input {
52 z := &Input{
53 buf: b,
54 }
55
56 n := len(b)
57 if n == 0 {
58 z.buf = nullBuffer
59 } else {
60 // Append NULL to buffer, but try to avoid reallocation
61 if cap(b) > n {
62 // Overwrite next byte but restore when done
63 b = b[:n+1]
64 c := b[n]
65 b[n] = 0
66
67 z.buf = b
68 z.restore = func() {
69 b[n] = c
70 }
71 } else {
72 z.buf = append(b, 0)
73 }
74 }
75 return z
76}
77
78// Restore restores the replaced byte past the end of the buffer by NULL.
79func (z *Input) Restore() {
80 if z.restore != nil {
81 z.restore()
82 z.restore = nil
83 }
84}
85
86// Err returns the error returned from io.Input or io.EOF when the end has been reached.
87func (z *Input) Err() error {
88 return z.PeekErr(0)
89}
90
91// PeekErr returns the error at position pos. When pos is zero, this is the same as calling Err().
92func (z *Input) PeekErr(pos int) error {
93 if z.err != nil {
94 return z.err
95 } else if z.pos+pos >= len(z.buf)-1 {
96 return io.EOF
97 }
98 return nil
99}
100
101// Peek returns the ith byte relative to the end position.
102// Peek returns 0 when an error has occurred, Err returns the erroz.
103func (z *Input) Peek(pos int) byte {
104 pos += z.pos
105 return z.buf[pos]
106}
107
108// PeekRune returns the rune and rune length of the ith byte relative to the end position.
109func (z *Input) PeekRune(pos int) (rune, int) {
110 // from unicode/utf8
111 c := z.Peek(pos)
112 if c < 0xC0 || z.Peek(pos+1) == 0 {
113 return rune(c), 1
114 } else if c < 0xE0 || z.Peek(pos+2) == 0 {
115 return rune(c&0x1F)<<6 | rune(z.Peek(pos+1)&0x3F), 2
116 } else if c < 0xF0 || z.Peek(pos+3) == 0 {
117 return rune(c&0x0F)<<12 | rune(z.Peek(pos+1)&0x3F)<<6 | rune(z.Peek(pos+2)&0x3F), 3
118 }
119 return rune(c&0x07)<<18 | rune(z.Peek(pos+1)&0x3F)<<12 | rune(z.Peek(pos+2)&0x3F)<<6 | rune(z.Peek(pos+3)&0x3F), 4
120}
121
122// Move advances the position.
123func (z *Input) Move(n int) {
124 z.pos += n
125}
126
127// Pos returns a mark to which can be rewinded.
128func (z *Input) Pos() int {
129 return z.pos - z.start
130}
131
132// Rewind rewinds the position to the given position.
133func (z *Input) Rewind(pos int) {
134 z.pos = z.start + pos
135}
136
137// Lexeme returns the bytes of the current selection.
138func (z *Input) Lexeme() []byte {
139 return z.buf[z.start:z.pos:z.pos]
140}
141
142// Skip collapses the position to the end of the selection.
143func (z *Input) Skip() {
144 z.start = z.pos
145}
146
147// Shift returns the bytes of the current selection and collapses the position to the end of the selection.
148func (z *Input) Shift() []byte {
149 b := z.buf[z.start:z.pos:z.pos]
150 z.start = z.pos
151 return b
152}
153
154// Offset returns the character position in the buffez.
155func (z *Input) Offset() int {
156 return z.pos
157}
158
159// Bytes returns the underlying buffez.
160func (z *Input) Bytes() []byte {
161 return z.buf[: len(z.buf)-1 : len(z.buf)-1]
162}
163
164// Len returns the length of the underlying buffez.
165func (z *Input) Len() int {
166 return len(z.buf) - 1
167}
168
169// Reset resets position to the underlying buffez.
170func (z *Input) Reset() {
171 z.start = 0
172 z.pos = 0
173}