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 }