github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/json/internal/contextjson/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 "unicode" 9 "unicode/utf8" 10 ) 11 12 // foldName returns a folded string such that foldName(x) == foldName(y) 13 // is identical to bytes.EqualFold(x, y). 14 func foldName(in []byte) []byte { 15 // This is inlinable to take advantage of "function outlining". 16 var arr [32]byte // large enough for most JSON names 17 return appendFoldedName(arr[:0], in) 18 } 19 20 func appendFoldedName(out, in []byte) []byte { 21 for i := 0; i < len(in); { 22 // Handle single-byte ASCII. 23 if c := in[i]; c < utf8.RuneSelf { 24 if 'a' <= c && c <= 'z' { 25 c -= 'a' - 'A' 26 } 27 out = append(out, c) 28 i++ 29 continue 30 } 31 // Handle multi-byte Unicode. 32 r, n := utf8.DecodeRune(in[i:]) 33 out = utf8.AppendRune(out, foldRune(r)) 34 i += n 35 } 36 return out 37 } 38 39 // foldRune is returns the smallest rune for all runes in the same fold set. 40 func foldRune(r rune) rune { 41 for { 42 r2 := unicode.SimpleFold(r) 43 if r2 <= r { 44 return r2 45 } 46 r = r2 47 } 48 }