forked from postmanlabs/observability-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjson_preprocessor.go
73 lines (60 loc) · 1.85 KB
/
json_preprocessor.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
package learn
import (
"io"
)
type stripControlCharactersReader struct {
hasPrecedingBackslash bool
wrapped io.Reader
}
func newStripControlCharactersReader(wrapped io.Reader) *stripControlCharactersReader {
return &stripControlCharactersReader{wrapped: wrapped}
}
// Read up to len(p) bytes, removing any control characters found.
// Removed characters do not count toward the total bytes read.
//
// If the control character is preceded by a backslash, it is replaced with a
// backslash rather than removed, e.g. "\<CR>" becomes "\\". This prevents
// the JSON parser from applying the backslash to escape the next character.
//
// Returns the number of bytes read.
func (r *stripControlCharactersReader) Read(p []byte) (n int, err error) {
pIdx := 0
buf := make([]byte, len(p))
// Read up to len(p) bytes, then discard any control characters. Continue
// reading (and discarding control characters) until p is full or there are
// no more bytes to read.
for pIdx < len(p) {
remaining := len(p) - pIdx
bufSlice := buf[:remaining]
var bufN int
bufN, err = r.wrapped.Read(bufSlice)
// Copy from buf to p, skipping control characters.
for _, c := range bufSlice[:bufN] {
toWrite := c
if c <= 0x1f {
if r.hasPrecedingBackslash {
// If the control character is escaped, replace it with a
// backslash.
toWrite = '\\'
} else {
// Otherwise, just remove it.
continue
}
}
if c == '\\' {
r.hasPrecedingBackslash = !r.hasPrecedingBackslash
} else {
r.hasPrecedingBackslash = false
}
p[pIdx] = toWrite
pIdx += 1
}
// If we hit an error or read fewer bytes than the size of the buffer,
// don't bother trying to read more from the underlying reader.
if err != nil || bufN < remaining {
break
}
// Otherwise, we loop to replace CRs we dropped.
}
return pIdx, err
}