Skip to content

Commit

Permalink
language: added PreferSameScript MatchOption
Browse files Browse the repository at this point in the history
and added match options.

Change-Id: I7c772740515ff557b30fa03be034622b49ea544a
Reviewed-on: https://go-review.googlesource.com/47592
Run-TryBot: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: Nigel Tao <nigeltao@golang.org>
  • Loading branch information
mpvl committed Aug 10, 2017
1 parent f6122dd commit b19bf47
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 28 deletions.
57 changes: 37 additions & 20 deletions language/match.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ package language

import "errors"

// A MatchOption configures a Matcher.
type MatchOption func(*matcher)

// PreferSameScript will, in the absence of a match, result in the first
// preferred tag with the same script as a supported tag to match this supported
// tag. The default is currently true, but this may change in the future.
func PreferSameScript(preferSame bool) MatchOption {
return func(m *matcher) { m.preferSameScript = preferSame }
}

// Matcher is the interface that wraps the Match method.
//
// Match returns the best match for any of the given tags, along with
Expand Down Expand Up @@ -36,8 +46,8 @@ func Comprehends(speaker, alternative Tag) Confidence {
// matched tag in t, but is augmented with the Unicode extension ('u')of the
// corresponding preferred tag. This allows user locale options to be passed
// transparently.
func NewMatcher(t []Tag) Matcher {
return newMatcher(t)
func NewMatcher(t []Tag, options ...MatchOption) Matcher {
return newMatcher(t, options)
}

func (m *matcher) Match(want ...Tag) (t Tag, index int, c Confidence) {
Expand All @@ -47,18 +57,20 @@ func (m *matcher) Match(want ...Tag) (t Tag, index int, c Confidence) {
} else {
// TODO: this should be an option
t = m.default_.tag
outer:
for _, w := range want {
script, _ := w.Script()
if script.scriptID == 0 {
// Don't do anything if there is no script, such as with
// private subtags.
continue
}
for i, h := range m.supported {
if script.scriptID == h.maxScript {
t, index = h.tag, i
break outer
if m.preferSameScript {
outer:
for _, w := range want {
script, _ := w.Script()
if script.scriptID == 0 {
// Don't do anything if there is no script, such as with
// private subtags.
continue
}
for i, h := range m.supported {
if script.scriptID == h.maxScript {
t, index = h.tag, i
break outer
}
}
}
}
Expand Down Expand Up @@ -407,10 +419,11 @@ func minimizeTags(t Tag) (Tag, error) {

// matcher keeps a set of supported language tags, indexed by language.
type matcher struct {
default_ *haveTag
supported []*haveTag
index map[langID]*matchHeader
passSettings bool
default_ *haveTag
supported []*haveTag
index map[langID]*matchHeader
passSettings bool
preferSameScript bool
}

// matchHeader has the lists of tags for exact matches and matches based on
Expand Down Expand Up @@ -521,9 +534,13 @@ func toConf(d uint8) Confidence {
// newMatcher builds an index for the given supported tags and returns it as
// a matcher. It also expands the index by considering various equivalence classes
// for a given tag.
func newMatcher(supported []Tag) *matcher {
func newMatcher(supported []Tag, options []MatchOption) *matcher {
m := &matcher{
index: make(map[langID]*matchHeader),
index: make(map[langID]*matchHeader),
preferSameScript: true,
}
for _, o := range options {
o(m)
}
if len(supported) == 0 {
m.default_ = &haveTag{}
Expand Down
16 changes: 8 additions & 8 deletions language/match_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ func parseSupported(list string) (out []Tag) {
func TestBestMatch(t *testing.T) {
for _, tt := range matchTests {
supported := parseSupported(tt.supported)
m := newMatcher(supported)
m := newMatcher(supported, nil)
if *verbose {
fmt.Printf("%s:\n%v\n", tt.comment, m)
}
Expand Down Expand Up @@ -475,7 +475,7 @@ var benchWant = [][]Tag{
}

func BenchmarkMatch(b *testing.B) {
m := newMatcher(benchHave)
m := newMatcher(benchHave, nil)
for i := 0; i < b.N; i++ {
for _, want := range benchWant {
m.getBest(want...)
Expand All @@ -485,47 +485,47 @@ func BenchmarkMatch(b *testing.B) {

func BenchmarkMatchExact(b *testing.B) {
want := mk("en")
m := newMatcher(benchHave)
m := newMatcher(benchHave, nil)
for i := 0; i < b.N; i++ {
m.getBest(want)
}
}

func BenchmarkMatchAltLanguagePresent(b *testing.B) {
want := mk("hr")
m := newMatcher(benchHave)
m := newMatcher(benchHave, nil)
for i := 0; i < b.N; i++ {
m.getBest(want)
}
}

func BenchmarkMatchAltLanguageNotPresent(b *testing.B) {
want := mk("nn")
m := newMatcher(benchHave)
m := newMatcher(benchHave, nil)
for i := 0; i < b.N; i++ {
m.getBest(want)
}
}

func BenchmarkMatchAltScriptPresent(b *testing.B) {
want := mk("zh-Hant-CN")
m := newMatcher(benchHave)
m := newMatcher(benchHave, nil)
for i := 0; i < b.N; i++ {
m.getBest(want)
}
}

func BenchmarkMatchAltScriptNotPresent(b *testing.B) {
want := mk("fr-Cyrl")
m := newMatcher(benchHave)
m := newMatcher(benchHave, nil)
for i := 0; i < b.N; i++ {
m.getBest(want)
}
}

func BenchmarkMatchLimitedExact(b *testing.B) {
want := []Tag{mk("he-NL"), mk("iw-NL")}
m := newMatcher(benchHave)
m := newMatcher(benchHave, nil)
for i := 0; i < b.N; i++ {
m.getBest(want...)
}
Expand Down

0 comments on commit b19bf47

Please sign in to comment.