summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-02 21:39:21 +0300
committerPaul Buetow <paul@buetow.org>2026-04-02 21:39:21 +0300
commit9d258ee5ebe2773b477d553b62c0c67650a5a5cf (patch)
treee8304fd1de54de69678a62345ec4fc4cd85cfb3d
parent11a3e62f17433a7df0e6a77a688321d94a736778 (diff)
task 005: use strings.Builder for string concatenation in loops
Replace per-rune += string(r) heap allocations with strings.Builder in SanitizeFilename (internal/utils.go) and splitLines (internal/batch/processor.go). Both now call Grow/Reset appropriately to pre-allocate capacity. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-rw-r--r--internal/batch/processor.go15
-rw-r--r--internal/utils.go13
2 files changed, 16 insertions, 12 deletions
diff --git a/internal/batch/processor.go b/internal/batch/processor.go
index 6867c3c..314d67f 100644
--- a/internal/batch/processor.go
+++ b/internal/batch/processor.go
@@ -103,20 +103,21 @@ func parseBatchLine(line string) *WordEntry {
}
}
-// splitLines splits a string by newlines
+// splitLines splits a string by newlines, handling both \n and \r\n line endings.
+// Uses strings.Builder to avoid per-character heap allocations from += concatenation.
func splitLines(s string) []string {
var lines []string
- current := ""
+ var current strings.Builder
for _, r := range s {
if r == '\n' {
- lines = append(lines, current)
- current = ""
+ lines = append(lines, current.String())
+ current.Reset()
} else if r != '\r' {
- current += string(r)
+ current.WriteRune(r)
}
}
- if current != "" {
- lines = append(lines, current)
+ if current.Len() > 0 {
+ lines = append(lines, current.String())
}
return lines
}
diff --git a/internal/utils.go b/internal/utils.go
index 779b95a..c135f9b 100644
--- a/internal/utils.go
+++ b/internal/utils.go
@@ -4,6 +4,7 @@ import (
"crypto/md5"
"encoding/hex"
"fmt"
+ "strings"
"time"
)
@@ -22,17 +23,19 @@ func GenerateCardID(bulgarianWord string) string {
return fmt.Sprintf("%d_%s", epochMillis, hashStr)
}
-// SanitizeFilename creates a safe filename from a string
+// SanitizeFilename creates a safe filename from a string.
+// Uses strings.Builder to avoid per-rune heap allocations.
func SanitizeFilename(s string) string {
- result := ""
+ var b strings.Builder
+ b.Grow(len(s))
for _, r := range s {
if isAlphaNumeric(r) || r == '-' || r == '_' {
- result += string(r)
+ b.WriteRune(r)
} else {
- result += "_"
+ b.WriteByte('_')
}
}
- return result
+ return b.String()
}
// isAlphaNumeric checks if a rune is alphanumeric