gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

coverage.go (4897B)


      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 }