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}
49