blob: a67fdf54e848ed50a08bbef77f9d7090d0fd278e [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"io"
"os"
)
// prefixer is a io.WriteCloser that adds given prefix to each line of the output.
type prefixer struct {
prefix []byte
writer io.Writer
buffer bytes.Buffer
}
// newPrefixer returns a new prefixer that uses the given prefix.
func newPrefixer(prefix string, writer io.Writer) *prefixer {
return &prefixer{
prefix: []byte("[" + prefix + "]\t"),
writer: writer,
buffer: bytes.Buffer{},
}
}
func (p *prefixer) Write(b []byte) (int, error) {
// write the bytes to the buffer.
p.buffer.Write(b)
// For each line in the unread buffer, add the prefix and write it to the underlying writer.
for {
idx := bytes.IndexByte(p.buffer.Bytes(), '\n')
if idx == -1 {
break
}
prefixed := append(p.prefix, p.buffer.Next(idx+1)...)
if _, err := p.writer.Write(prefixed); err != nil {
return len(b), err
}
}
return len(b), nil
}
// Close flushes the remaining buffer content with prefix, and closes the underlying writer if applicable.
func (p *prefixer) Close() error {
// Flush the remaining buffer content if any.
// Add the prefix at the beginning, and a newline character at the end.
if p.buffer.Len() > 0 {
prefixed := append(p.prefix, p.buffer.Bytes()...)
prefixed = append(prefixed, '\n')
if _, err := p.writer.Write(prefixed); err != nil {
return err
}
}
// Close the underlying writer unless the writer is stdout or stderr.
if p.writer != os.Stdout && p.writer != os.Stderr {
if closer, ok := p.writer.(io.Closer); ok {
return closer.Close()
}
}
return nil
}