forked from Onyx-Protocol/Onyx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
122 lines (110 loc) · 2.05 KB
/
main.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
122
package main
import (
"encoding/hex"
"flag"
"io"
"log"
"math"
"os"
)
var (
decode bool
lineLen = flag.Int("n", math.MaxInt32, "max encoded output line `length`")
)
func main() {
log.SetFlags(0)
log.SetPrefix("hex: ")
flag.BoolVar(&decode, "d", false, "decode (negates -e)")
flagNotBoolVar(&decode, "e", true, "encode (negates -d) (default true)")
flag.Parse()
var r io.Reader = &encodeReader{os.Stdin}
if *lineLen >= 2 {
r = &splitLineReader{r: r, max: *lineLen - *lineLen%2}
}
if decode {
r = &decodeReader{r: &stripSpaceReader{os.Stdin}}
}
_, err := io.Copy(os.Stdout, r)
if err != nil {
log.Fatal(err)
}
}
type encodeReader struct {
r io.Reader
}
func (r *encodeReader) Read(p []byte) (int, error) {
if len(p)%2 == 1 {
p = p[:len(p)-1]
}
h := p[len(p)/2:]
n, err := r.r.Read(h)
return hex.Encode(p, h[:n]), err
}
type splitLineReader struct {
r io.Reader
n int
max int
}
func (r *splitLineReader) Read(p []byte) (int, error) {
if len(p) == 0 {
return 0, nil
}
p = p[:len(p)-1] // leave room for possible '\n' below
if len(p) > r.max-r.n {
p = p[:r.max-r.n]
}
n, err := r.r.Read(p)
p = p[:n]
r.n += n
if r.n >= r.max || err == io.EOF {
p = p[:n+1]
p[n] = '\n'
r.n = 0
}
return len(p), err
}
type decodeReader struct {
r io.Reader
par int // parity of last read (0 or 1)
b byte // odd byte from last read (if any)
}
func (r *decodeReader) Read(p []byte) (int, error) {
if len(p) == 0 {
return 0, nil
}
if r.par == 1 {
p[0] = r.b
}
n, err := r.r.Read(p[r.par:])
p = p[:r.par+n]
r.par = len(p) % 2
if r.par == 1 {
r.b = p[len(p)-1]
p = p[:len(p)-1]
}
d, err1 := hex.Decode(p, p)
if err1 != nil {
return d, err1
}
if r.par == 1 && err == io.EOF {
err = hex.ErrLength
}
return d, err
}
type stripSpaceReader struct {
r io.Reader
}
func (r *stripSpaceReader) Read(p []byte) (int, error) {
n, err := r.r.Read(p)
w := 0
for _, b := range p[:n] {
if !isSpace(b) {
p[w] = b
w++
}
}
return w, err
}
func isSpace(b byte) bool {
return b == ' ' || b == '\t' || b == '\n' || b == '\r'
}