Source File
fold.go
Belonging Package
encoding/json
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package json
import (
)
const (
caseMask = ^byte(0x20) // Mask to ignore case in ASCII.
kelvin = '\u212a'
smallLongEss = '\u017f'
)
// foldFunc returns one of four different case folding equivalence
// functions, from most general (and slow) to fastest:
//
// 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8
// 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S')
// 3) asciiEqualFold, no special, but includes non-letters (including _)
// 4) simpleLetterEqualFold, no specials, no non-letters.
//
// The letters S and K are special because they map to 3 runes, not just 2:
// * S maps to s and to U+017F 'ſ' Latin small letter long s
// * k maps to K and to U+212A 'K' Kelvin sign
// See https://play.golang.org/p/tTxjOc0OGo
//
// The returned function is specialized for matching against s and
// should only be given s. It's not curried for performance reasons.
func ( []byte) func(, []byte) bool {
:= false
:= false // special letter
for , := range {
if >= utf8.RuneSelf {
return bytes.EqualFold
}
:= & caseMask
if < 'A' || > 'Z' {
= true
} else if == 'K' || == 'S' {
// See above for why these letters are special.
= true
}
}
if {
return equalFoldRight
}
if {
return asciiEqualFold
}
return simpleLetterEqualFold
}
// equalFoldRight is a specialization of bytes.EqualFold when s is
// known to be all ASCII (including punctuation), but contains an 's',
// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
// See comments on foldFunc.
func (, []byte) bool {
for , := range {
if len() == 0 {
return false
}
:= [0]
if < utf8.RuneSelf {
if != {
:= & caseMask
if 'A' <= && <= 'Z' {
if != &caseMask {
return false
}
} else {
return false
}
}
= [1:]
continue
}
// sb is ASCII and t is not. t must be either kelvin
// sign or long s; sb must be s, S, k, or K.
, := utf8.DecodeRune()
switch {
case 's', 'S':
if != smallLongEss {
return false
}
case 'k', 'K':
if != kelvin {
return false
}
default:
return false
}
= [:]
}
if len() > 0 {
return false
}
return true
}
// asciiEqualFold is a specialization of bytes.EqualFold for use when
// s is all ASCII (but may contain non-letters) and contains no
// special-folding letters.
// See comments on foldFunc.
func (, []byte) bool {
if len() != len() {
return false
}
for , := range {
:= []
if == {
continue
}
if ('a' <= && <= 'z') || ('A' <= && <= 'Z') {
if &caseMask != &caseMask {
return false
}
} else {
return false
}
}
return true
}
// simpleLetterEqualFold is a specialization of bytes.EqualFold for
// use when s is all ASCII letters (no underscores, etc) and also
// doesn't contain 'k', 'K', 's', or 'S'.
// See comments on foldFunc.
func (, []byte) bool {
if len() != len() {
return false
}
for , := range {
if &caseMask != []&caseMask {
return false
}
}
return true
}