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

View as plain text