input.go (4154B)
1 package parse 2 3 import ( 4 "io" 5 "io/ioutil" 6 ) 7 8 var 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. 12 type 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. 23 func 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. 45 func 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. 51 func 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. 79 func (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. 87 func (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(). 92 func (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. 103 func (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. 109 func (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. 123 func (z *Input) Move(n int) { 124 z.pos += n 125 } 126 127 // Pos returns a mark to which can be rewinded. 128 func (z *Input) Pos() int { 129 return z.pos - z.start 130 } 131 132 // Rewind rewinds the position to the given position. 133 func (z *Input) Rewind(pos int) { 134 z.pos = z.start + pos 135 } 136 137 // Lexeme returns the bytes of the current selection. 138 func (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. 143 func (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. 148 func (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. 155 func (z *Input) Offset() int { 156 return z.pos 157 } 158 159 // Bytes returns the underlying buffez. 160 func (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. 165 func (z *Input) Len() int { 166 return len(z.buf) - 1 167 } 168 169 // Reset resets position to the underlying buffez. 170 func (z *Input) Reset() { 171 z.start = 0 172 z.pos = 0 173 }