htmlindex.go raw

   1  // Copyright 2015 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  //go:generate go run gen.go
   6  
   7  // Package htmlindex maps character set encoding names to Encodings as
   8  // recommended by the W3C for use in HTML 5. See http://www.w3.org/TR/encoding.
   9  package htmlindex
  10  
  11  // TODO: perhaps have a "bare" version of the index (used by this package) that
  12  // is not pre-loaded with all encodings. Global variables in encodings prevent
  13  // the linker from being able to purge unneeded tables. This means that
  14  // referencing all encodings, as this package does for the default index, links
  15  // in all encodings unconditionally.
  16  //
  17  // This issue can be solved by either solving the linking issue (see
  18  // https://github.com/golang/go/issues/6330) or refactoring the encoding tables
  19  // (e.g. moving the tables to internal packages that do not use global
  20  // variables).
  21  
  22  // TODO: allow canonicalizing names
  23  
  24  import (
  25  	"errors"
  26  	"strings"
  27  	"sync"
  28  
  29  	"golang.org/x/text/encoding"
  30  	"golang.org/x/text/encoding/internal/identifier"
  31  	"golang.org/x/text/language"
  32  )
  33  
  34  var (
  35  	errInvalidName = errors.New("htmlindex: invalid encoding name")
  36  	errUnknown     = errors.New("htmlindex: unknown Encoding")
  37  	errUnsupported = errors.New("htmlindex: this encoding is not supported")
  38  )
  39  
  40  var (
  41  	matcherOnce sync.Once
  42  	matcher     language.Matcher
  43  )
  44  
  45  // LanguageDefault returns the canonical name of the default encoding for a
  46  // given language.
  47  func LanguageDefault(tag language.Tag) string {
  48  	matcherOnce.Do(func() {
  49  		tags := []language.Tag{}
  50  		for _, t := range strings.Split(locales, " ") {
  51  			tags = append(tags, language.MustParse(t))
  52  		}
  53  		matcher = language.NewMatcher(tags, language.PreferSameScript(true))
  54  	})
  55  	_, i, _ := matcher.Match(tag)
  56  	return canonical[localeMap[i]] // Default is Windows-1252.
  57  }
  58  
  59  // Get returns an Encoding for one of the names listed in
  60  // http://www.w3.org/TR/encoding using the Default Index. Matching is case-
  61  // insensitive.
  62  func Get(name string) (encoding.Encoding, error) {
  63  	x, ok := nameMap[strings.ToLower(strings.TrimSpace(name))]
  64  	if !ok {
  65  		return nil, errInvalidName
  66  	}
  67  	return encodings[x], nil
  68  }
  69  
  70  // Name reports the canonical name of the given Encoding. It will return
  71  // an error if e is not associated with a supported encoding scheme.
  72  func Name(e encoding.Encoding) (string, error) {
  73  	id, ok := e.(identifier.Interface)
  74  	if !ok {
  75  		return "", errUnknown
  76  	}
  77  	mib, _ := id.ID()
  78  	if mib == 0 {
  79  		return "", errUnknown
  80  	}
  81  	v, ok := mibMap[mib]
  82  	if !ok {
  83  		return "", errUnsupported
  84  	}
  85  	return canonical[v], nil
  86  }
  87