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

View as plain text