vitess.io/vitess@v0.16.2/go/mysql/collations/internal/uca/collation.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 uca
    18  
    19  import (
    20  	"sync"
    21  
    22  	"vitess.io/vitess/go/mysql/collations/internal/charset"
    23  )
    24  
    25  type Collation interface {
    26  	Charset() charset.Charset
    27  	Weights() (Weights, Layout)
    28  	WeightForSpace() uint16
    29  	WeightsEqual(left, right rune) bool
    30  }
    31  
    32  var _ Collation = (*Collation900)(nil)
    33  
    34  type Collation900 struct {
    35  	table     Weights
    36  	implicits func([]uint16, rune)
    37  	contract  Contractor
    38  	param     *parametricT
    39  	maxLevel  int
    40  	iterpool  *sync.Pool
    41  }
    42  
    43  func (c *Collation900) Charset() charset.Charset {
    44  	return charset.Charset_utf8mb4{}
    45  }
    46  
    47  func (c *Collation900) Weights() (Weights, Layout) {
    48  	return c.table, Layout_uca900{}
    49  }
    50  
    51  func (c *Collation900) Iterator(input []byte) WeightIterator {
    52  	iter := c.iterpool.Get().(WeightIterator)
    53  	iter.reset(input)
    54  	return iter
    55  }
    56  
    57  func (c *Collation900) WeightForSpace() uint16 {
    58  	ascii := *c.table[0]
    59  	return ascii[CodepointsPerPage+' ']
    60  }
    61  
    62  func (c *Collation900) WeightsEqual(left, right rune) bool {
    63  	if left == right {
    64  		return true
    65  	}
    66  	return equalWeights900(c.table, c.maxLevel, left, right)
    67  }
    68  
    69  func NewCollation(name string, weights Weights, weightPatches []Patch, reorder []Reorder, contract Contractor, upperCaseFirst bool, levels int) *Collation900 {
    70  	coll := &Collation900{
    71  		table:     ApplyTailoring(Layout_uca900{}, weights, weightPatches),
    72  		implicits: UnicodeImplicitWeights900,
    73  		contract:  contract,
    74  		maxLevel:  levels,
    75  		param:     newParametricTailoring(reorder, upperCaseFirst),
    76  		iterpool:  &sync.Pool{},
    77  	}
    78  
    79  	switch {
    80  	case coll.param == nil && len(weightPatches) == 0 && coll.contract == nil:
    81  		coll.iterpool.New = func() any {
    82  			return &FastIterator900{iterator900: iterator900{Collation900: *coll}}
    83  		}
    84  	case name == "utf8mb4_ja_0900_as_cs_ks" || name == "utf8mb4_ja_0900_as_cs":
    85  		coll.iterpool.New = func() any {
    86  			return &jaIterator900{iterator900: iterator900{Collation900: *coll}}
    87  		}
    88  	case name == "utf8mb4_zh_0900_as_cs":
    89  		coll.implicits = unicodeImplicitChineseWeights
    90  		fallthrough
    91  	default:
    92  		coll.iterpool.New = func() any {
    93  			return &slowIterator900{iterator900: iterator900{Collation900: *coll}}
    94  		}
    95  	}
    96  
    97  	return coll
    98  }
    99  
   100  var _ Collation = (*CollationLegacy)(nil)
   101  
   102  type CollationLegacy struct {
   103  	charset      charset.Charset
   104  	table        Weights
   105  	maxCodepoint rune
   106  	contract     Contractor
   107  	iterpool     *sync.Pool
   108  }
   109  
   110  func (c *CollationLegacy) Charset() charset.Charset {
   111  	return c.charset
   112  }
   113  
   114  func (c *CollationLegacy) Weights() (Weights, Layout) {
   115  	return c.table, Layout_uca_legacy{Max: c.maxCodepoint}
   116  }
   117  
   118  func (c *CollationLegacy) Iterator(input []byte) *WeightIteratorLegacy {
   119  	iter := c.iterpool.Get().(*WeightIteratorLegacy)
   120  	iter.reset(input)
   121  	return iter
   122  }
   123  
   124  func (c *CollationLegacy) WeightForSpace() uint16 {
   125  	ascii := *c.table[0]
   126  	stride := ascii[0]
   127  	return ascii[1+' '*stride]
   128  }
   129  
   130  func (c *CollationLegacy) WeightsEqual(left, right rune) bool {
   131  	if left == right {
   132  		return true
   133  	}
   134  	return equalWeightsLegacy(c.table, left, right)
   135  }
   136  
   137  func NewCollationLegacy(cs charset.Charset, weights Weights, weightPatches []Patch, contract Contractor, maxCodepoint rune) *CollationLegacy {
   138  	coll := &CollationLegacy{
   139  		charset:      cs,
   140  		table:        ApplyTailoring(Layout_uca_legacy{}, weights, weightPatches),
   141  		maxCodepoint: maxCodepoint,
   142  		contract:     contract,
   143  		iterpool:     &sync.Pool{},
   144  	}
   145  
   146  	coll.iterpool.New = func() any {
   147  		return &WeightIteratorLegacy{CollationLegacy: *coll}
   148  	}
   149  
   150  	return coll
   151  }