-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathescape.go
More file actions
79 lines (71 loc) · 1.95 KB
/
escape.go
File metadata and controls
79 lines (71 loc) · 1.95 KB
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
package lineprotocol
import (
"strconv"
"strings"
)
// escaper represents a set of characters that can be escaped.
type escaper struct {
// table maps from byte value to the byte used to escape that value.
// If an entry is zero, it doesn't need to be escaped.
table [256]byte
// revTable holds the inverse of table - it maps
// from escaped value to the unescaped value.
revTable [256]byte
// escapes holds all the characters that need to be escaped.
escapes string
}
// newEscaper returns an escaper that escapes the
// given characters.
func newEscaper(escapes string) *escaper {
var e escaper
for _, b := range escapes {
// Note that this works because the Go escaping rules
// for white space are the same as line-protocol's.
q := strconv.QuoteRune(b)
q = q[1 : len(q)-1] // strip single quotes.
q = strings.TrimPrefix(q, "\\") // remove backslash if present.
e.table[byte(b)] = q[0] // use single remaining character.
e.revTable[q[0]] = byte(b)
}
e.escapes = escapes
return &e
}
// appendEscaped returns the escaped form of s appended to buf.
func (e *escaper) appendEscaped(buf []byte, s string) []byte {
newLen := e.escapedLen(s)
if newLen == len(s) {
return append(buf, s...)
}
if cap(buf)-len(buf) < newLen {
nBuf := make([]byte, len(buf), len(buf)+newLen)
copy(nBuf, buf)
buf = nBuf
}
e._escape(buf[len(buf):len(buf)+newLen], s)
return buf[:len(buf)+newLen]
}
func (e *escaper) escapedLen(s string) int {
n := len(s)
for i := 0; i < len(e.escapes); i++ {
n += strings.Count(s, e.escapes[i:i+1])
}
return n
}
// _escape writes the escaped form of s into buf. It
// assumes buf is the correct length (as determined
// by escapedLen).
// This method should be treated as private to escaper.
func (e *escaper) _escape(buf []byte, s string) {
j := 0
for i := 0; i < len(s); i++ {
b := s[i]
if r := e.table[b]; r != 0 {
buf[j] = '\\'
buf[j+1] = r
j += 2
} else {
buf[j] = b
j++
}
}
}