github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/json/internal/contextjson_120/fold.go (about) 1 // Copyright 2013 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 json 6 7 import ( 8 "bytes" 9 "unicode/utf8" 10 ) 11 12 const ( 13 caseMask = ^byte(0x20) // Mask to ignore case in ASCII. 14 kelvin = '\u212a' 15 smallLongEss = '\u017f' 16 ) 17 18 // foldFunc returns one of four different case folding equivalence 19 // functions, from most general (and slow) to fastest: 20 // 21 // 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8 22 // 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S') 23 // 3) asciiEqualFold, no special, but includes non-letters (including _) 24 // 4) simpleLetterEqualFold, no specials, no non-letters. 25 // 26 // The letters S and K are special because they map to 3 runes, not just 2: 27 // - S maps to s and to U+017F 'ſ' Latin small letter long s 28 // - k maps to K and to U+212A 'K' Kelvin sign 29 // 30 // See https://play.golang.org/p/tTxjOc0OGo 31 // 32 // The returned function is specialized for matching against s and 33 // should only be given s. It's not curried for performance reasons. 34 func foldFunc(s []byte) func(s, t []byte) bool { 35 nonLetter := false 36 special := false // special letter 37 for _, b := range s { 38 if b >= utf8.RuneSelf { 39 return bytes.EqualFold 40 } 41 upper := b & caseMask 42 if upper < 'A' || upper > 'Z' { 43 nonLetter = true 44 } else if upper == 'K' || upper == 'S' { 45 // See above for why these letters are special. 46 special = true 47 } 48 } 49 if special { 50 return equalFoldRight 51 } 52 if nonLetter { 53 return asciiEqualFold 54 } 55 return simpleLetterEqualFold 56 } 57 58 // equalFoldRight is a specialization of bytes.EqualFold when s is 59 // known to be all ASCII (including punctuation), but contains an 's', 60 // 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t. 61 // See comments on foldFunc. 62 func equalFoldRight(s, t []byte) bool { 63 for _, sb := range s { 64 if len(t) == 0 { 65 return false 66 } 67 tb := t[0] 68 if tb < utf8.RuneSelf { 69 if sb != tb { 70 sbUpper := sb & caseMask 71 if 'A' <= sbUpper && sbUpper <= 'Z' { 72 if sbUpper != tb&caseMask { 73 return false 74 } 75 } else { 76 return false 77 } 78 } 79 t = t[1:] 80 continue 81 } 82 // sb is ASCII and t is not. t must be either kelvin 83 // sign or long s; sb must be s, S, k, or K. 84 tr, size := utf8.DecodeRune(t) 85 switch sb { 86 case 's', 'S': 87 if tr != smallLongEss { 88 return false 89 } 90 case 'k', 'K': 91 if tr != kelvin { 92 return false 93 } 94 default: 95 return false 96 } 97 t = t[size:] 98 99 } 100 return len(t) == 0 101 } 102 103 // asciiEqualFold is a specialization of bytes.EqualFold for use when 104 // s is all ASCII (but may contain non-letters) and contains no 105 // special-folding letters. 106 // See comments on foldFunc. 107 func asciiEqualFold(s, t []byte) bool { 108 if len(s) != len(t) { 109 return false 110 } 111 for i, sb := range s { 112 tb := t[i] 113 if sb == tb { 114 continue 115 } 116 if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') { 117 if sb&caseMask != tb&caseMask { 118 return false 119 } 120 } else { 121 return false 122 } 123 } 124 return true 125 } 126 127 // simpleLetterEqualFold is a specialization of bytes.EqualFold for 128 // use when s is all ASCII letters (no underscores, etc) and also 129 // doesn't contain 'k', 'K', 's', or 'S'. 130 // See comments on foldFunc. 131 func simpleLetterEqualFold(s, t []byte) bool { 132 if len(s) != len(t) { 133 return false 134 } 135 for i, b := range s { 136 if b&caseMask != t[i]&caseMask { 137 return false 138 } 139 } 140 return true 141 }