barometer: update DMA's vendoring packages
[barometer.git] / src / dma / vendor / golang.org / x / text / language / coverage.go
1 // Copyright 2014 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
5 package language
6
7 import (
8         "fmt"
9         "sort"
10
11         "golang.org/x/text/internal/language"
12 )
13
14 // The Coverage interface is used to define the level of coverage of an
15 // internationalization service. Note that not all types are supported by all
16 // services. As lists may be generated on the fly, it is recommended that users
17 // of a Coverage cache the results.
18 type Coverage interface {
19         // Tags returns the list of supported tags.
20         Tags() []Tag
21
22         // BaseLanguages returns the list of supported base languages.
23         BaseLanguages() []Base
24
25         // Scripts returns the list of supported scripts.
26         Scripts() []Script
27
28         // Regions returns the list of supported regions.
29         Regions() []Region
30 }
31
32 var (
33         // Supported defines a Coverage that lists all supported subtags. Tags
34         // always returns nil.
35         Supported Coverage = allSubtags{}
36 )
37
38 // TODO:
39 // - Support Variants, numbering systems.
40 // - CLDR coverage levels.
41 // - Set of common tags defined in this package.
42
43 type allSubtags struct{}
44
45 // Regions returns the list of supported regions. As all regions are in a
46 // consecutive range, it simply returns a slice of numbers in increasing order.
47 // The "undefined" region is not returned.
48 func (s allSubtags) Regions() []Region {
49         reg := make([]Region, language.NumRegions)
50         for i := range reg {
51                 reg[i] = Region{language.Region(i + 1)}
52         }
53         return reg
54 }
55
56 // Scripts returns the list of supported scripts. As all scripts are in a
57 // consecutive range, it simply returns a slice of numbers in increasing order.
58 // The "undefined" script is not returned.
59 func (s allSubtags) Scripts() []Script {
60         scr := make([]Script, language.NumScripts)
61         for i := range scr {
62                 scr[i] = Script{language.Script(i + 1)}
63         }
64         return scr
65 }
66
67 // BaseLanguages returns the list of all supported base languages. It generates
68 // the list by traversing the internal structures.
69 func (s allSubtags) BaseLanguages() []Base {
70         bs := language.BaseLanguages()
71         base := make([]Base, len(bs))
72         for i, b := range bs {
73                 base[i] = Base{b}
74         }
75         return base
76 }
77
78 // Tags always returns nil.
79 func (s allSubtags) Tags() []Tag {
80         return nil
81 }
82
83 // coverage is used by NewCoverage which is used as a convenient way for
84 // creating Coverage implementations for partially defined data. Very often a
85 // package will only need to define a subset of slices. coverage provides a
86 // convenient way to do this. Moreover, packages using NewCoverage, instead of
87 // their own implementation, will not break if later new slice types are added.
88 type coverage struct {
89         tags    func() []Tag
90         bases   func() []Base
91         scripts func() []Script
92         regions func() []Region
93 }
94
95 func (s *coverage) Tags() []Tag {
96         if s.tags == nil {
97                 return nil
98         }
99         return s.tags()
100 }
101
102 // bases implements sort.Interface and is used to sort base languages.
103 type bases []Base
104
105 func (b bases) Len() int {
106         return len(b)
107 }
108
109 func (b bases) Swap(i, j int) {
110         b[i], b[j] = b[j], b[i]
111 }
112
113 func (b bases) Less(i, j int) bool {
114         return b[i].langID < b[j].langID
115 }
116
117 // BaseLanguages returns the result from calling s.bases if it is specified or
118 // otherwise derives the set of supported base languages from tags.
119 func (s *coverage) BaseLanguages() []Base {
120         if s.bases == nil {
121                 tags := s.Tags()
122                 if len(tags) == 0 {
123                         return nil
124                 }
125                 a := make([]Base, len(tags))
126                 for i, t := range tags {
127                         a[i] = Base{language.Language(t.lang())}
128                 }
129                 sort.Sort(bases(a))
130                 k := 0
131                 for i := 1; i < len(a); i++ {
132                         if a[k] != a[i] {
133                                 k++
134                                 a[k] = a[i]
135                         }
136                 }
137                 return a[:k+1]
138         }
139         return s.bases()
140 }
141
142 func (s *coverage) Scripts() []Script {
143         if s.scripts == nil {
144                 return nil
145         }
146         return s.scripts()
147 }
148
149 func (s *coverage) Regions() []Region {
150         if s.regions == nil {
151                 return nil
152         }
153         return s.regions()
154 }
155
156 // NewCoverage returns a Coverage for the given lists. It is typically used by
157 // packages providing internationalization services to define their level of
158 // coverage. A list may be of type []T or func() []T, where T is either Tag,
159 // Base, Script or Region. The returned Coverage derives the value for Bases
160 // from Tags if no func or slice for []Base is specified. For other unspecified
161 // types the returned Coverage will return nil for the respective methods.
162 func NewCoverage(list ...interface{}) Coverage {
163         s := &coverage{}
164         for _, x := range list {
165                 switch v := x.(type) {
166                 case func() []Base:
167                         s.bases = v
168                 case func() []Script:
169                         s.scripts = v
170                 case func() []Region:
171                         s.regions = v
172                 case func() []Tag:
173                         s.tags = v
174                 case []Base:
175                         s.bases = func() []Base { return v }
176                 case []Script:
177                         s.scripts = func() []Script { return v }
178                 case []Region:
179                         s.regions = func() []Region { return v }
180                 case []Tag:
181                         s.tags = func() []Tag { return v }
182                 default:
183                         panic(fmt.Sprintf("language: unsupported set type %T", v))
184                 }
185         }
186         return s
187 }