language: added PreferSameScript MatchOption 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>
diff --git a/language/match.go b/language/match.go index 71f1258..63bc744 100644 --- a/language/match.go +++ b/language/match.go
@@ -6,6 +6,16 @@ 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 @@ -36,8 +46,8 @@ // 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) { @@ -47,18 +57,20 @@ } 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 + } } } } @@ -407,10 +419,11 @@ // 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 @@ -521,9 +534,13 @@ // 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{}
diff --git a/language/match_test.go b/language/match_test.go index cbb847c..4fb56a0 100644 --- a/language/match_test.go +++ b/language/match_test.go
@@ -381,7 +381,7 @@ 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) } @@ -475,7 +475,7 @@ } 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...) @@ -485,7 +485,7 @@ 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) } @@ -493,7 +493,7 @@ 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) } @@ -501,7 +501,7 @@ 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) } @@ -509,7 +509,7 @@ 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) } @@ -517,7 +517,7 @@ 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) } @@ -525,7 +525,7 @@ 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...) }