зеркало из https://github.com/golang/dep.git
52 строки
1.3 KiB
Go
52 строки
1.3 KiB
Go
// Copyright 2017 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package gps
|
|
|
|
import (
|
|
"bytes"
|
|
"unicode"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// toFold returns a string with the property that strings.EqualFold(s, t) iff
|
|
// ToFold(s) == ToFold(t) This lets us test a large set of strings for
|
|
// fold-equivalent duplicates without making a quadratic number of calls to
|
|
// EqualFold. Note that strings.ToUpper and strings.ToLower do not have the
|
|
// desired property in some corner cases.
|
|
//
|
|
// This is hoisted from toolchain internals: src/cmd/go/internal/str/str.go
|
|
func toFold(s string) string {
|
|
// Fast path: all ASCII, no upper case.
|
|
// Most paths look like this already.
|
|
for i := 0; i < len(s); i++ {
|
|
c := s[i]
|
|
if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' {
|
|
goto Slow
|
|
}
|
|
}
|
|
return s
|
|
|
|
Slow:
|
|
var buf bytes.Buffer
|
|
for _, r := range s {
|
|
// SimpleFold(x) cycles to the next equivalent rune > x
|
|
// or wraps around to smaller values. Iterate until it wraps,
|
|
// and we've found the minimum value.
|
|
for {
|
|
r0 := r
|
|
r = unicode.SimpleFold(r0)
|
|
if r <= r0 {
|
|
break
|
|
}
|
|
}
|
|
// Exception to allow fast path above: A-Z => a-z
|
|
if 'A' <= r && r <= 'Z' {
|
|
r += 'a' - 'A'
|
|
}
|
|
buf.WriteRune(r)
|
|
}
|
|
return buf.String()
|
|
}
|