aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/tdewolff/parse/xml/util.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/tdewolff/parse/xml/util.go')
-rw-r--r--vendor/github.com/tdewolff/parse/xml/util.go108
1 files changed, 108 insertions, 0 deletions
diff --git a/vendor/github.com/tdewolff/parse/xml/util.go b/vendor/github.com/tdewolff/parse/xml/util.go
new file mode 100644
index 0000000..1501b9b
--- /dev/null
+++ b/vendor/github.com/tdewolff/parse/xml/util.go
@@ -0,0 +1,108 @@
+package xml // import "github.com/tdewolff/parse/xml"
+
+import "github.com/tdewolff/parse"
+
+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 i, c := range b {
+ if c == '&' {
+ if quote, n := parse.QuoteEntity(b[i:]); n > 0 {
+ if quote == '"' {
+ doubles++
+ } else {
+ singles++
+ }
+ }
+ } else 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 == '&' {
+ if entityQuote, n := parse.QuoteEntity(b[i:]); n > 0 {
+ j += copy(t[j:], b[start:i])
+ if entityQuote != quote {
+ t[j] = entityQuote
+ j++
+ } else {
+ j += copy(t[j:], escapedQuote)
+ }
+ start = i + n
+ }
+ } else 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 // &lt;
+ } else {
+ n += 4 // &amp;
+ }
+ 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
+}