1/**
2 *  Copyright 2014 Paul Querna
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 *  you may not use this file except in compliance with the License.
6 *  You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *  Unless required by applicable law or agreed to in writing, software
11 *  distributed under the License is distributed on an "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 *  See the License for the specific language governing permissions and
14 *  limitations under the License.
15 *
16 */
17
18/* Portions of this file are on Go stdlib's encoding/json/fold.go */
19// Copyright 2009 The Go Authors. All rights reserved.
20// Use of this source code is governed by a BSD-style
21// license that can be found in the LICENSE file.
22
23package v1
24
25import (
26	"unicode/utf8"
27)
28
29const (
30	caseMask     = ^byte(0x20) // Mask to ignore case in ASCII.
31	kelvin       = '\u212a'
32	smallLongEss = '\u017f'
33)
34
35// equalFoldRight is a specialization of bytes.EqualFold when s is
36// known to be all ASCII (including punctuation), but contains an 's',
37// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
38// See comments on foldFunc.
39func EqualFoldRight(s, t []byte) bool {
40	for _, sb := range s {
41		if len(t) == 0 {
42			return false
43		}
44		tb := t[0]
45		if tb < utf8.RuneSelf {
46			if sb != tb {
47				sbUpper := sb & caseMask
48				if 'A' <= sbUpper && sbUpper <= 'Z' {
49					if sbUpper != tb&caseMask {
50						return false
51					}
52				} else {
53					return false
54				}
55			}
56			t = t[1:]
57			continue
58		}
59		// sb is ASCII and t is not. t must be either kelvin
60		// sign or long s; sb must be s, S, k, or K.
61		tr, size := utf8.DecodeRune(t)
62		switch sb {
63		case 's', 'S':
64			if tr != smallLongEss {
65				return false
66			}
67		case 'k', 'K':
68			if tr != kelvin {
69				return false
70			}
71		default:
72			return false
73		}
74		t = t[size:]
75
76	}
77	if len(t) > 0 {
78		return false
79	}
80	return true
81}
82
83// asciiEqualFold is a specialization of bytes.EqualFold for use when
84// s is all ASCII (but may contain non-letters) and contains no
85// special-folding letters.
86// See comments on foldFunc.
87func AsciiEqualFold(s, t []byte) bool {
88	if len(s) != len(t) {
89		return false
90	}
91	for i, sb := range s {
92		tb := t[i]
93		if sb == tb {
94			continue
95		}
96		if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
97			if sb&caseMask != tb&caseMask {
98				return false
99			}
100		} else {
101			return false
102		}
103	}
104	return true
105}
106
107// simpleLetterEqualFold is a specialization of bytes.EqualFold for
108// use when s is all ASCII letters (no underscores, etc) and also
109// doesn't contain 'k', 'K', 's', or 'S'.
110// See comments on foldFunc.
111func SimpleLetterEqualFold(s, t []byte) bool {
112	if len(s) != len(t) {
113		return false
114	}
115	for i, b := range s {
116		if b&caseMask != t[i]&caseMask {
117			return false
118		}
119	}
120	return true
121}
122