diff options
| author | Paul Buetow <paul@buetow.org> | 2026-04-02 21:39:21 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-04-02 21:39:21 +0300 |
| commit | 9d258ee5ebe2773b477d553b62c0c67650a5a5cf (patch) | |
| tree | e8304fd1de54de69678a62345ec4fc4cd85cfb3d | |
| parent | 11a3e62f17433a7df0e6a77a688321d94a736778 (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.go | 15 | ||||
| -rw-r--r-- | internal/utils.go | 13 |
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 |
