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
5package json
6
7import (
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).
14func 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
20func 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.
40func foldRune(r rune) rune {
41 for {
42 r2 := unicode.SimpleFold(r)
43 if r2 <= r {
44 return r2
45 }
46 r = r2
47 }
48}