github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/golang.org/x/text/collate/option.go (about) 1 // Copyright 2014 The Go 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 package collate 6 7 import ( 8 "sort" 9 10 "golang.org/x/text/internal/colltab" 11 "golang.org/x/text/language" 12 "golang.org/x/text/unicode/norm" 13 ) 14 15 // newCollator creates a new collator with default options configured. 16 func newCollator(t colltab.Weighter) *Collator { 17 // Initialize a collator with default options. 18 c := &Collator{ 19 options: options{ 20 ignore: [colltab.NumLevels]bool{ 21 colltab.Quaternary: true, 22 colltab.Identity: true, 23 }, 24 f: norm.NFD, 25 t: t, 26 }, 27 } 28 29 // TODO: store vt in tags or remove. 30 c.variableTop = t.Top() 31 32 return c 33 } 34 35 // An Option is used to change the behavior of a Collator. Options override the 36 // settings passed through the locale identifier. 37 type Option struct { 38 priority int 39 f func(o *options) 40 } 41 42 type prioritizedOptions []Option 43 44 func (p prioritizedOptions) Len() int { 45 return len(p) 46 } 47 48 func (p prioritizedOptions) Swap(i, j int) { 49 p[i], p[j] = p[j], p[i] 50 } 51 52 func (p prioritizedOptions) Less(i, j int) bool { 53 return p[i].priority < p[j].priority 54 } 55 56 type options struct { 57 // ignore specifies which levels to ignore. 58 ignore [colltab.NumLevels]bool 59 60 // caseLevel is true if there is an additional level of case matching 61 // between the secondary and tertiary levels. 62 caseLevel bool 63 64 // backwards specifies the order of sorting at the secondary level. 65 // This option exists predominantly to support reverse sorting of accents in French. 66 backwards bool 67 68 // numeric specifies whether any sequence of decimal digits (category is Nd) 69 // is sorted at a primary level with its numeric value. 70 // For example, "A-21" < "A-123". 71 // This option is set by wrapping the main Weighter with NewNumericWeighter. 72 numeric bool 73 74 // alternate specifies an alternative handling of variables. 75 alternate alternateHandling 76 77 // variableTop is the largest primary value that is considered to be 78 // variable. 79 variableTop uint32 80 81 t colltab.Weighter 82 83 f norm.Form 84 } 85 86 func (o *options) setOptions(opts []Option) { 87 sort.Sort(prioritizedOptions(opts)) 88 for _, x := range opts { 89 x.f(o) 90 } 91 } 92 93 // OptionsFromTag extracts the BCP47 collation options from the tag and 94 // configures a collator accordingly. These options are set before any other 95 // option. 96 func OptionsFromTag(t language.Tag) Option { 97 return Option{0, func(o *options) { 98 o.setFromTag(t) 99 }} 100 } 101 102 func (o *options) setFromTag(t language.Tag) { 103 o.caseLevel = ldmlBool(t, o.caseLevel, "kc") 104 o.backwards = ldmlBool(t, o.backwards, "kb") 105 o.numeric = ldmlBool(t, o.numeric, "kn") 106 107 // Extract settings from the BCP47 u extension. 108 switch t.TypeForKey("ks") { // strength 109 case "level1": 110 o.ignore[colltab.Secondary] = true 111 o.ignore[colltab.Tertiary] = true 112 case "level2": 113 o.ignore[colltab.Tertiary] = true 114 case "level3", "": 115 // The default. 116 case "level4": 117 o.ignore[colltab.Quaternary] = false 118 case "identic": 119 o.ignore[colltab.Quaternary] = false 120 o.ignore[colltab.Identity] = false 121 } 122 123 switch t.TypeForKey("ka") { 124 case "shifted": 125 o.alternate = altShifted 126 // The following two types are not official BCP47, but we support them to 127 // give access to this otherwise hidden functionality. The name blanked is 128 // derived from the LDML name blanked and posix reflects the main use of 129 // the shift-trimmed option. 130 case "blanked": 131 o.alternate = altBlanked 132 case "posix": 133 o.alternate = altShiftTrimmed 134 } 135 136 // TODO: caseFirst ("kf"), reorder ("kr"), and maybe variableTop ("vt"). 137 138 // Not used: 139 // - normalization ("kk", not necessary for this implementation) 140 // - hiraganaQuatenary ("kh", obsolete) 141 } 142 143 func ldmlBool(t language.Tag, old bool, key string) bool { 144 switch t.TypeForKey(key) { 145 case "true": 146 return true 147 case "false": 148 return false 149 default: 150 return old 151 } 152 } 153 154 var ( 155 // IgnoreCase sets case-insensitive comparison. 156 IgnoreCase Option = ignoreCase 157 ignoreCase = Option{3, ignoreCaseF} 158 159 // IgnoreDiacritics causes diacritical marks to be ignored. ("o" == "รถ"). 160 IgnoreDiacritics Option = ignoreDiacritics 161 ignoreDiacritics = Option{3, ignoreDiacriticsF} 162 163 // IgnoreWidth causes full-width characters to match their half-width 164 // equivalents. 165 IgnoreWidth Option = ignoreWidth 166 ignoreWidth = Option{2, ignoreWidthF} 167 168 // Loose sets the collator to ignore diacritics, case and width. 169 Loose Option = loose 170 loose = Option{4, looseF} 171 172 // Force ordering if strings are equivalent but not equal. 173 Force Option = force 174 force = Option{5, forceF} 175 176 // Numeric specifies that numbers should sort numerically ("2" < "12"). 177 Numeric Option = numeric 178 numeric = Option{5, numericF} 179 ) 180 181 func ignoreWidthF(o *options) { 182 o.ignore[colltab.Tertiary] = true 183 o.caseLevel = true 184 } 185 186 func ignoreDiacriticsF(o *options) { 187 o.ignore[colltab.Secondary] = true 188 } 189 190 func ignoreCaseF(o *options) { 191 o.ignore[colltab.Tertiary] = true 192 o.caseLevel = false 193 } 194 195 func looseF(o *options) { 196 ignoreWidthF(o) 197 ignoreDiacriticsF(o) 198 ignoreCaseF(o) 199 } 200 201 func forceF(o *options) { 202 o.ignore[colltab.Identity] = false 203 } 204 205 func numericF(o *options) { o.numeric = true } 206 207 // Reorder overrides the pre-defined ordering of scripts and character sets. 208 func Reorder(s ...string) Option { 209 // TODO: need fractional weights to implement this. 210 panic("TODO: implement") 211 } 212 213 // TODO: consider making these public again. These options cannot be fully 214 // specified in BCP47, so an API interface seems warranted. Still a higher-level 215 // interface would be nice (e.g. a POSIX option for enabling altShiftTrimmed) 216 217 // alternateHandling identifies the various ways in which variables are handled. 218 // A rune with a primary weight lower than the variable top is considered a 219 // variable. 220 // See https://www.unicode.org/reports/tr10/#Variable_Weighting for details. 221 type alternateHandling int 222 223 const ( 224 // altNonIgnorable turns off special handling of variables. 225 altNonIgnorable alternateHandling = iota 226 227 // altBlanked sets variables and all subsequent primary ignorables to be 228 // ignorable at all levels. This is identical to removing all variables 229 // and subsequent primary ignorables from the input. 230 altBlanked 231 232 // altShifted sets variables to be ignorable for levels one through three and 233 // adds a fourth level based on the values of the ignored levels. 234 altShifted 235 236 // altShiftTrimmed is a slight variant of altShifted that is used to 237 // emulate POSIX. 238 altShiftTrimmed 239 )