forked from OpenPrinting/ipp-usb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
linewriter.go
81 lines (69 loc) · 1.83 KB
/
linewriter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/* ipp-usb - HTTP reverse proxy, backed by IPP-over-USB connection to device
*
* Copyright (C) 2020 and up by Alexander Pevzner ([email protected])
* See LICENSE for license terms and conditions
*
* LineWriter is a helper object, implementing io.Writer interface
* on a top of write-line callback. It is used by logger.
*/
package main
import (
"bytes"
)
// LineWriter implements io.Write and io.Close interfaces
// It splits stream into text lines and calls a provided
// callback for each complete line.
//
// Line passed to callback is not terminated by '\n'
// character. Close flushes last incomplete line, if any
type LineWriter struct {
Func func([]byte) // write-line callback
Prefix string // Prefix prepended to each line
buf bytes.Buffer // buffer for incomplete lines
}
// Write implements io.Writer interface
func (lw *LineWriter) Write(text []byte) (n int, err error) {
n = len(text)
for len(text) > 0 {
// Fetch next line
var line []byte
var unfinished bool
if l := bytes.IndexByte(text, '\n'); l >= 0 {
l++
line = text[:l-1]
text = text[l:]
} else {
line = text
text = nil
unfinished = true
}
// Dispatch next line
if lw.buf.Len() == 0 {
lw.buf.Write([]byte(lw.Prefix))
}
lw.buf.Write(line)
if !unfinished {
lw.Func(lw.buf.Bytes())
lw.buf.Reset()
}
}
return
}
// Close implements io.Closer interface
//
// Close flushes the last incomplete line from the
// internal buffer. Close is not needed, if it is
// known that there is no such a line, or if its
// presence doesn't matter (without Close its content
// will be lost)
func (lw *LineWriter) Close() error {
if lw.buf.Len() > 0 {
lw.Func(lw.buf.Bytes())
}
return nil
}
// WriteClose writes text to LineWriter and then closes it
func (lw *LineWriter) WriteClose(text []byte) {
lw.Write(text)
lw.Close()
}