mirror of
https://github.com/sbrow/thor.git
synced 2026-08-26 11:23:32 -04:00
perf: Replaced a bunch of string array concats with strings.Builders.
This commit is contained in:
+7
-10
@@ -21,37 +21,34 @@ ALERT_EMOJIS: map[string]string = {
|
||||
}
|
||||
|
||||
inject_alerts :: proc(html: string) -> string {
|
||||
parts: [dynamic]string
|
||||
defer delete(parts)
|
||||
sb := strings.builder_make()
|
||||
defer strings.builder_destroy(&sb)
|
||||
|
||||
remaining := html
|
||||
|
||||
for {
|
||||
bq_start := strings.index(remaining, "<blockquote>")
|
||||
if bq_start < 0 {
|
||||
append(&parts, remaining)
|
||||
strings.write_string(&sb, remaining)
|
||||
break
|
||||
}
|
||||
|
||||
bq_close := strings.index(remaining, "</blockquote>")
|
||||
if bq_close < 0 {
|
||||
append(&parts, remaining)
|
||||
strings.write_string(&sb, remaining)
|
||||
break
|
||||
}
|
||||
|
||||
bq_end := bq_close + len("</blockquote>")
|
||||
bq := remaining[bq_start:bq_end]
|
||||
|
||||
// Append text before this blockquote
|
||||
append(&parts, remaining[:bq_start])
|
||||
|
||||
// Transform if it's an alert, otherwise keep as-is
|
||||
append(&parts, transform_alert(bq))
|
||||
strings.write_string(&sb, remaining[:bq_start])
|
||||
strings.write_string(&sb, transform_alert(bq))
|
||||
|
||||
remaining = remaining[bq_end:]
|
||||
}
|
||||
|
||||
return strings.join(parts[:], "")
|
||||
return strings.to_string(sb)
|
||||
}
|
||||
|
||||
transform_alert :: proc(bq: string) -> string {
|
||||
|
||||
+9
-13
@@ -384,30 +384,27 @@ expand_emoji :: proc(text: string) -> string {
|
||||
return text
|
||||
}
|
||||
|
||||
parts: [dynamic]string
|
||||
defer delete(parts)
|
||||
sb := strings.builder_make()
|
||||
defer strings.builder_destroy(&sb)
|
||||
|
||||
remaining := text
|
||||
|
||||
for {
|
||||
colon := strings.index(remaining, ":")
|
||||
if colon < 0 {
|
||||
append(&parts, remaining)
|
||||
strings.write_string(&sb, remaining)
|
||||
break
|
||||
}
|
||||
|
||||
// Find the closing colon
|
||||
after := remaining[colon + 1:]
|
||||
end := strings.index(after, ":")
|
||||
if end < 0 {
|
||||
append(&parts, remaining)
|
||||
strings.write_string(&sb, remaining)
|
||||
break
|
||||
}
|
||||
|
||||
shortcode := remaining[colon + 1 : colon + 1 + end]
|
||||
|
||||
// Validate: shortcode must be all lowercase letters, digits, or underscores
|
||||
// and must not contain whitespace
|
||||
valid := true
|
||||
for c in shortcode {
|
||||
if !(c >= 'a' && c <= 'z') && !(c >= '0' && c <= '9') && c != '_' && c != '+' && c != '-' {
|
||||
@@ -416,23 +413,22 @@ expand_emoji :: proc(text: string) -> string {
|
||||
}
|
||||
}
|
||||
if !valid || len(shortcode) == 0 {
|
||||
append(&parts, remaining[:colon + 1])
|
||||
strings.write_string(&sb, remaining[:colon + 1])
|
||||
remaining = remaining[colon + 1:]
|
||||
continue
|
||||
}
|
||||
|
||||
emoji, found := EMOJIS[shortcode]
|
||||
if !found {
|
||||
append(&parts, remaining[:colon + 1])
|
||||
strings.write_string(&sb, remaining[:colon + 1])
|
||||
remaining = remaining[colon + 1:]
|
||||
continue
|
||||
}
|
||||
|
||||
// Replace :shortcode: with emoji
|
||||
append(&parts, remaining[:colon])
|
||||
append(&parts, emoji)
|
||||
strings.write_string(&sb, remaining[:colon])
|
||||
strings.write_string(&sb, emoji)
|
||||
remaining = remaining[colon + 1 + end + 1:]
|
||||
}
|
||||
|
||||
return strings.join(parts[:], "")
|
||||
return strings.to_string(sb)
|
||||
}
|
||||
|
||||
+18
-15
@@ -20,11 +20,11 @@ strip_definitions :: proc(
|
||||
clean_body: string,
|
||||
sn_defs, mn_defs: map[string]string,
|
||||
) {
|
||||
// TODO: Should this be temp allocated?
|
||||
lines := strings.split(body, "\n")
|
||||
defer delete(lines)
|
||||
output_lines: [dynamic]string
|
||||
defer delete(output_lines)
|
||||
|
||||
out_sb := strings.builder_make()
|
||||
defer strings.builder_destroy(&out_sb)
|
||||
|
||||
i := 0
|
||||
for i < len(lines) {
|
||||
@@ -32,48 +32,51 @@ strip_definitions :: proc(
|
||||
|
||||
id, def_text, kind, is_def := parse_def_line(line)
|
||||
if !is_def {
|
||||
append(&output_lines, line)
|
||||
if strings.builder_len(out_sb) > 0 {
|
||||
strings.write_string(&out_sb, "\n")
|
||||
}
|
||||
strings.write_string(&out_sb, line)
|
||||
i += 1
|
||||
continue
|
||||
}
|
||||
|
||||
// Collect definition text (initial line + multi-line continuations)
|
||||
def_parts: [dynamic]string
|
||||
def_sb := strings.builder_make()
|
||||
if def_text != "" {
|
||||
append(&def_parts, def_text)
|
||||
strings.write_string(&def_sb, def_text)
|
||||
}
|
||||
|
||||
i += 1
|
||||
for i < len(lines) {
|
||||
next := lines[i]
|
||||
// Stop at blank lines
|
||||
if len(next) == 0 {
|
||||
break
|
||||
}
|
||||
// Stop at new note definitions
|
||||
_, _, _, is_new_def := parse_def_line(next)
|
||||
if is_new_def {
|
||||
break
|
||||
}
|
||||
// Include as continuation (trim indented lines)
|
||||
if strings.builder_len(def_sb) > 0 {
|
||||
strings.write_string(&def_sb, "\n")
|
||||
}
|
||||
if is_indented(next) {
|
||||
append(&def_parts, strings.trim_left(next, " \t"))
|
||||
strings.write_string(&def_sb, strings.trim_left(next, " \t"))
|
||||
} else {
|
||||
append(&def_parts, next)
|
||||
strings.write_string(&def_sb, next)
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
|
||||
joined := strings.join(def_parts[:], "\n")
|
||||
joined := strings.clone(strings.to_string(def_sb))
|
||||
strings.builder_destroy(&def_sb)
|
||||
|
||||
if kind == .Marginnote {
|
||||
mn_defs[id] = joined
|
||||
} else {
|
||||
sn_defs[id] = joined
|
||||
}
|
||||
delete(def_parts)
|
||||
}
|
||||
|
||||
clean_body = strings.join(output_lines[:], "\n")
|
||||
clean_body = strings.clone(strings.to_string(out_sb))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+33
-28
@@ -244,37 +244,39 @@ capture_name_to_css :: proc(name: string) -> string {
|
||||
}
|
||||
|
||||
escape_html :: proc(s: string) -> string {
|
||||
parts: [dynamic]string
|
||||
defer delete(parts)
|
||||
sb := strings.builder_make()
|
||||
defer strings.builder_destroy(&sb)
|
||||
|
||||
start := 0
|
||||
for i in 0..<len(s) {
|
||||
switch s[i] {
|
||||
case '&':
|
||||
if i > start do append(&parts, s[start:i])
|
||||
append(&parts, "&")
|
||||
if i > start do strings.write_string(&sb, s[start:i])
|
||||
strings.write_string(&sb, "&")
|
||||
start = i + 1
|
||||
case '<':
|
||||
if i > start do append(&parts, s[start:i])
|
||||
append(&parts, "<")
|
||||
if i > start do strings.write_string(&sb, s[start:i])
|
||||
strings.write_string(&sb, "<")
|
||||
start = i + 1
|
||||
case '>':
|
||||
if i > start do append(&parts, s[start:i])
|
||||
append(&parts, ">")
|
||||
if i > start do strings.write_string(&sb, s[start:i])
|
||||
strings.write_string(&sb, ">")
|
||||
start = i + 1
|
||||
case '"':
|
||||
if i > start do append(&parts, s[start:i])
|
||||
append(&parts, """)
|
||||
if i > start do strings.write_string(&sb, s[start:i])
|
||||
strings.write_string(&sb, """)
|
||||
start = i + 1
|
||||
}
|
||||
}
|
||||
if start < len(s) do append(&parts, s[start:])
|
||||
if len(parts) == 0 do return s
|
||||
return strings.join(parts[:], "")
|
||||
if start == 0 do return s
|
||||
if start < len(s) do strings.write_string(&sb, s[start:])
|
||||
return strings.to_string(sb)
|
||||
}
|
||||
|
||||
unescape_html :: proc(s: string) -> string {
|
||||
parts: [dynamic]string
|
||||
defer delete(parts)
|
||||
sb := strings.builder_make()
|
||||
defer strings.builder_destroy(&sb)
|
||||
|
||||
start := 0
|
||||
for i in 0..<len(s) {
|
||||
if s[i] != '&' do continue
|
||||
@@ -290,13 +292,13 @@ unescape_html :: proc(s: string) -> string {
|
||||
case "'", "'": replacement = "'"
|
||||
case: continue
|
||||
}
|
||||
if i > start do append(&parts, s[start:i])
|
||||
append(&parts, replacement)
|
||||
if i > start do strings.write_string(&sb, s[start:i])
|
||||
strings.write_string(&sb, replacement)
|
||||
start = i + semi + 1
|
||||
}
|
||||
if start < len(s) do append(&parts, s[start:])
|
||||
if len(parts) == 0 do return s
|
||||
return strings.join(parts[:], "")
|
||||
if start == 0 do return s
|
||||
if start < len(s) do strings.write_string(&sb, s[start:])
|
||||
return strings.to_string(sb)
|
||||
}
|
||||
|
||||
highlight_block :: proc(code: string, lang: string, file_path: string) -> string {
|
||||
@@ -416,19 +418,22 @@ highlight_code :: proc(html: string, file_path: string) -> string {
|
||||
PREFIX :: `<pre><code class="language-`
|
||||
CODE_END :: `</code></pre>`
|
||||
|
||||
parts: [dynamic]string
|
||||
defer delete(parts)
|
||||
sb := strings.builder_make()
|
||||
defer strings.builder_destroy(&sb)
|
||||
|
||||
pos := 0
|
||||
found := false
|
||||
|
||||
for {
|
||||
rel := strings.index(html[pos:], PREFIX)
|
||||
if rel < 0 {
|
||||
break
|
||||
}
|
||||
found = true
|
||||
idx := pos + rel
|
||||
|
||||
if idx > pos {
|
||||
append(&parts, html[pos:idx])
|
||||
strings.write_string(&sb, html[pos:idx])
|
||||
}
|
||||
|
||||
lang_start := idx + len(PREFIX)
|
||||
@@ -455,17 +460,17 @@ highlight_code :: proc(html: string, file_path: string) -> string {
|
||||
|
||||
code := html[code_start:end_idx]
|
||||
highlighted := highlight_block(code, lang, file_path)
|
||||
append(&parts, fmt.tprintf(`<pre><code class="language-%s">%s</code></pre>`, lang, highlighted))
|
||||
strings.write_string(&sb, fmt.tprintf(`<pre><code class="language-%s">%s</code></pre>`, lang, highlighted))
|
||||
|
||||
pos = end_idx + len(CODE_END)
|
||||
}
|
||||
|
||||
if pos < len(html) {
|
||||
append(&parts, html[pos:])
|
||||
if pos < len(html) && found {
|
||||
strings.write_string(&sb, html[pos:])
|
||||
}
|
||||
|
||||
if len(parts) == 0 {
|
||||
if !found {
|
||||
return html
|
||||
}
|
||||
return strings.join(parts[:], "")
|
||||
return strings.to_string(sb)
|
||||
}
|
||||
|
||||
+9
-8
@@ -70,14 +70,15 @@ Posts_Data :: struct {
|
||||
}
|
||||
|
||||
strip_html_tags :: proc(s: string) -> string {
|
||||
parts: [dynamic]string
|
||||
defer delete(parts)
|
||||
sb := strings.builder_make()
|
||||
defer strings.builder_destroy(&sb)
|
||||
|
||||
in_tag := false
|
||||
start := 0
|
||||
for i in 0 ..< len(s) {
|
||||
if s[i] == '<' && !in_tag {
|
||||
if i > start {
|
||||
append(&parts, s[start:i])
|
||||
strings.write_string(&sb, s[start:i])
|
||||
}
|
||||
in_tag = true
|
||||
} else if s[i] == '>' && in_tag {
|
||||
@@ -85,13 +86,13 @@ strip_html_tags :: proc(s: string) -> string {
|
||||
start = i + 1
|
||||
}
|
||||
}
|
||||
if !in_tag && start < len(s) {
|
||||
append(&parts, s[start:])
|
||||
}
|
||||
if len(parts) == 0 {
|
||||
if start == 0 {
|
||||
return s
|
||||
}
|
||||
return strings.join(parts[:], "")
|
||||
if !in_tag && start < len(s) {
|
||||
strings.write_string(&sb, s[start:])
|
||||
}
|
||||
return strings.to_string(sb)
|
||||
}
|
||||
|
||||
og_type :: proc(is_article: bool) -> string {
|
||||
|
||||
+14
-10
@@ -5,10 +5,12 @@ import "core:strings"
|
||||
wrap_sections :: proc(html: string) -> string {
|
||||
H2 :: "<h2"
|
||||
|
||||
parts: [dynamic]string
|
||||
defer delete(parts)
|
||||
sb := strings.builder_make()
|
||||
defer strings.builder_destroy(&sb)
|
||||
|
||||
pos := 0
|
||||
search_pos := 0
|
||||
found := false
|
||||
|
||||
for {
|
||||
rel := strings.index(html[search_pos:], H2)
|
||||
@@ -16,11 +18,12 @@ wrap_sections :: proc(html: string) -> string {
|
||||
break
|
||||
}
|
||||
idx := search_pos + rel
|
||||
found = true
|
||||
|
||||
if idx > pos {
|
||||
append(&parts, "<section>")
|
||||
append(&parts, html[pos:idx])
|
||||
append(&parts, "</section>")
|
||||
strings.write_string(&sb, "<section>")
|
||||
strings.write_string(&sb, html[pos:idx])
|
||||
strings.write_string(&sb, "</section>")
|
||||
}
|
||||
|
||||
pos = idx
|
||||
@@ -28,13 +31,14 @@ wrap_sections :: proc(html: string) -> string {
|
||||
}
|
||||
|
||||
if pos < len(html) {
|
||||
append(&parts, "<section>")
|
||||
append(&parts, html[pos:])
|
||||
append(&parts, "</section>")
|
||||
strings.write_string(&sb, "<section>")
|
||||
strings.write_string(&sb, html[pos:])
|
||||
strings.write_string(&sb, "</section>")
|
||||
found = true
|
||||
}
|
||||
|
||||
if len(parts) == 0 {
|
||||
if !found {
|
||||
return html
|
||||
}
|
||||
return strings.join(parts[:], "")
|
||||
return strings.to_string(sb)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user