...
Run Format

Source file src/strings/strings.go

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// Package strings implements simple functions to manipulate UTF-8 encoded strings.
     6	//
     7	// For information about UTF-8 strings in Go, see https://blog.golang.org/strings.
     8	package strings
     9	
    10	import (
    11		"unicode"
    12		"unicode/utf8"
    13	)
    14	
    15	// explode splits s into an array of UTF-8 sequences, one per Unicode character (still strings) up to a maximum of n (n < 0 means no limit).
    16	// Invalid UTF-8 sequences become correct encodings of U+FFF8.
    17	func explode(s string, n int) []string {
    18		if n == 0 {
    19			return nil
    20		}
    21		l := utf8.RuneCountInString(s)
    22		if n <= 0 || n > l {
    23			n = l
    24		}
    25		a := make([]string, n)
    26		var size int
    27		var ch rune
    28		i, cur := 0, 0
    29		for ; i+1 < n; i++ {
    30			ch, size = utf8.DecodeRuneInString(s[cur:])
    31			if ch == utf8.RuneError {
    32				a[i] = string(utf8.RuneError)
    33			} else {
    34				a[i] = s[cur : cur+size]
    35			}
    36			cur += size
    37		}
    38		// add the rest, if there is any
    39		if cur < len(s) {
    40			a[i] = s[cur:]
    41		}
    42		return a
    43	}
    44	
    45	// primeRK is the prime base used in Rabin-Karp algorithm.
    46	const primeRK = 16777619
    47	
    48	// hashStr returns the hash and the appropriate multiplicative
    49	// factor for use in Rabin-Karp algorithm.
    50	func hashStr(sep string) (uint32, uint32) {
    51		hash := uint32(0)
    52		for i := 0; i < len(sep); i++ {
    53			hash = hash*primeRK + uint32(sep[i])
    54		}
    55		var pow, sq uint32 = 1, primeRK
    56		for i := len(sep); i > 0; i >>= 1 {
    57			if i&1 != 0 {
    58				pow *= sq
    59			}
    60			sq *= sq
    61		}
    62		return hash, pow
    63	}
    64	
    65	// hashStrRev returns the hash of the reverse of sep and the
    66	// appropriate multiplicative factor for use in Rabin-Karp algorithm.
    67	func hashStrRev(sep string) (uint32, uint32) {
    68		hash := uint32(0)
    69		for i := len(sep) - 1; i >= 0; i-- {
    70			hash = hash*primeRK + uint32(sep[i])
    71		}
    72		var pow, sq uint32 = 1, primeRK
    73		for i := len(sep); i > 0; i >>= 1 {
    74			if i&1 != 0 {
    75				pow *= sq
    76			}
    77			sq *= sq
    78		}
    79		return hash, pow
    80	}
    81	
    82	// Count counts the number of non-overlapping instances of sep in s.
    83	// If sep is an empty string, Count returns 1 + the number of Unicode code points in s.
    84	func Count(s, sep string) int {
    85		n := 0
    86		// special cases
    87		switch {
    88		case len(sep) == 0:
    89			return utf8.RuneCountInString(s) + 1
    90		case len(sep) == 1:
    91			// special case worth making fast
    92			c := sep[0]
    93			for i := 0; i < len(s); i++ {
    94				if s[i] == c {
    95					n++
    96				}
    97			}
    98			return n
    99		case len(sep) > len(s):
   100			return 0
   101		case len(sep) == len(s):
   102			if sep == s {
   103				return 1
   104			}
   105			return 0
   106		}
   107		// Rabin-Karp search
   108		hashsep, pow := hashStr(sep)
   109		h := uint32(0)
   110		for i := 0; i < len(sep); i++ {
   111			h = h*primeRK + uint32(s[i])
   112		}
   113		lastmatch := 0
   114		if h == hashsep && s[:len(sep)] == sep {
   115			n++
   116			lastmatch = len(sep)
   117		}
   118		for i := len(sep); i < len(s); {
   119			h *= primeRK
   120			h += uint32(s[i])
   121			h -= pow * uint32(s[i-len(sep)])
   122			i++
   123			if h == hashsep && lastmatch <= i-len(sep) && s[i-len(sep):i] == sep {
   124				n++
   125				lastmatch = i
   126			}
   127		}
   128		return n
   129	}
   130	
   131	// Contains reports whether substr is within s.
   132	func Contains(s, substr string) bool {
   133		return Index(s, substr) >= 0
   134	}
   135	
   136	// ContainsAny reports whether any Unicode code points in chars are within s.
   137	func ContainsAny(s, chars string) bool {
   138		return IndexAny(s, chars) >= 0
   139	}
   140	
   141	// ContainsRune reports whether the Unicode code point r is within s.
   142	func ContainsRune(s string, r rune) bool {
   143		return IndexRune(s, r) >= 0
   144	}
   145	
   146	// LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s.
   147	func LastIndex(s, sep string) int {
   148		n := len(sep)
   149		switch {
   150		case n == 0:
   151			return len(s)
   152		case n == 1:
   153			return LastIndexByte(s, sep[0])
   154		case n == len(s):
   155			if sep == s {
   156				return 0
   157			}
   158			return -1
   159		case n > len(s):
   160			return -1
   161		}
   162		// Rabin-Karp search from the end of the string
   163		hashsep, pow := hashStrRev(sep)
   164		last := len(s) - n
   165		var h uint32
   166		for i := len(s) - 1; i >= last; i-- {
   167			h = h*primeRK + uint32(s[i])
   168		}
   169		if h == hashsep && s[last:] == sep {
   170			return last
   171		}
   172		for i := last - 1; i >= 0; i-- {
   173			h *= primeRK
   174			h += uint32(s[i])
   175			h -= pow * uint32(s[i+n])
   176			if h == hashsep && s[i:i+n] == sep {
   177				return i
   178			}
   179		}
   180		return -1
   181	}
   182	
   183	// IndexRune returns the index of the first instance of the Unicode code point
   184	// r, or -1 if rune is not present in s.
   185	func IndexRune(s string, r rune) int {
   186		switch {
   187		case r < utf8.RuneSelf:
   188			return IndexByte(s, byte(r))
   189		default:
   190			for i, c := range s {
   191				if c == r {
   192					return i
   193				}
   194			}
   195		}
   196		return -1
   197	}
   198	
   199	// IndexAny returns the index of the first instance of any Unicode code point
   200	// from chars in s, or -1 if no Unicode code point from chars is present in s.
   201	func IndexAny(s, chars string) int {
   202		if len(chars) > 0 {
   203			for i, c := range s {
   204				for _, m := range chars {
   205					if c == m {
   206						return i
   207					}
   208				}
   209			}
   210		}
   211		return -1
   212	}
   213	
   214	// LastIndexAny returns the index of the last instance of any Unicode code
   215	// point from chars in s, or -1 if no Unicode code point from chars is
   216	// present in s.
   217	func LastIndexAny(s, chars string) int {
   218		if len(chars) > 0 {
   219			for i := len(s); i > 0; {
   220				rune, size := utf8.DecodeLastRuneInString(s[0:i])
   221				i -= size
   222				for _, m := range chars {
   223					if rune == m {
   224						return i
   225					}
   226				}
   227			}
   228		}
   229		return -1
   230	}
   231	
   232	// LastIndexByte returns the index of the last instance of c in s, or -1 if c is not present in s.
   233	func LastIndexByte(s string, c byte) int {
   234		for i := len(s) - 1; i >= 0; i-- {
   235			if s[i] == c {
   236				return i
   237			}
   238		}
   239		return -1
   240	}
   241	
   242	// Generic split: splits after each instance of sep,
   243	// including sepSave bytes of sep in the subarrays.
   244	func genSplit(s, sep string, sepSave, n int) []string {
   245		if n == 0 {
   246			return nil
   247		}
   248		if sep == "" {
   249			return explode(s, n)
   250		}
   251		if n < 0 {
   252			n = Count(s, sep) + 1
   253		}
   254		c := sep[0]
   255		start := 0
   256		a := make([]string, n)
   257		na := 0
   258		for i := 0; i+len(sep) <= len(s) && na+1 < n; i++ {
   259			if s[i] == c && (len(sep) == 1 || s[i:i+len(sep)] == sep) {
   260				a[na] = s[start : i+sepSave]
   261				na++
   262				start = i + len(sep)
   263				i += len(sep) - 1
   264			}
   265		}
   266		a[na] = s[start:]
   267		return a[0 : na+1]
   268	}
   269	
   270	// SplitN slices s into substrings separated by sep and returns a slice of
   271	// the substrings between those separators.
   272	// If sep is empty, SplitN splits after each UTF-8 sequence.
   273	// The count determines the number of substrings to return:
   274	//   n > 0: at most n substrings; the last substring will be the unsplit remainder.
   275	//   n == 0: the result is nil (zero substrings)
   276	//   n < 0: all substrings
   277	func SplitN(s, sep string, n int) []string { return genSplit(s, sep, 0, n) }
   278	
   279	// SplitAfterN slices s into substrings after each instance of sep and
   280	// returns a slice of those substrings.
   281	// If sep is empty, SplitAfterN splits after each UTF-8 sequence.
   282	// The count determines the number of substrings to return:
   283	//   n > 0: at most n substrings; the last substring will be the unsplit remainder.
   284	//   n == 0: the result is nil (zero substrings)
   285	//   n < 0: all substrings
   286	func SplitAfterN(s, sep string, n int) []string {
   287		return genSplit(s, sep, len(sep), n)
   288	}
   289	
   290	// Split slices s into all substrings separated by sep and returns a slice of
   291	// the substrings between those separators.
   292	// If sep is empty, Split splits after each UTF-8 sequence.
   293	// It is equivalent to SplitN with a count of -1.
   294	func Split(s, sep string) []string { return genSplit(s, sep, 0, -1) }
   295	
   296	// SplitAfter slices s into all substrings after each instance of sep and
   297	// returns a slice of those substrings.
   298	// If sep is empty, SplitAfter splits after each UTF-8 sequence.
   299	// It is equivalent to SplitAfterN with a count of -1.
   300	func SplitAfter(s, sep string) []string {
   301		return genSplit(s, sep, len(sep), -1)
   302	}
   303	
   304	// Fields splits the string s around each instance of one or more consecutive white space
   305	// characters, as defined by unicode.IsSpace, returning an array of substrings of s or an
   306	// empty list if s contains only white space.
   307	func Fields(s string) []string {
   308		return FieldsFunc(s, unicode.IsSpace)
   309	}
   310	
   311	// FieldsFunc splits the string s at each run of Unicode code points c satisfying f(c)
   312	// and returns an array of slices of s. If all code points in s satisfy f(c) or the
   313	// string is empty, an empty slice is returned.
   314	// FieldsFunc makes no guarantees about the order in which it calls f(c).
   315	// If f does not return consistent results for a given c, FieldsFunc may crash.
   316	func FieldsFunc(s string, f func(rune) bool) []string {
   317		// First count the fields.
   318		n := 0
   319		inField := false
   320		for _, rune := range s {
   321			wasInField := inField
   322			inField = !f(rune)
   323			if inField && !wasInField {
   324				n++
   325			}
   326		}
   327	
   328		// Now create them.
   329		a := make([]string, n)
   330		na := 0
   331		fieldStart := -1 // Set to -1 when looking for start of field.
   332		for i, rune := range s {
   333			if f(rune) {
   334				if fieldStart >= 0 {
   335					a[na] = s[fieldStart:i]
   336					na++
   337					fieldStart = -1
   338				}
   339			} else if fieldStart == -1 {
   340				fieldStart = i
   341			}
   342		}
   343		if fieldStart >= 0 { // Last field might end at EOF.
   344			a[na] = s[fieldStart:]
   345		}
   346		return a
   347	}
   348	
   349	// Join concatenates the elements of a to create a single string.   The separator string
   350	// sep is placed between elements in the resulting string.
   351	func Join(a []string, sep string) string {
   352		if len(a) == 0 {
   353			return ""
   354		}
   355		if len(a) == 1 {
   356			return a[0]
   357		}
   358		n := len(sep) * (len(a) - 1)
   359		for i := 0; i < len(a); i++ {
   360			n += len(a[i])
   361		}
   362	
   363		b := make([]byte, n)
   364		bp := copy(b, a[0])
   365		for _, s := range a[1:] {
   366			bp += copy(b[bp:], sep)
   367			bp += copy(b[bp:], s)
   368		}
   369		return string(b)
   370	}
   371	
   372	// HasPrefix tests whether the string s begins with prefix.
   373	func HasPrefix(s, prefix string) bool {
   374		return len(s) >= len(prefix) && s[0:len(prefix)] == prefix
   375	}
   376	
   377	// HasSuffix tests whether the string s ends with suffix.
   378	func HasSuffix(s, suffix string) bool {
   379		return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
   380	}
   381	
   382	// Map returns a copy of the string s with all its characters modified
   383	// according to the mapping function. If mapping returns a negative value, the character is
   384	// dropped from the string with no replacement.
   385	func Map(mapping func(rune) rune, s string) string {
   386		// In the worst case, the string can grow when mapped, making
   387		// things unpleasant.  But it's so rare we barge in assuming it's
   388		// fine.  It could also shrink but that falls out naturally.
   389		maxbytes := len(s) // length of b
   390		nbytes := 0        // number of bytes encoded in b
   391		// The output buffer b is initialized on demand, the first
   392		// time a character differs.
   393		var b []byte
   394	
   395		for i, c := range s {
   396			r := mapping(c)
   397			if b == nil {
   398				if r == c {
   399					continue
   400				}
   401				b = make([]byte, maxbytes)
   402				nbytes = copy(b, s[:i])
   403			}
   404			if r >= 0 {
   405				wid := 1
   406				if r >= utf8.RuneSelf {
   407					wid = utf8.RuneLen(r)
   408				}
   409				if nbytes+wid > maxbytes {
   410					// Grow the buffer.
   411					maxbytes = maxbytes*2 + utf8.UTFMax
   412					nb := make([]byte, maxbytes)
   413					copy(nb, b[0:nbytes])
   414					b = nb
   415				}
   416				nbytes += utf8.EncodeRune(b[nbytes:maxbytes], r)
   417			}
   418		}
   419		if b == nil {
   420			return s
   421		}
   422		return string(b[0:nbytes])
   423	}
   424	
   425	// Repeat returns a new string consisting of count copies of the string s.
   426	func Repeat(s string, count int) string {
   427		b := make([]byte, len(s)*count)
   428		bp := copy(b, s)
   429		for bp < len(b) {
   430			copy(b[bp:], b[:bp])
   431			bp *= 2
   432		}
   433		return string(b)
   434	}
   435	
   436	// ToUpper returns a copy of the string s with all Unicode letters mapped to their upper case.
   437	func ToUpper(s string) string { return Map(unicode.ToUpper, s) }
   438	
   439	// ToLower returns a copy of the string s with all Unicode letters mapped to their lower case.
   440	func ToLower(s string) string { return Map(unicode.ToLower, s) }
   441	
   442	// ToTitle returns a copy of the string s with all Unicode letters mapped to their title case.
   443	func ToTitle(s string) string { return Map(unicode.ToTitle, s) }
   444	
   445	// ToUpperSpecial returns a copy of the string s with all Unicode letters mapped to their
   446	// upper case, giving priority to the special casing rules.
   447	func ToUpperSpecial(_case unicode.SpecialCase, s string) string {
   448		return Map(func(r rune) rune { return _case.ToUpper(r) }, s)
   449	}
   450	
   451	// ToLowerSpecial returns a copy of the string s with all Unicode letters mapped to their
   452	// lower case, giving priority to the special casing rules.
   453	func ToLowerSpecial(_case unicode.SpecialCase, s string) string {
   454		return Map(func(r rune) rune { return _case.ToLower(r) }, s)
   455	}
   456	
   457	// ToTitleSpecial returns a copy of the string s with all Unicode letters mapped to their
   458	// title case, giving priority to the special casing rules.
   459	func ToTitleSpecial(_case unicode.SpecialCase, s string) string {
   460		return Map(func(r rune) rune { return _case.ToTitle(r) }, s)
   461	}
   462	
   463	// isSeparator reports whether the rune could mark a word boundary.
   464	// TODO: update when package unicode captures more of the properties.
   465	func isSeparator(r rune) bool {
   466		// ASCII alphanumerics and underscore are not separators
   467		if r <= 0x7F {
   468			switch {
   469			case '0' <= r && r <= '9':
   470				return false
   471			case 'a' <= r && r <= 'z':
   472				return false
   473			case 'A' <= r && r <= 'Z':
   474				return false
   475			case r == '_':
   476				return false
   477			}
   478			return true
   479		}
   480		// Letters and digits are not separators
   481		if unicode.IsLetter(r) || unicode.IsDigit(r) {
   482			return false
   483		}
   484		// Otherwise, all we can do for now is treat spaces as separators.
   485		return unicode.IsSpace(r)
   486	}
   487	
   488	// Title returns a copy of the string s with all Unicode letters that begin words
   489	// mapped to their title case.
   490	//
   491	// BUG(rsc): The rule Title uses for word boundaries does not handle Unicode punctuation properly.
   492	func Title(s string) string {
   493		// Use a closure here to remember state.
   494		// Hackish but effective. Depends on Map scanning in order and calling
   495		// the closure once per rune.
   496		prev := ' '
   497		return Map(
   498			func(r rune) rune {
   499				if isSeparator(prev) {
   500					prev = r
   501					return unicode.ToTitle(r)
   502				}
   503				prev = r
   504				return r
   505			},
   506			s)
   507	}
   508	
   509	// TrimLeftFunc returns a slice of the string s with all leading
   510	// Unicode code points c satisfying f(c) removed.
   511	func TrimLeftFunc(s string, f func(rune) bool) string {
   512		i := indexFunc(s, f, false)
   513		if i == -1 {
   514			return ""
   515		}
   516		return s[i:]
   517	}
   518	
   519	// TrimRightFunc returns a slice of the string s with all trailing
   520	// Unicode code points c satisfying f(c) removed.
   521	func TrimRightFunc(s string, f func(rune) bool) string {
   522		i := lastIndexFunc(s, f, false)
   523		if i >= 0 && s[i] >= utf8.RuneSelf {
   524			_, wid := utf8.DecodeRuneInString(s[i:])
   525			i += wid
   526		} else {
   527			i++
   528		}
   529		return s[0:i]
   530	}
   531	
   532	// TrimFunc returns a slice of the string s with all leading
   533	// and trailing Unicode code points c satisfying f(c) removed.
   534	func TrimFunc(s string, f func(rune) bool) string {
   535		return TrimRightFunc(TrimLeftFunc(s, f), f)
   536	}
   537	
   538	// IndexFunc returns the index into s of the first Unicode
   539	// code point satisfying f(c), or -1 if none do.
   540	func IndexFunc(s string, f func(rune) bool) int {
   541		return indexFunc(s, f, true)
   542	}
   543	
   544	// LastIndexFunc returns the index into s of the last
   545	// Unicode code point satisfying f(c), or -1 if none do.
   546	func LastIndexFunc(s string, f func(rune) bool) int {
   547		return lastIndexFunc(s, f, true)
   548	}
   549	
   550	// indexFunc is the same as IndexFunc except that if
   551	// truth==false, the sense of the predicate function is
   552	// inverted.
   553	func indexFunc(s string, f func(rune) bool, truth bool) int {
   554		start := 0
   555		for start < len(s) {
   556			wid := 1
   557			r := rune(s[start])
   558			if r >= utf8.RuneSelf {
   559				r, wid = utf8.DecodeRuneInString(s[start:])
   560			}
   561			if f(r) == truth {
   562				return start
   563			}
   564			start += wid
   565		}
   566		return -1
   567	}
   568	
   569	// lastIndexFunc is the same as LastIndexFunc except that if
   570	// truth==false, the sense of the predicate function is
   571	// inverted.
   572	func lastIndexFunc(s string, f func(rune) bool, truth bool) int {
   573		for i := len(s); i > 0; {
   574			r, size := utf8.DecodeLastRuneInString(s[0:i])
   575			i -= size
   576			if f(r) == truth {
   577				return i
   578			}
   579		}
   580		return -1
   581	}
   582	
   583	func makeCutsetFunc(cutset string) func(rune) bool {
   584		return func(r rune) bool { return IndexRune(cutset, r) >= 0 }
   585	}
   586	
   587	// Trim returns a slice of the string s with all leading and
   588	// trailing Unicode code points contained in cutset removed.
   589	func Trim(s string, cutset string) string {
   590		if s == "" || cutset == "" {
   591			return s
   592		}
   593		return TrimFunc(s, makeCutsetFunc(cutset))
   594	}
   595	
   596	// TrimLeft returns a slice of the string s with all leading
   597	// Unicode code points contained in cutset removed.
   598	func TrimLeft(s string, cutset string) string {
   599		if s == "" || cutset == "" {
   600			return s
   601		}
   602		return TrimLeftFunc(s, makeCutsetFunc(cutset))
   603	}
   604	
   605	// TrimRight returns a slice of the string s, with all trailing
   606	// Unicode code points contained in cutset removed.
   607	func TrimRight(s string, cutset string) string {
   608		if s == "" || cutset == "" {
   609			return s
   610		}
   611		return TrimRightFunc(s, makeCutsetFunc(cutset))
   612	}
   613	
   614	// TrimSpace returns a slice of the string s, with all leading
   615	// and trailing white space removed, as defined by Unicode.
   616	func TrimSpace(s string) string {
   617		return TrimFunc(s, unicode.IsSpace)
   618	}
   619	
   620	// TrimPrefix returns s without the provided leading prefix string.
   621	// If s doesn't start with prefix, s is returned unchanged.
   622	func TrimPrefix(s, prefix string) string {
   623		if HasPrefix(s, prefix) {
   624			return s[len(prefix):]
   625		}
   626		return s
   627	}
   628	
   629	// TrimSuffix returns s without the provided trailing suffix string.
   630	// If s doesn't end with suffix, s is returned unchanged.
   631	func TrimSuffix(s, suffix string) string {
   632		if HasSuffix(s, suffix) {
   633			return s[:len(s)-len(suffix)]
   634		}
   635		return s
   636	}
   637	
   638	// Replace returns a copy of the string s with the first n
   639	// non-overlapping instances of old replaced by new.
   640	// If old is empty, it matches at the beginning of the string
   641	// and after each UTF-8 sequence, yielding up to k+1 replacements
   642	// for a k-rune string.
   643	// If n < 0, there is no limit on the number of replacements.
   644	func Replace(s, old, new string, n int) string {
   645		if old == new || n == 0 {
   646			return s // avoid allocation
   647		}
   648	
   649		// Compute number of replacements.
   650		if m := Count(s, old); m == 0 {
   651			return s // avoid allocation
   652		} else if n < 0 || m < n {
   653			n = m
   654		}
   655	
   656		// Apply replacements to buffer.
   657		t := make([]byte, len(s)+n*(len(new)-len(old)))
   658		w := 0
   659		start := 0
   660		for i := 0; i < n; i++ {
   661			j := start
   662			if len(old) == 0 {
   663				if i > 0 {
   664					_, wid := utf8.DecodeRuneInString(s[start:])
   665					j += wid
   666				}
   667			} else {
   668				j += Index(s[start:], old)
   669			}
   670			w += copy(t[w:], s[start:j])
   671			w += copy(t[w:], new)
   672			start = j + len(old)
   673		}
   674		w += copy(t[w:], s[start:])
   675		return string(t[0:w])
   676	}
   677	
   678	// EqualFold reports whether s and t, interpreted as UTF-8 strings,
   679	// are equal under Unicode case-folding.
   680	func EqualFold(s, t string) bool {
   681		for s != "" && t != "" {
   682			// Extract first rune from each string.
   683			var sr, tr rune
   684			if s[0] < utf8.RuneSelf {
   685				sr, s = rune(s[0]), s[1:]
   686			} else {
   687				r, size := utf8.DecodeRuneInString(s)
   688				sr, s = r, s[size:]
   689			}
   690			if t[0] < utf8.RuneSelf {
   691				tr, t = rune(t[0]), t[1:]
   692			} else {
   693				r, size := utf8.DecodeRuneInString(t)
   694				tr, t = r, t[size:]
   695			}
   696	
   697			// If they match, keep going; if not, return false.
   698	
   699			// Easy case.
   700			if tr == sr {
   701				continue
   702			}
   703	
   704			// Make sr < tr to simplify what follows.
   705			if tr < sr {
   706				tr, sr = sr, tr
   707			}
   708			// Fast check for ASCII.
   709			if tr < utf8.RuneSelf && 'A' <= sr && sr <= 'Z' {
   710				// ASCII, and sr is upper case.  tr must be lower case.
   711				if tr == sr+'a'-'A' {
   712					continue
   713				}
   714				return false
   715			}
   716	
   717			// General case.  SimpleFold(x) returns the next equivalent rune > x
   718			// or wraps around to smaller values.
   719			r := unicode.SimpleFold(sr)
   720			for r != sr && r < tr {
   721				r = unicode.SimpleFold(r)
   722			}
   723			if r == tr {
   724				continue
   725			}
   726			return false
   727		}
   728	
   729		// One string is empty.  Are both?
   730		return s == t
   731	}
   732	

View as plain text