reduce copying for lists

This commit is contained in:
Russ Ross 2011-06-25 15:02:46 -06:00
parent cf97fbd897
commit eff64c563f
4 changed files with 48 additions and 34 deletions

View File

@ -882,20 +882,22 @@ func blockOliPrefix(data []byte) int {
// parse ordered or unordered list block // parse ordered or unordered list block
func blockList(out *bytes.Buffer, rndr *render, data []byte, flags int) int { func blockList(out *bytes.Buffer, rndr *render, data []byte, flags int) int {
var work bytes.Buffer i := 0
work := func() bool {
i, j := 0, 0 j := 0
for i < len(data) { for i < len(data) {
j = blockListItem(&work, rndr, data[i:], &flags) j = blockListItem(out, rndr, data[i:], &flags)
i += j i += j
if j == 0 || flags&LIST_ITEM_END_OF_LIST != 0 { if j == 0 || flags&LIST_ITEM_END_OF_LIST != 0 {
break break
} }
} }
return true
}
if rndr.mk.List != nil { if rndr.mk.List != nil {
rndr.mk.List(out, work.Bytes(), flags, rndr.mk.Opaque) rndr.mk.List(out, work, flags, rndr.mk.Opaque)
} }
return i return i
} }

50
html.go
View File

@ -123,39 +123,42 @@ func HtmlTocRenderer(flags int) *Renderer {
func attrEscape(out *bytes.Buffer, src []byte) { func attrEscape(out *bytes.Buffer, src []byte) {
org := 0 org := 0
for i, ch := range src { for i, ch := range src {
// doing this check is a bit faster than falling into // using if statements is a bit faster than a switch statement.
// the switch statement. as the compiler improves, this // as the compiler improves, this should be unnecessary
// should be unnecessary // this is only worthwhile because attrEscape is the single
if ch != '"' && ch != '&' && ch != '<' && ch != '>' { // largest CPU user in normal use
continue if ch == '"' {
}
switch ch {
case '<':
if i > org { if i > org {
// copy all the normal characters since the last escape // copy all the normal characters since the last escape
out.Write(src[org:i]) out.Write(src[org:i])
} }
org = i + 1 org = i + 1
out.WriteString("&lt;") out.WriteString("&quot;")
case '>': continue
if i > org {
out.Write(src[org:i])
} }
org = i + 1 if ch == '&' {
out.WriteString("&gt;")
case '&':
if i > org { if i > org {
out.Write(src[org:i]) out.Write(src[org:i])
} }
org = i + 1 org = i + 1
out.WriteString("&amp;") out.WriteString("&amp;")
case '"': continue
}
if ch == '<' {
if i > org { if i > org {
out.Write(src[org:i]) out.Write(src[org:i])
} }
org = i + 1 org = i + 1
out.WriteString("&quot;") out.WriteString("&lt;")
continue
}
if ch == '>' {
if i > org {
out.Write(src[org:i])
}
org = i + 1
out.WriteString("&gt;")
continue
} }
} }
if org < len(src) { if org < len(src) {
@ -351,8 +354,10 @@ func htmlTableCell(out *bytes.Buffer, text []byte, align int, opaque interface{}
out.WriteString("</td>") out.WriteString("</td>")
} }
func htmlList(out *bytes.Buffer, text []byte, flags int, opaque interface{}) { func htmlList(out *bytes.Buffer, text func() bool, flags int, opaque interface{}) {
if out.Len() > 0 { marker := out.Len()
if marker > 0 {
out.WriteByte('\n') out.WriteByte('\n')
} }
if flags&LIST_TYPE_ORDERED != 0 { if flags&LIST_TYPE_ORDERED != 0 {
@ -360,7 +365,10 @@ func htmlList(out *bytes.Buffer, text []byte, flags int, opaque interface{}) {
} else { } else {
out.WriteString("<ul>\n") out.WriteString("<ul>\n")
} }
out.Write(text) if !text() {
out.Truncate(marker)
return
}
if flags&LIST_TYPE_ORDERED != 0 { if flags&LIST_TYPE_ORDERED != 0 {
out.WriteString("</ol>\n") out.WriteString("</ol>\n")
} else { } else {

View File

@ -104,13 +104,17 @@ func latexHRule(out *bytes.Buffer, opaque interface{}) {
out.WriteString("\n\\HRule\n") out.WriteString("\n\\HRule\n")
} }
func latexList(out *bytes.Buffer, text []byte, flags int, opaque interface{}) { func latexList(out *bytes.Buffer, text func() bool, flags int, opaque interface{}) {
marker := out.Len()
if flags&LIST_TYPE_ORDERED != 0 { if flags&LIST_TYPE_ORDERED != 0 {
out.WriteString("\n\\begin{enumerate}\n") out.WriteString("\n\\begin{enumerate}\n")
} else { } else {
out.WriteString("\n\\begin{itemize}\n") out.WriteString("\n\\begin{itemize}\n")
} }
out.Write(text) if !text() {
out.Truncate(marker)
return
}
if flags&LIST_TYPE_ORDERED != 0 { if flags&LIST_TYPE_ORDERED != 0 {
out.WriteString("\n\\end{enumerate}\n") out.WriteString("\n\\end{enumerate}\n")
} else { } else {

View File

@ -101,7 +101,7 @@ type Renderer struct {
BlockHtml func(out *bytes.Buffer, text []byte, opaque interface{}) BlockHtml func(out *bytes.Buffer, text []byte, opaque interface{})
Header func(out *bytes.Buffer, text func() bool, level int, opaque interface{}) Header func(out *bytes.Buffer, text func() bool, level int, opaque interface{})
HRule func(out *bytes.Buffer, opaque interface{}) HRule func(out *bytes.Buffer, opaque interface{})
List func(out *bytes.Buffer, text []byte, flags int, opaque interface{}) List func(out *bytes.Buffer, text func() bool, flags int, opaque interface{})
ListItem func(out *bytes.Buffer, text []byte, flags int, opaque interface{}) ListItem func(out *bytes.Buffer, text []byte, flags int, opaque interface{})
Paragraph func(out *bytes.Buffer, text []byte, opaque interface{}) Paragraph func(out *bytes.Buffer, text []byte, opaque interface{})
Table func(out *bytes.Buffer, header []byte, body []byte, columnData []int, opaque interface{}) Table func(out *bytes.Buffer, header []byte, body []byte, columnData []int, opaque interface{})