github.com/karrick/gorill@v1.10.3/nltr.go (about) 1 package gorill 2 3 import ( 4 "io" 5 ) 6 7 // LineTerminatedReader reads from the source io.Reader and ensures the final 8 // byte from this is a newline. 9 type LineTerminatedReader struct { 10 R io.Reader 11 wasFinalByteNewline bool 12 oweNewline bool 13 } 14 15 // Read satisfies the io.Reader interface by reading up to len(p) bytes into p. 16 // It returns the number of bytes read (0 <= n <= len(p)) and any error 17 // encountered. 18 func (r *LineTerminatedReader) Read(p []byte) (int, error) { 19 if r.oweNewline { 20 r.oweNewline = false 21 if len(p) == 0 { 22 return 0, nil // from io.Reader documentation 23 } 24 p[0] = '\n' 25 return 1, io.EOF // allowed per io.Reader documentation 26 } 27 n, err := r.R.Read(p) 28 if n > 0 { 29 r.wasFinalByteNewline = p[n-1] == '\n' 30 } 31 if err != io.EOF || r.wasFinalByteNewline { 32 return n, err 33 } 34 // fmt.Fprintf(os.Stderr, "Hit EOF && final byte was not a newline.\n") 35 if n == len(p) { 36 // No room to append newline to this buffer. 37 r.oweNewline = true 38 return n, nil 39 } 40 // Append the newline byte when it fits. 41 p[n] = '\n' 42 return n + 1, err 43 }