gopkg.in/alecthomas/gometalinter.v3@v3.0.0/_linters/src/github.com/client9/misspell/ascii.go (about)

     1  package misspell
     2  
     3  // ByteToUpper converts an ascii byte to upper cases
     4  // Uses a branchless algorithm
     5  func ByteToUpper(x byte) byte {
     6  	b := byte(0x80) | x
     7  	c := b - byte(0x61)
     8  	d := ^(b - byte(0x7b))
     9  	e := (c & d) & (^x & 0x7f)
    10  	return x - (e >> 2)
    11  }
    12  
    13  // ByteToLower converts an ascii byte to lower case
    14  // uses a branchless algorithm
    15  func ByteToLower(eax byte) byte {
    16  	ebx := eax&byte(0x7f) + byte(0x25)
    17  	ebx = ebx&byte(0x7f) + byte(0x1a)
    18  	ebx = ((ebx & ^eax) >> 2) & byte(0x20)
    19  	return eax + ebx
    20  }
    21  
    22  // ByteEqualFold does ascii compare, case insensitive
    23  func ByteEqualFold(a, b byte) bool {
    24  	return a == b || ByteToLower(a) == ByteToLower(b)
    25  }
    26  
    27  // StringEqualFold ASCII case-insensitive comparison
    28  // golang toUpper/toLower for both bytes and strings
    29  // appears to be Unicode based which is super slow
    30  // based from https://codereview.appspot.com/5180044/patch/14007/21002
    31  func StringEqualFold(s1, s2 string) bool {
    32  	if len(s1) != len(s2) {
    33  		return false
    34  	}
    35  	for i := 0; i < len(s1); i++ {
    36  		c1 := s1[i]
    37  		c2 := s2[i]
    38  		// c1 & c2
    39  		if c1 != c2 {
    40  			c1 |= 'a' - 'A'
    41  			c2 |= 'a' - 'A'
    42  			if c1 != c2 || c1 < 'a' || c1 > 'z' {
    43  				return false
    44  			}
    45  		}
    46  	}
    47  	return true
    48  }
    49  
    50  // StringHasPrefixFold is similar to strings.HasPrefix but comparison
    51  // is done ignoring ASCII case.
    52  // /
    53  func StringHasPrefixFold(s1, s2 string) bool {
    54  	// prefix is bigger than input --> false
    55  	if len(s1) < len(s2) {
    56  		return false
    57  	}
    58  	if len(s1) == len(s2) {
    59  		return StringEqualFold(s1, s2)
    60  	}
    61  	return StringEqualFold(s1[:len(s2)], s2)
    62  }