github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/uio/linewriter.go (about) 1 // Copyright 2019 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package uio 6 7 import ( 8 "bytes" 9 "io" 10 ) 11 12 // LineWriter processes one line of log output at a time. 13 type LineWriter interface { 14 // OneLine is always called with exactly one line of output. 15 OneLine(b []byte) 16 } 17 18 // FullLineWriter returns an io.Writer that waits for a full line of prints 19 // before calling w.Write on one line each. 20 func FullLineWriter(w LineWriter) io.WriteCloser { 21 return &fullLineWriter{w: w} 22 } 23 24 type fullLineWriter struct { 25 w LineWriter 26 buffer []byte 27 } 28 29 func (fsw *fullLineWriter) printBuf() { 30 bufs := bytes.Split(fsw.buffer, []byte{'\n'}) 31 for _, buf := range bufs { 32 if len(buf) != 0 { 33 fsw.w.OneLine(buf) 34 } 35 } 36 fsw.buffer = nil 37 } 38 39 // Write implements io.Writer and buffers p until at least one full line is 40 // received. 41 func (fsw *fullLineWriter) Write(p []byte) (int, error) { 42 i := bytes.LastIndexByte(p, '\n') 43 if i == -1 { 44 fsw.buffer = append(fsw.buffer, p...) 45 } else { 46 fsw.buffer = append(fsw.buffer, p[:i]...) 47 fsw.printBuf() 48 fsw.buffer = append([]byte{}, p[i:]...) 49 } 50 return len(p), nil 51 } 52 53 // Close implements io.Closer and flushes the buffer. 54 func (fsw *fullLineWriter) Close() error { 55 fsw.printBuf() 56 return nil 57 }