From 66d3599cbab80aea966030ee07d2ca22355c957d Mon Sep 17 00:00:00 2001 From: Alexander Yastrebov Date: Tue, 11 Feb 2025 14:38:55 +0100 Subject: [PATCH] predicates/forwarded: use strings.Cut to parse header Use strings.Cut instead of strings.Split to reduce memory allocations. See #3403 for details. Signed-off-by: Alexander Yastrebov --- predicates/forwarded/forwarded.go | 37 +++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/predicates/forwarded/forwarded.go b/predicates/forwarded/forwarded.go index 6c1489c340..d2810a5ba8 100644 --- a/predicates/forwarded/forwarded.go +++ b/predicates/forwarded/forwarded.go @@ -133,8 +133,18 @@ func parseForwarded(fh string) *forwarded { f := &forwarded{} - for _, forwardedFull := range strings.Split(fh, ",") { - for _, forwardedPair := range strings.Split(strings.TrimSpace(forwardedFull), ";") { + // TODO: use range over func added in go1.23 like: + // for forwardedFull := range split(fh, ",") { + // for forwardedPair := range split(strings.TrimSpace(forwardedFull), ";") { + // // ... + // } + // } + // once go1.24 is released + // + // Also use strings.SplitSeq added in go1.24 once go1.25 is released. + + split(fh, ",")(func(forwardedFull string) bool { + split(strings.TrimSpace(forwardedFull), ";")(func(forwardedPair string) bool { token, value, found := strings.Cut(forwardedPair, "=") value = strings.Trim(value, `"`) if found && value != "" { @@ -145,8 +155,27 @@ func parseForwarded(fh string) *forwarded { f.host = value } } - } - } + return true + }) + return true + }) return f } + +func split(s string, sep string) func(yield func(string) bool) { + return func(yield func(string) bool) { + for { + i := strings.Index(s, sep) + if i < 0 { + break + } + frag := s[:i] + if !yield(frag) { + return + } + s = s[i+len(sep):] + } + yield(s) + } +}