aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/strings/strings.go
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2011-09-26 18:32:51 -0400
committerRuss Cox <rsc@golang.org>2011-09-26 18:32:51 -0400
commita8a18f6566dd4af3335a587d10cec77f6c5a3e90 (patch)
tree19e282d3578e0a57304a595801da4aeaefabb5cf /src/pkg/strings/strings.go
parent1fa87ada553ec8b9d4e520fe715faa3f9d391a5c (diff)
downloadgo-a8a18f6566dd4af3335a587d10cec77f6c5a3e90.tar.xz
strings: add EqualFold
Case-insensitive strcmp without using ToLower. (Using ToLower is not always correct, and it allocates.) R=golang-dev, r CC=golang-dev https://golang.org/cl/5143044
Diffstat (limited to 'src/pkg/strings/strings.go')
-rw-r--r--src/pkg/strings/strings.go54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/pkg/strings/strings.go b/src/pkg/strings/strings.go
index c547297e66..446fa3a0c8 100644
--- a/src/pkg/strings/strings.go
+++ b/src/pkg/strings/strings.go
@@ -583,3 +583,57 @@ func Replace(s, old, new string, n int) string {
w += copy(t[w:], s[start:])
return string(t[0:w])
}
+
+// EqualFold returns true if s and t are equal under Unicode case-folding.
+func EqualFold(s, t string) bool {
+ for s != "" && t != "" {
+ // Extract first rune from each string.
+ var sr, tr int
+ if s[0] < utf8.RuneSelf {
+ sr, s = int(s[0]), s[1:]
+ } else {
+ r, size := utf8.DecodeRuneInString(s)
+ sr, s = r, s[size:]
+ }
+ if t[0] < utf8.RuneSelf {
+ tr, t = int(t[0]), t[1:]
+ } else {
+ r, size := utf8.DecodeRuneInString(t)
+ tr, t = r, t[size:]
+ }
+
+ // If they match, keep going; if not, return false.
+
+ // Easy case.
+ if tr == sr {
+ continue
+ }
+
+ // Make sr < tr to simplify what follows.
+ if tr < sr {
+ tr, sr = sr, tr
+ }
+ // Fast check for ASCII.
+ if tr < utf8.RuneSelf && 'A' <= sr && sr <= 'Z' {
+ // ASCII, and sr is upper case. tr must be lower case.
+ if tr == sr+'a'-'A' {
+ continue
+ }
+ return false
+ }
+
+ // General case. SimpleFold(x) returns the next equivalent rune > x
+ // or wraps around to smaller values.
+ r := unicode.SimpleFold(sr)
+ for r != sr && r < tr {
+ r = unicode.SimpleFold(r)
+ }
+ if r == tr {
+ continue
+ }
+ return false
+ }
+
+ // One string is empty. Are both?
+ return s == t
+}