@ -802,7 +802,7 @@ type equalMultiStringMapMatcher struct {
func ( m * equalMultiStringMapMatcher ) add ( s string ) {
if ! m . caseSensitive {
s = toNormalisedLower ( s )
s = toNormalisedLower ( s , nil ) // Don't pass a stack buffer here - it will always escape to heap.
}
m . values [ s ] = struct { } { }
@ -840,15 +840,24 @@ func (m *equalMultiStringMapMatcher) setMatches() []string {
}
func ( m * equalMultiStringMapMatcher ) Matches ( s string ) bool {
if ! m . caseSensitive {
s = toNormalisedLower ( s )
if len ( m . values ) > 0 {
sNorm := s
var a [ 32 ] byte
if ! m . caseSensitive {
sNorm = toNormalisedLower ( s , a [ : ] )
}
if _ , ok := m . values [ sNorm ] ; ok {
return true
}
}
if _ , ok := m . values [ s ] ; ok {
return true
}
if m . minPrefixLen > 0 && len ( s ) >= m . minPrefixLen {
for _ , matcher := range m . prefixes [ s [ : m . minPrefixLen ] ] {
prefix := s [ : m . minPrefixLen ]
var a [ 32 ] byte
if ! m . caseSensitive {
prefix = toNormalisedLower ( s [ : m . minPrefixLen ] , a [ : ] )
}
for _ , matcher := range m . prefixes [ prefix ] {
if matcher . Matches ( s ) {
return true
}
@ -859,22 +868,37 @@ func (m *equalMultiStringMapMatcher) Matches(s string) bool {
// toNormalisedLower normalise the input string using "Unicode Normalization Form D" and then convert
// it to lower case.
func toNormalisedLower ( s string ) string {
var buf [ ] byte
func toNormalisedLower ( s string , a [ ] byte ) string {
for i := 0 ; i < len ( s ) ; i ++ {
c := s [ i ]
if c >= utf8 . RuneSelf {
return strings . Map ( unicode . ToLower , norm . NFKD . String ( s ) )
}
if 'A' <= c && c <= 'Z' {
if buf == nil {
buf = [ ] byte ( s )
}
buf [ i ] = c + 'a' - 'A'
return toNormalisedLowerSlow ( s , i , a )
}
}
if buf == nil {
return s
return s
}
// toNormalisedLowerSlow is split from toNormalisedLower because having a call
// to `copy` slows it down even when it is not called.
func toNormalisedLowerSlow ( s string , i int , a [ ] byte ) string {
var buf [ ] byte
if cap ( a ) > len ( s ) {
buf = a [ : len ( s ) ]
copy ( buf , s )
} else {
buf = [ ] byte ( s )
}
for ; i < len ( s ) ; i ++ {
c := s [ i ]
if c >= utf8 . RuneSelf {
return strings . Map ( unicode . ToLower , norm . NFKD . String ( s ) )
}
if 'A' <= c && c <= 'Z' {
buf [ i ] = c + 'a' - 'A'
}
}
return yoloString ( buf )
}