-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathio.go
121 lines (105 loc) · 2.79 KB
/
io.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package dry
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"os"
)
type CountingReader struct {
Reader io.Reader
BytesRead int
}
func (r *CountingReader) Read(p []byte) (n int, err error) {
n, err = r.Reader.Read(p)
r.BytesRead += n
return n, err
}
type CountingWriter struct {
Writer io.Writer
BytesWritten int
}
func (r *CountingWriter) Write(p []byte) (n int, err error) {
n, err = r.Writer.Write(p)
r.BytesWritten += n
return n, err
}
type CountingReadWriter struct {
ReadWriter io.ReadWriter
BytesRead int
BytesWritten int
}
func (rw *CountingReadWriter) Read(p []byte) (n int, err error) {
n, err = rw.ReadWriter.Read(p)
rw.BytesRead += n
return n, err
}
func (rw *CountingReadWriter) Write(p []byte) (n int, err error) {
n, err = rw.ReadWriter.Write(p)
rw.BytesWritten += n
return n, err
}
// ReadBinary wraps binary.Read with a CountingReader and returns
// the acutal bytes read by it.
func ReadBinary(r io.Reader, order binary.ByteOrder, data interface{}) (n int, err error) {
countingReader := CountingReader{Reader: r}
err = binary.Read(&countingReader, order, data)
return countingReader.BytesRead, err
}
// WriteFull calls writer.Write until all of data is written,
// or an is error returned.
func WriteFull(data []byte, writer io.Writer) (n int, err error) {
dataSize := len(data)
for n = 0; n < dataSize; {
m, err := writer.Write(data[n:])
n += m
if err != nil {
return n, err
}
}
return dataSize, nil
}
// ReadLine reads unbuffered until a newline '\n' byte and removes
// an optional carriege return '\r' at the end of the line.
// In case of an error, the string up to the error is returned.
func ReadLine(reader io.Reader) (line string, err error) {
buffer := bytes.NewBuffer(make([]byte, 0, 4096))
p := make([]byte, 1)
for {
var n int
n, err = reader.Read(p)
if err != nil || p[0] == '\n' {
break
}
if n > 0 {
buffer.WriteByte(p[0])
}
}
data := buffer.Bytes()
if len(data) > 0 && data[len(data)-1] == '\r' {
data = data[:len(data)-1]
}
return string(data), err
}
// WaitForStdin blocks until input is available from os.Stdin.
// The first byte from os.Stdin is returned as result.
// If there are println arguments, then fmt.Println will be
// called with those before reading from os.Stdin.
func WaitForStdin(println ...interface{}) byte {
if len(println) > 0 {
fmt.Println(println...)
}
buffer := make([]byte, 1)
os.Stdin.Read(buffer) //#nosec G104
return buffer[0]
}
// ReaderFunc implements io.Reader as function type with a Read method.
type ReaderFunc func(p []byte) (int, error)
func (f ReaderFunc) Read(p []byte) (int, error) {
return f(p)
}
// WriterFunc implements io.Writer as function type with a Write method.
type WriterFunc func(p []byte) (int, error)
func (f WriterFunc) Write(p []byte) (int, error) {
return f(p)
}