performance fix: with autolinking on, it is almost twice as fast now

pull/2/head
Russ Ross 2011-05-30 15:36:31 -06:00
parent 4a17a5b58f
commit 679e1686db
3 changed files with 28 additions and 19 deletions

View File

@ -427,9 +427,12 @@ func htmlAutolink(out *bytes.Buffer, link []byte, kind int, opaque interface{})
* an actual URI, e.g. `mailto:foo@bar.com`, we don't * an actual URI, e.g. `mailto:foo@bar.com`, we don't
* want to print the `mailto:` prefix * want to print the `mailto:` prefix
*/ */
if bytes.HasPrefix(link, []byte("mailto:")) { switch {
case bytes.HasPrefix(link, []byte("mailto://")):
attrEscape(out, link[9:])
case bytes.HasPrefix(link, []byte("mailto:")):
attrEscape(out, link[7:]) attrEscape(out, link[7:])
} else { default:
attrEscape(out, link) attrEscape(out, link)
} }

View File

@ -536,14 +536,22 @@ func inlineEntity(out *bytes.Buffer, rndr *render, data []byte, offset int) int
} }
func inlineAutolink(out *bytes.Buffer, rndr *render, data []byte, offset int) int { func inlineAutolink(out *bytes.Buffer, rndr *render, data []byte, offset int) int {
orig_data := data // quick check to rule out most false hits on ':'
data = data[offset:] if len(data) < offset + 3 || data[offset+1] != '/' || data[offset+2] != '/' {
return 0
}
if offset > 0 { // scan backward for a word boundary
if !isspace(orig_data[offset-1]) && !ispunct(orig_data[offset-1]) { rewind := 0
return 0 for offset - rewind > 0 && rewind <= 7 && !isspace(data[offset-rewind-1]) && !isspace(data[offset-rewind-1]) {
} rewind++
} }
if rewind > 6 { // longest supported protocol is "mailto" which has 6 letters
return 0
}
orig_data := data
data = data[offset-rewind:]
if !isSafeLink(data) { if !isSafeLink(data) {
return 0 return 0
@ -577,7 +585,7 @@ func inlineAutolink(out *bytes.Buffer, rndr *render, data []byte, offset int) in
} }
if copen != 0 { if copen != 0 {
buf_end := offset + link_end - 2 buf_end := offset - rewind + link_end - 2
open_delim := 1 open_delim := 1
@ -618,6 +626,11 @@ func inlineAutolink(out *bytes.Buffer, rndr *render, data []byte, offset int) in
} }
} }
// we were triggered on the ':', so we need to rewind the output a bit
if out.Len() >= rewind {
out.Truncate(len(out.Bytes()) - rewind)
}
if rndr.mk.autolink != nil { if rndr.mk.autolink != nil {
u_link := bytes.NewBuffer(nil) u_link := bytes.NewBuffer(nil)
unescapeText(u_link, data[:link_end]) unescapeText(u_link, data[:link_end])
@ -625,7 +638,7 @@ func inlineAutolink(out *bytes.Buffer, rndr *render, data []byte, offset int) in
rndr.mk.autolink(out, u_link.Bytes(), LINK_TYPE_NORMAL, rndr.mk.opaque) rndr.mk.autolink(out, u_link.Bytes(), LINK_TYPE_NORMAL, rndr.mk.opaque)
} }
return link_end return link_end - rewind
} }
var validUris = [][]byte{[]byte("http://"), []byte("https://"), []byte("ftp://"), []byte("mailto://")} var validUris = [][]byte{[]byte("http://"), []byte("https://"), []byte("ftp://"), []byte("mailto://")}

View File

@ -187,14 +187,7 @@ func Markdown(input []byte, renderer *Renderer, extensions uint32) []byte {
rndr.inline['&'] = inlineEntity rndr.inline['&'] = inlineEntity
if extensions&EXTENSION_AUTOLINK != 0 { if extensions&EXTENSION_AUTOLINK != 0 {
rndr.inline['h'] = inlineAutolink // http, https rndr.inline[':'] = inlineAutolink
rndr.inline['H'] = inlineAutolink
rndr.inline['f'] = inlineAutolink // ftp
rndr.inline['F'] = inlineAutolink
rndr.inline['m'] = inlineAutolink // mailto
rndr.inline['M'] = inlineAutolink
} }
// first pass: look for references, copy everything else // first pass: look for references, copy everything else