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  }