k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340/pkg/internal/third_party/go-json-experiment/json/fold.go (about) 1 // Copyright 2020 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 similar to strings.EqualFold(x, y), but ignores underscore and dashes. 14 // This allows foldName to match common naming conventions. 15 func foldName(in []byte) []byte { 16 // This is inlinable to take advantage of "function outlining". 17 // See https://blog.filippo.io/efficient-go-apis-with-the-inliner/ 18 var arr [32]byte // large enough for most JSON names 19 return appendFoldedName(arr[:0], in) 20 } 21 func appendFoldedName(out, in []byte) []byte { 22 for i := 0; i < len(in); { 23 // Handle single-byte ASCII. 24 if c := in[i]; c < utf8.RuneSelf { 25 if c != '_' && c != '-' { 26 if 'a' <= c && c <= 'z' { 27 c -= 'a' - 'A' 28 } 29 out = append(out, c) 30 } 31 i++ 32 continue 33 } 34 // Handle multi-byte Unicode. 35 r, n := utf8.DecodeRune(in[i:]) 36 out = utf8.AppendRune(out, foldRune(r)) 37 i += n 38 } 39 return out 40 } 41 42 // foldRune is a variation on unicode.SimpleFold that returns the same rune 43 // for all runes in the same fold set. 44 // 45 // Invariant: 46 // 47 // foldRune(x) == foldRune(y) ⇔ strings.EqualFold(string(x), string(y)) 48 func foldRune(r rune) rune { 49 for { 50 r2 := unicode.SimpleFold(r) 51 if r2 <= r { 52 return r2 // smallest character in the fold set 53 } 54 r = r2 55 } 56 }