1// Copyright 2015 Google Inc. All rights reserved 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package kati 16 17import ( 18 "io" 19 "sync" 20) 21 22var ( 23 ebufFree = sync.Pool{ 24 New: func() interface{} { return new(evalBuffer) }, 25 } 26 wbufFree = sync.Pool{ 27 New: func() interface{} { return new(wordBuffer) }, 28 } 29) 30 31func writeByte(w io.Writer, b byte) error { 32 if bw, ok := w.(io.ByteWriter); ok { 33 return bw.WriteByte(b) 34 } 35 _, err := w.Write([]byte{b}) 36 return err 37} 38 39// use io.WriteString to stringWrite. 40 41type ssvWriter struct { 42 io.Writer 43 sep bool 44} 45 46func (w *ssvWriter) writeWord(word []byte) { 47 if w.sep { 48 writeByte(w.Writer, ' ') 49 } 50 w.sep = true 51 w.Writer.Write(word) 52} 53 54func (w *ssvWriter) writeWordString(word string) { 55 if w.sep { 56 writeByte(w.Writer, ' ') 57 } 58 w.sep = true 59 io.WriteString(w.Writer, word) 60} 61 62func (w *ssvWriter) resetSep() { 63 w.sep = false 64} 65 66type buffer struct { 67 buf []byte 68 bootstrap [64]byte // memory to hold first slice 69} 70 71func (b *buffer) Write(data []byte) (int, error) { 72 b.buf = append(b.buf, data...) 73 return len(data), nil 74} 75 76func (b *buffer) WriteByte(c byte) error { 77 b.buf = append(b.buf, c) 78 return nil 79} 80 81func (b *buffer) WriteString(s string) (int, error) { 82 b.buf = append(b.buf, []byte(s)...) 83 return len(s), nil 84} 85 86func (b *buffer) Bytes() []byte { return b.buf } 87func (b *buffer) Len() int { return len(b.buf) } 88func (b *buffer) String() string { return string(b.buf) } 89 90func (b *buffer) Reset() { 91 if b.buf == nil { 92 b.buf = b.bootstrap[:0] 93 } 94 b.buf = b.buf[:0] 95} 96 97type evalBuffer struct { 98 buffer 99 ssvWriter 100 args [][]byte 101} 102 103func newEbuf() *evalBuffer { 104 buf := ebufFree.Get().(*evalBuffer) 105 buf.Reset() 106 return buf 107} 108 109func (buf *evalBuffer) release() { 110 if cap(buf.Bytes()) > 1024 { 111 return 112 } 113 buf.Reset() 114 buf.args = buf.args[:0] 115 ebufFree.Put(buf) 116} 117 118func (b *evalBuffer) Reset() { 119 b.buffer.Reset() 120 b.resetSep() 121} 122 123func (b *evalBuffer) resetSep() { 124 if b.ssvWriter.Writer == nil { 125 b.ssvWriter.Writer = &b.buffer 126 } 127 b.ssvWriter.resetSep() 128} 129 130type wordBuffer struct { 131 buf buffer 132 words [][]byte 133} 134 135func newWbuf() *wordBuffer { 136 buf := wbufFree.Get().(*wordBuffer) 137 buf.Reset() 138 return buf 139} 140 141func (buf *wordBuffer) release() { 142 if cap(buf.Bytes()) > 1024 { 143 return 144 } 145 buf.Reset() 146 wbufFree.Put(buf) 147} 148 149func (wb *wordBuffer) Write(data []byte) (int, error) { 150 if len(data) == 0 { 151 return 0, nil 152 } 153 off := len(wb.buf.buf) 154 var cont bool 155 if !isWhitespace(rune(data[0])) && len(wb.buf.buf) > 0 { 156 cont = !isWhitespace(rune(wb.buf.buf[off-1])) 157 } 158 ws := newWordScanner(data) 159 for ws.Scan() { 160 if cont { 161 word := wb.words[len(wb.words)-1] 162 wb.words = wb.words[:len(wb.words)-1] 163 wb.buf.buf = wb.buf.buf[:len(wb.buf.buf)-len(word)] 164 var w []byte 165 w = append(w, word...) 166 w = append(w, ws.Bytes()...) 167 wb.writeWord(w) 168 cont = false 169 continue 170 } 171 wb.writeWord(ws.Bytes()) 172 } 173 if isWhitespace(rune(data[len(data)-1])) { 174 wb.buf.buf = append(wb.buf.buf, ' ') 175 } 176 return len(data), nil 177} 178 179func (wb *wordBuffer) WriteByte(c byte) error { 180 _, err := wb.Write([]byte{c}) 181 return err 182} 183 184func (wb *wordBuffer) WriteString(s string) (int, error) { 185 return wb.Write([]byte(s)) 186} 187 188func (wb *wordBuffer) writeWord(word []byte) { 189 if len(wb.buf.buf) > 0 { 190 wb.buf.buf = append(wb.buf.buf, ' ') 191 } 192 off := len(wb.buf.buf) 193 wb.buf.buf = append(wb.buf.buf, word...) 194 wb.words = append(wb.words, wb.buf.buf[off:off+len(word)]) 195} 196 197func (wb *wordBuffer) writeWordString(word string) { 198 wb.writeWord([]byte(word)) 199} 200 201func (wb *wordBuffer) Reset() { 202 wb.buf.Reset() 203 wb.words = nil 204} 205 206func (wb *wordBuffer) resetSep() {} 207 208func (wb *wordBuffer) Bytes() []byte { 209 return wb.buf.Bytes() 210} 211