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
|
package xml
var (
ltEntityBytes = []byte("<")
ampEntityBytes = []byte("&")
singleQuoteEntityBytes = []byte("'")
doubleQuoteEntityBytes = []byte(""")
)
// EscapeAttrVal returns the escape attribute value bytes without quotes.
func EscapeAttrVal(buf *[]byte, b []byte) []byte {
singles := 0
doubles := 0
for _, c := range b {
if c == '"' {
doubles++
} else if c == '\'' {
singles++
}
}
n := len(b) + 2
var quote byte
var escapedQuote []byte
if doubles > singles {
n += singles * 4
quote = '\''
escapedQuote = singleQuoteEntityBytes
} else {
n += doubles * 4
quote = '"'
escapedQuote = doubleQuoteEntityBytes
}
if n > cap(*buf) {
*buf = make([]byte, 0, n) // maximum size, not actual size
}
t := (*buf)[:n] // maximum size, not actual size
t[0] = quote
j := 1
start := 0
for i, c := range b {
if c == quote {
j += copy(t[j:], b[start:i])
j += copy(t[j:], escapedQuote)
start = i + 1
}
}
j += copy(t[j:], b[start:])
t[j] = quote
return t[:j+1]
}
// EscapeCDATAVal returns the escaped text bytes.
func EscapeCDATAVal(buf *[]byte, b []byte) ([]byte, bool) {
n := 0
for _, c := range b {
if c == '<' || c == '&' {
if c == '<' {
n += 3 // <
} else {
n += 4 // &
}
if n > len("<![CDATA[]]>") {
return b, false
}
}
}
if len(b)+n > cap(*buf) {
*buf = make([]byte, 0, len(b)+n)
}
t := (*buf)[:len(b)+n]
j := 0
start := 0
for i, c := range b {
if c == '<' {
j += copy(t[j:], b[start:i])
j += copy(t[j:], ltEntityBytes)
start = i + 1
} else if c == '&' {
j += copy(t[j:], b[start:i])
j += copy(t[j:], ampEntityBytes)
start = i + 1
}
}
j += copy(t[j:], b[start:])
return t[:j], true
}
|