github.com/haraldrudell/parl@v0.4.176/pio/write-closer-to-chan-line.go (about) 1 /* 2 © 2021–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package pio 7 8 import ( 9 "io" 10 "io/fs" 11 "strings" 12 "sync" 13 14 "github.com/haraldrudell/parl" 15 "github.com/haraldrudell/parl/perrors" 16 ) 17 18 type WriteCloserToChanLine struct { 19 lock sync.Mutex 20 s string 21 ch parl.NBChan[string] 22 withNewline bool 23 } 24 25 func NewWriteCloserToChanLine(withNewline ...bool) (writeCloser io.WriteCloser) { 26 var withNewline0 bool 27 if len(withNewline) > 0 { 28 withNewline0 = withNewline[0] 29 } 30 return &WriteCloserToChanLine{withNewline: withNewline0} 31 } 32 33 func (wc *WriteCloserToChanLine) Write(p []byte) (n int, err error) { 34 35 // check for closed write stream 36 if wc.ch.DidClose() { 37 err = perrors.ErrorfPF(fs.ErrClosed.Error()) 38 return 39 } 40 41 wc.lock.Lock() 42 defer wc.lock.Unlock() 43 44 // write data to string 45 s := wc.s + string(p) 46 n = len(p) 47 48 // write buffer line-by-line to channel 49 for { 50 index := strings.Index(s, "\n") 51 if index == -1 { 52 break // no more newlines 53 } 54 var i int 55 if wc.withNewline { 56 i = index + 1 57 } else { 58 i = index 59 } 60 wc.ch.Send(s[:i]) 61 s = s[index+1:] 62 } 63 wc.s = s // store remaining string characters 64 65 return 66 } 67 68 func (wc *WriteCloserToChanLine) Close() (err error) { 69 wc.lock.Lock() 70 defer wc.lock.Unlock() 71 72 if wc.s != "" { 73 wc.ch.Send(wc.s) 74 } 75 76 wc.ch.Close() 77 return 78 } 79 80 func (wc *WriteCloserToChanLine) Ch() (readCh <-chan string) { 81 return wc.ch.Ch() 82 }