From f4095c73c49d7b47e0dd34e739ad8869fc05f4e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9?= Date: Thu, 4 Dec 2025 10:39:33 +0100 Subject: [PATCH 1/4] optimize TrimSpace --- byteseq.go | 32 ++++++-------------------------- common.go | 10 ---------- 2 files changed, 6 insertions(+), 36 deletions(-) diff --git a/byteseq.go b/byteseq.go index 583caab..076d9ee 100644 --- a/byteseq.go +++ b/byteseq.go @@ -92,35 +92,15 @@ func TrimRight[S byteSeq](s S, cutset byte) S { // This is an optimized version that's faster than strings/bytes.TrimSpace for ASCII strings. // It removes the following ASCII whitespace characters: space, tab, newline, carriage return, vertical tab, and form feed. func TrimSpace[S byteSeq](s S) S { - length := len(s) - - // Fast path for empty input - if length == 0 { - return s - } - - // Find first non-whitespace character - start := 0 - for start < length && whitespaceTable[s[start]] { - start++ - } - - // If all whitespace, return empty with zero capacity to match bytes.TrimSpace behavior - if start == length { - return s[length:length] - } + i, j := 0, len(s)-1 - // Find last non-whitespace character - end := length - 1 - for end > start && whitespaceTable[s[end]] { - end-- + // Find first non-whitespace from start + for ; i <= j && (s[i] == ' ' || s[i]-'\t' <= 4); i++ { } - // If no trimming needed, return original (no allocation) - if start == 0 && end == length-1 { - return s + // Find first non-whitespace from end + for ; i < j && (s[j] == ' ' || s[j]-'\t' <= 4); j-- { } - // Return trimmed substring/subslice - return s[start : end+1] + return s[i : j+1] } diff --git a/common.go b/common.go index 8a256c6..493b4c4 100644 --- a/common.go +++ b/common.go @@ -27,16 +27,6 @@ const ( toUpperTable = "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\u007f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" ) -// Lookup table for ASCII whitespace characters (true = whitespace, false = not whitespace) -var whitespaceTable = [256]bool{ - '\t': true, // 9 - horizontal tab - '\n': true, // 10 - line feed - '\v': true, // 11 - vertical tab - '\f': true, // 12 - form feed - '\r': true, // 13 - carriage return - ' ': true, // 32 - space -} - // Copyright © 2014, Roger Peppe // github.com/rogpeppe/fastuuid // All rights reserved. From 63e4e33eea118ce204a183b0d755cc038657da82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9?= Date: Thu, 4 Dec 2025 13:40:29 +0100 Subject: [PATCH 2/4] fix linting for TrimSpace --- byteseq.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/byteseq.go b/byteseq.go index 076d9ee..33a2040 100644 --- a/byteseq.go +++ b/byteseq.go @@ -95,11 +95,11 @@ func TrimSpace[S byteSeq](s S) S { i, j := 0, len(s)-1 // Find first non-whitespace from start - for ; i <= j && (s[i] == ' ' || s[i]-'\t' <= 4); i++ { + for ; i <= j && (s[i] == ' ' || s[i]-'\t' <= 4); i++ { //nolint:revive // we want to check for multiple whitespace chars } // Find first non-whitespace from end - for ; i < j && (s[j] == ' ' || s[j]-'\t' <= 4); j-- { + for ; i < j && (s[j] == ' ' || s[j]-'\t' <= 4); j-- { //nolint:revive // we want to check for multiple whitespace chars } return s[i : j+1] From c6c6b9ee428b6511313f753df5e9f096d104e723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9?= Date: Thu, 4 Dec 2025 13:50:38 +0100 Subject: [PATCH 3/4] optimize TrimSpace --- byteseq.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/byteseq.go b/byteseq.go index 33a2040..1136792 100644 --- a/byteseq.go +++ b/byteseq.go @@ -94,6 +94,11 @@ func TrimRight[S byteSeq](s S, cutset byte) S { func TrimSpace[S byteSeq](s S) S { i, j := 0, len(s)-1 + // fast path for empty string + if j < 0 { + return s + } + // Find first non-whitespace from start for ; i <= j && (s[i] == ' ' || s[i]-'\t' <= 4); i++ { //nolint:revive // we want to check for multiple whitespace chars } From be229ff57283b488ede08ec56da13deeff2a2e6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9?= Date: Thu, 4 Dec 2025 14:12:23 +0100 Subject: [PATCH 4/4] optimize TrimSpace --- byteseq.go | 4 ++-- common.go | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/byteseq.go b/byteseq.go index 1136792..99ce831 100644 --- a/byteseq.go +++ b/byteseq.go @@ -100,11 +100,11 @@ func TrimSpace[S byteSeq](s S) S { } // Find first non-whitespace from start - for ; i <= j && (s[i] == ' ' || s[i]-'\t' <= 4); i++ { //nolint:revive // we want to check for multiple whitespace chars + for ; i <= j && whitespaceTable[s[i]]; i++ { //nolint:revive // we want to check for multiple whitespace chars } // Find first non-whitespace from end - for ; i < j && (s[j] == ' ' || s[j]-'\t' <= 4); j-- { //nolint:revive // we want to check for multiple whitespace chars + for ; i < j && whitespaceTable[s[j]]; j-- { //nolint:revive // we want to check for multiple whitespace chars } return s[i : j+1] diff --git a/common.go b/common.go index 493b4c4..8a256c6 100644 --- a/common.go +++ b/common.go @@ -27,6 +27,16 @@ const ( toUpperTable = "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\u007f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" ) +// Lookup table for ASCII whitespace characters (true = whitespace, false = not whitespace) +var whitespaceTable = [256]bool{ + '\t': true, // 9 - horizontal tab + '\n': true, // 10 - line feed + '\v': true, // 11 - vertical tab + '\f': true, // 12 - form feed + '\r': true, // 13 - carriage return + ' ': true, // 32 - space +} + // Copyright © 2014, Roger Peppe // github.com/rogpeppe/fastuuid // All rights reserved.