vitess.io/vitess@v0.16.2/go/mysql/collations/multibyte.go (about)

     1  /*
     2  Copyright 2021 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package collations
    18  
    19  import (
    20  	"math"
    21  
    22  	"vitess.io/vitess/go/mysql/collations/internal/charset"
    23  )
    24  
    25  type Collation_multibyte struct {
    26  	id      ID
    27  	name    string
    28  	sort    *[256]byte
    29  	charset charset.Charset
    30  }
    31  
    32  func (c *Collation_multibyte) Init() {}
    33  
    34  func (c *Collation_multibyte) ID() ID {
    35  	return c.id
    36  }
    37  
    38  func (c *Collation_multibyte) Name() string {
    39  	return c.name
    40  }
    41  
    42  func (c *Collation_multibyte) Charset() charset.Charset {
    43  	return c.charset
    44  }
    45  
    46  func (c *Collation_multibyte) IsBinary() bool {
    47  	return c.sort == nil
    48  }
    49  
    50  func (c *Collation_multibyte) Collate(left, right []byte, isPrefix bool) int {
    51  	if c.sort == nil {
    52  		return collationBinary(left, right, isPrefix)
    53  	}
    54  
    55  	cmpLen := minInt(len(left), len(right))
    56  	cs := c.charset
    57  	sortOrder := c.sort
    58  	for i := 0; i < cmpLen; i++ {
    59  		sortL, sortR := left[i], right[i]
    60  		if sortL > 127 {
    61  			if sortL != sortR {
    62  				return int(sortL) - int(sortR)
    63  			}
    64  			_, widthL := cs.DecodeRune(left[i:])
    65  			_, widthR := cs.DecodeRune(right[i:])
    66  			switch minInt(widthL, widthR) {
    67  			case 4:
    68  				i++
    69  				if left[i] != right[i] {
    70  					return int(left[i]) - int(right[i])
    71  				}
    72  				fallthrough
    73  			case 3:
    74  				i++
    75  				if left[i] != right[i] {
    76  					return int(left[i]) - int(right[i])
    77  				}
    78  				fallthrough
    79  			case 2:
    80  				i++
    81  				if left[i] != right[i] {
    82  					return int(left[i]) - int(right[i])
    83  				}
    84  				fallthrough
    85  			case 1:
    86  			}
    87  		} else {
    88  			sortL, sortR = sortOrder[sortL], sortOrder[sortR]
    89  			if sortL != sortR {
    90  				return int(sortL) - int(sortR)
    91  			}
    92  		}
    93  	}
    94  
    95  	if isPrefix {
    96  		left = left[:cmpLen]
    97  	}
    98  	return len(left) - len(right)
    99  }
   100  
   101  func (c *Collation_multibyte) WeightString(dst, src []byte, numCodepoints int) []byte {
   102  	cs := c.charset
   103  	sortOrder := c.sort
   104  
   105  	if numCodepoints == 0 || numCodepoints == PadToMax {
   106  		for len(src) > 0 {
   107  			w := src[0]
   108  			if w <= 127 {
   109  				if sortOrder != nil {
   110  					w = sortOrder[w]
   111  				}
   112  				dst = append(dst, w)
   113  				src = src[1:]
   114  			} else {
   115  				_, width := cs.DecodeRune(src)
   116  				dst = append(dst, src[:width]...)
   117  				src = src[width:]
   118  			}
   119  		}
   120  		if numCodepoints == PadToMax {
   121  			for len(dst) < cap(dst) {
   122  				dst = append(dst, ' ')
   123  			}
   124  		}
   125  	} else {
   126  		for len(src) > 0 && numCodepoints > 0 {
   127  			w := src[0]
   128  			if w <= 127 {
   129  				if sortOrder != nil {
   130  					w = sortOrder[w]
   131  				}
   132  				dst = append(dst, w)
   133  				src = src[1:]
   134  			} else {
   135  				_, width := cs.DecodeRune(src)
   136  				dst = append(dst, src[:width]...)
   137  				src = src[width:]
   138  			}
   139  			numCodepoints--
   140  		}
   141  		for numCodepoints > 0 {
   142  			dst = append(dst, ' ')
   143  			numCodepoints--
   144  		}
   145  	}
   146  
   147  	return dst
   148  }
   149  
   150  func (c *Collation_multibyte) Hash(src []byte, numCodepoints int) HashCode {
   151  	cs := c.charset
   152  	sortOrder := c.sort
   153  
   154  	var hash = uintptr(c.id)
   155  	var left = numCodepoints
   156  	if left == 0 {
   157  		left = math.MaxInt32
   158  	}
   159  	for len(src) > 0 && left > 0 {
   160  		w := src[0]
   161  		if w <= 127 {
   162  			if sortOrder != nil {
   163  				w = sortOrder[w]
   164  			}
   165  			hash = memhash8(w, hash)
   166  			src = src[1:]
   167  		} else {
   168  			_, width := cs.DecodeRune(src)
   169  			hash = memhash(src[:width], hash)
   170  			src = src[width:]
   171  		}
   172  		left--
   173  	}
   174  	if numCodepoints > 0 {
   175  		for left > 0 {
   176  			hash = memhash8(' ', hash)
   177  			left--
   178  		}
   179  	}
   180  	return hash
   181  }
   182  
   183  func (c *Collation_multibyte) WeightStringLen(numCodepoints int) int {
   184  	return numCodepoints
   185  }
   186  
   187  func (c *Collation_multibyte) Wildcard(pat []byte, matchOne rune, matchMany rune, escape rune) WildcardPattern {
   188  	var equals func(rune, rune) bool
   189  	var sortOrder = c.sort
   190  
   191  	if sortOrder != nil {
   192  		equals = func(a, b rune) bool {
   193  			if a < 128 && b < 128 {
   194  				return sortOrder[a] == sortOrder[b]
   195  			}
   196  			return a == b
   197  		}
   198  	} else {
   199  		equals = func(a, b rune) bool {
   200  			return a == b
   201  		}
   202  	}
   203  
   204  	return newUnicodeWildcardMatcher(c.charset, equals, c.Collate, pat, matchOne, matchMany, escape)
   205  }