github.com/goki/ki@v1.1.11/runes/runes.go (about)

     1  // Copyright (c) 2018, The GoKi 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  /*
     6  Package runes provides a small subset of functions that are found in strings, bytes
     7  standard packages, for rune slices.  For rendering, and other logic, it is best to
     8  keep raw data in runes, and not having to convert back and forth to byte or string
     9  is more efficient.
    10  
    11  These are largely copied from strings or bytes packages.
    12  */
    13  package runes
    14  
    15  import (
    16  	"unicode"
    17  	"unicode/utf8"
    18  )
    19  
    20  // EqualFold reports whether s and t are equal under Unicode case-folding.
    21  // copied from strings.EqualFold
    22  func EqualFold(s, t []rune) bool {
    23  	for len(s) > 0 && len(t) > 0 {
    24  		// Extract first rune from each string.
    25  		var sr, tr rune
    26  		sr, s = s[0], s[1:]
    27  		tr, t = t[0], t[1:]
    28  		// If they match, keep going; if not, return false.
    29  
    30  		// Easy case.
    31  		if tr == sr {
    32  			continue
    33  		}
    34  
    35  		// Make sr < tr to simplify what follows.
    36  		if tr < sr {
    37  			tr, sr = sr, tr
    38  		}
    39  		// Fast check for ASCII.
    40  		if tr < utf8.RuneSelf {
    41  			// ASCII only, sr/tr must be upper/lower case
    42  			if 'A' <= sr && sr <= 'Z' && tr == sr+'a'-'A' {
    43  				continue
    44  			}
    45  			return false
    46  		}
    47  
    48  		// General case. SimpleFold(x) returns the next equivalent rune > x
    49  		// or wraps around to smaller values.
    50  		r := unicode.SimpleFold(sr)
    51  		for r != sr && r < tr {
    52  			r = unicode.SimpleFold(r)
    53  		}
    54  		if r == tr {
    55  			continue
    56  		}
    57  		return false
    58  	}
    59  
    60  	// One string is empty. Are both?
    61  	return len(s) == len(t)
    62  }
    63  
    64  // Index returns the index of given rune string in the text, returning -1 if not found.
    65  func Index(txt, find []rune) int {
    66  	fsz := len(find)
    67  	if fsz == 0 {
    68  		return -1
    69  	}
    70  	tsz := len(txt)
    71  	if tsz < fsz {
    72  		return -1
    73  	}
    74  	mn := tsz - fsz
    75  	for i := 0; i <= mn; i++ {
    76  		found := true
    77  		for j := range find {
    78  			if txt[i+j] != find[j] {
    79  				found = false
    80  				break
    81  			}
    82  		}
    83  		if found {
    84  			return i
    85  		}
    86  	}
    87  	return -1
    88  }
    89  
    90  // IndexFold returns the index of given rune string in the text, using case folding
    91  // (i.e., case insensitive matching).  Returns -1 if not found.
    92  func IndexFold(txt, find []rune) int {
    93  	fsz := len(find)
    94  	if fsz == 0 {
    95  		return -1
    96  	}
    97  	tsz := len(txt)
    98  	if tsz < fsz {
    99  		return -1
   100  	}
   101  	mn := tsz - fsz
   102  	for i := 0; i <= mn; i++ {
   103  		if EqualFold(txt[i:i+fsz], find) {
   104  			return i
   105  		}
   106  	}
   107  	return -1
   108  }
   109  
   110  // Repeat returns a new rune slice consisting of count copies of b.
   111  //
   112  // It panics if count is negative or if
   113  // the result of (len(b) * count) overflows.
   114  func Repeat(r []rune, count int) []rune {
   115  	if count == 0 {
   116  		return []rune{}
   117  	}
   118  	// Since we cannot return an error on overflow,
   119  	// we should panic if the repeat will generate
   120  	// an overflow.
   121  	// See Issue golang.org/issue/16237.
   122  	if count < 0 {
   123  		panic("runes: negative Repeat count")
   124  	} else if len(r)*count/count != len(r) {
   125  		panic("runes: Repeat count causes overflow")
   126  	}
   127  
   128  	nb := make([]rune, len(r)*count)
   129  	bp := copy(nb, r)
   130  	for bp < len(nb) {
   131  		copy(nb[bp:], nb[:bp])
   132  		bp *= 2
   133  	}
   134  	return nb
   135  }