mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
Implement PrefixWriter
PrefixWriter is a passthrough io.Writer that prepends a prefix to the beginning of each line.
This commit is contained in:
parent
b1084c1362
commit
da279cf3ff
@ -51,16 +51,18 @@ func probe(hwProbeFns []device.ProbeFn) []device.Driver {
|
||||
continue
|
||||
}
|
||||
|
||||
strBuf.Reset()
|
||||
major, minor, patch := drv.DriverVersion()
|
||||
kfmt.Fprintf(&strBuf, "[hal] %s(%d.%d.%d): ", drv.DriverName(), major, minor, patch)
|
||||
w.prefix = strBuf.Bytes()
|
||||
|
||||
kfmt.Printf("[hal] %s(%d.%d.%d): ", drv.DriverName(), major, minor, patch)
|
||||
if err := drv.DriverInit(); err != nil {
|
||||
kfmt.Printf("init failed: %s\n", err.Message)
|
||||
if err := drv.DriverInit(&w); err != nil {
|
||||
kfmt.Fprintf(&w, "init failed: %s\n", err.Message)
|
||||
continue
|
||||
}
|
||||
|
||||
kfmt.Fprintf(&w, "initialized\n")
|
||||
drivers = append(drivers, drv)
|
||||
kfmt.Printf("initialized\n")
|
||||
}
|
||||
|
||||
return drivers
|
||||
|
57
src/gopheros/kernel/kfmt/prefix_writer.go
Normal file
57
src/gopheros/kernel/kfmt/prefix_writer.go
Normal file
@ -0,0 +1,57 @@
|
||||
package kfmt
|
||||
|
||||
import "io"
|
||||
|
||||
// PrefixWriter is an io.Writer that wraps another io.Writer and injects a
|
||||
// prefix at the beginning of each line.
|
||||
type PrefixWriter struct {
|
||||
// A writer where all writes get sent to.
|
||||
Sink io.Writer
|
||||
|
||||
// The prefix injected at the beginning of each line.
|
||||
Prefix []byte
|
||||
|
||||
bytesAfterPrefix int
|
||||
}
|
||||
|
||||
// Write writes len(p) bytes from p to the underlying data stream and returns
|
||||
// back the number of bytes written. The PrefixWriter keeps track of the
|
||||
// beginning of new lines and injects the configured prefix at each new line.
|
||||
// The injected prefix is not included in the number of written bytes returned
|
||||
// by this method.
|
||||
func (w *PrefixWriter) Write(p []byte) (int, error) {
|
||||
var (
|
||||
written int
|
||||
startIndex, curIndex int
|
||||
)
|
||||
|
||||
if w.bytesAfterPrefix == 0 && len(p) != 0 {
|
||||
w.Sink.Write(w.Prefix)
|
||||
}
|
||||
|
||||
for ; curIndex < len(p); curIndex++ {
|
||||
if p[curIndex] == '\n' {
|
||||
n, err := w.Sink.Write(p[startIndex : curIndex+1])
|
||||
if curIndex+1 != len(p) {
|
||||
w.Sink.Write(w.Prefix)
|
||||
}
|
||||
written += n
|
||||
if err != nil {
|
||||
return written, err
|
||||
}
|
||||
w.bytesAfterPrefix = 0
|
||||
startIndex = curIndex + 1
|
||||
}
|
||||
}
|
||||
|
||||
if startIndex < curIndex {
|
||||
n, err := w.Sink.Write(p[startIndex:curIndex])
|
||||
written += n
|
||||
w.bytesAfterPrefix = n
|
||||
if err != nil {
|
||||
return written, err
|
||||
}
|
||||
}
|
||||
|
||||
return written, nil
|
||||
}
|
92
src/gopheros/kernel/kfmt/prefix_writer_test.go
Normal file
92
src/gopheros/kernel/kfmt/prefix_writer_test.go
Normal file
@ -0,0 +1,92 @@
|
||||
package kfmt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPrefixWriter(t *testing.T) {
|
||||
specs := []struct {
|
||||
input string
|
||||
exp string
|
||||
}{
|
||||
{
|
||||
"",
|
||||
"",
|
||||
},
|
||||
{
|
||||
"\n",
|
||||
"prefix: \n",
|
||||
},
|
||||
{
|
||||
"no line break anywhere",
|
||||
"prefix: no line break anywhere",
|
||||
},
|
||||
{
|
||||
"line feed at the end\n",
|
||||
"prefix: line feed at the end\n",
|
||||
},
|
||||
{
|
||||
"\nthe big brown\nfog jumped\nover the lazy\ndog",
|
||||
"prefix: \nprefix: the big brown\nprefix: fog jumped\nprefix: over the lazy\nprefix: dog",
|
||||
},
|
||||
}
|
||||
|
||||
var (
|
||||
buf bytes.Buffer
|
||||
w = PrefixWriter{
|
||||
Sink: &buf,
|
||||
Prefix: []byte("prefix: "),
|
||||
}
|
||||
)
|
||||
|
||||
for specIndex, spec := range specs {
|
||||
buf.Reset()
|
||||
w.bytesAfterPrefix = 0
|
||||
|
||||
wrote, err := w.Write([]byte(spec.input))
|
||||
if err != nil {
|
||||
t.Errorf("[spec %d] unexpected error: %v", specIndex, err)
|
||||
}
|
||||
|
||||
if expLen := len(spec.input); expLen != wrote {
|
||||
t.Errorf("[spec %d] expected writer to write %d bytes; wrote %d", specIndex, expLen, wrote)
|
||||
}
|
||||
|
||||
if got := buf.String(); got != spec.exp {
|
||||
t.Errorf("[spec %d] expected output:\n%q\ngot:\n%q", specIndex, spec.exp, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrefixWriterErrors(t *testing.T) {
|
||||
specs := []string{
|
||||
"no line break anywhere",
|
||||
"\nthe big brown\nfog jumped\nover the lazy\ndog",
|
||||
}
|
||||
|
||||
var (
|
||||
expErr = errors.New("write failed")
|
||||
w = PrefixWriter{
|
||||
Sink: writerThatAlwaysErrors{expErr},
|
||||
Prefix: []byte("prefix: "),
|
||||
}
|
||||
)
|
||||
|
||||
for specIndex, spec := range specs {
|
||||
w.bytesAfterPrefix = 0
|
||||
_, err := w.Write([]byte(spec))
|
||||
if err != expErr {
|
||||
t.Errorf("[spec %d] expected error: %v; got %v", specIndex, expErr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type writerThatAlwaysErrors struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (w writerThatAlwaysErrors) Write(_ []byte) (int, error) {
|
||||
return 0, w.err
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user