mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 18:43:34 +00:00
build: move e2e dependencies into e2e/go.mod
Several packages are only used while running the e2e suite. These packages are less important to update, as the they can not influence the final executable that is part of the Ceph-CSI container-image. By moving these dependencies out of the main Ceph-CSI go.mod, it is easier to identify if a reported CVE affects Ceph-CSI, or only the testing (like most of the Kubernetes CVEs). Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
committed by
mergify[bot]
parent
15da101b1b
commit
bec6090996
249
vendor/golang.org/x/text/encoding/charmap/charmap.go
generated
vendored
249
vendor/golang.org/x/text/encoding/charmap/charmap.go
generated
vendored
@ -1,249 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run maketables.go
|
||||
|
||||
// Package charmap provides simple character encodings such as IBM Code Page 437
|
||||
// and Windows 1252.
|
||||
package charmap // import "golang.org/x/text/encoding/charmap"
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// These encodings vary only in the way clients should interpret them. Their
|
||||
// coded character set is identical and a single implementation can be shared.
|
||||
var (
|
||||
// ISO8859_6E is the ISO 8859-6E encoding.
|
||||
ISO8859_6E encoding.Encoding = &iso8859_6E
|
||||
|
||||
// ISO8859_6I is the ISO 8859-6I encoding.
|
||||
ISO8859_6I encoding.Encoding = &iso8859_6I
|
||||
|
||||
// ISO8859_8E is the ISO 8859-8E encoding.
|
||||
ISO8859_8E encoding.Encoding = &iso8859_8E
|
||||
|
||||
// ISO8859_8I is the ISO 8859-8I encoding.
|
||||
ISO8859_8I encoding.Encoding = &iso8859_8I
|
||||
|
||||
iso8859_6E = internal.Encoding{
|
||||
Encoding: ISO8859_6,
|
||||
Name: "ISO-8859-6E",
|
||||
MIB: identifier.ISO88596E,
|
||||
}
|
||||
|
||||
iso8859_6I = internal.Encoding{
|
||||
Encoding: ISO8859_6,
|
||||
Name: "ISO-8859-6I",
|
||||
MIB: identifier.ISO88596I,
|
||||
}
|
||||
|
||||
iso8859_8E = internal.Encoding{
|
||||
Encoding: ISO8859_8,
|
||||
Name: "ISO-8859-8E",
|
||||
MIB: identifier.ISO88598E,
|
||||
}
|
||||
|
||||
iso8859_8I = internal.Encoding{
|
||||
Encoding: ISO8859_8,
|
||||
Name: "ISO-8859-8I",
|
||||
MIB: identifier.ISO88598I,
|
||||
}
|
||||
)
|
||||
|
||||
// All is a list of all defined encodings in this package.
|
||||
var All []encoding.Encoding = listAll
|
||||
|
||||
// TODO: implement these encodings, in order of importance.
|
||||
// ASCII, ISO8859_1: Rather common. Close to Windows 1252.
|
||||
// ISO8859_9: Close to Windows 1254.
|
||||
|
||||
// utf8Enc holds a rune's UTF-8 encoding in data[:len].
|
||||
type utf8Enc struct {
|
||||
len uint8
|
||||
data [3]byte
|
||||
}
|
||||
|
||||
// Charmap is an 8-bit character set encoding.
|
||||
type Charmap struct {
|
||||
// name is the encoding's name.
|
||||
name string
|
||||
// mib is the encoding type of this encoder.
|
||||
mib identifier.MIB
|
||||
// asciiSuperset states whether the encoding is a superset of ASCII.
|
||||
asciiSuperset bool
|
||||
// low is the lower bound of the encoded byte for a non-ASCII rune. If
|
||||
// Charmap.asciiSuperset is true then this will be 0x80, otherwise 0x00.
|
||||
low uint8
|
||||
// replacement is the encoded replacement character.
|
||||
replacement byte
|
||||
// decode is the map from encoded byte to UTF-8.
|
||||
decode [256]utf8Enc
|
||||
// encoding is the map from runes to encoded bytes. Each entry is a
|
||||
// uint32: the high 8 bits are the encoded byte and the low 24 bits are
|
||||
// the rune. The table entries are sorted by ascending rune.
|
||||
encode [256]uint32
|
||||
}
|
||||
|
||||
// NewDecoder implements the encoding.Encoding interface.
|
||||
func (m *Charmap) NewDecoder() *encoding.Decoder {
|
||||
return &encoding.Decoder{Transformer: charmapDecoder{charmap: m}}
|
||||
}
|
||||
|
||||
// NewEncoder implements the encoding.Encoding interface.
|
||||
func (m *Charmap) NewEncoder() *encoding.Encoder {
|
||||
return &encoding.Encoder{Transformer: charmapEncoder{charmap: m}}
|
||||
}
|
||||
|
||||
// String returns the Charmap's name.
|
||||
func (m *Charmap) String() string {
|
||||
return m.name
|
||||
}
|
||||
|
||||
// ID implements an internal interface.
|
||||
func (m *Charmap) ID() (mib identifier.MIB, other string) {
|
||||
return m.mib, ""
|
||||
}
|
||||
|
||||
// charmapDecoder implements transform.Transformer by decoding to UTF-8.
|
||||
type charmapDecoder struct {
|
||||
transform.NopResetter
|
||||
charmap *Charmap
|
||||
}
|
||||
|
||||
func (m charmapDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
for i, c := range src {
|
||||
if m.charmap.asciiSuperset && c < utf8.RuneSelf {
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = c
|
||||
nDst++
|
||||
nSrc = i + 1
|
||||
continue
|
||||
}
|
||||
|
||||
decode := &m.charmap.decode[c]
|
||||
n := int(decode.len)
|
||||
if nDst+n > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
// It's 15% faster to avoid calling copy for these tiny slices.
|
||||
for j := 0; j < n; j++ {
|
||||
dst[nDst] = decode.data[j]
|
||||
nDst++
|
||||
}
|
||||
nSrc = i + 1
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
// DecodeByte returns the Charmap's rune decoding of the byte b.
|
||||
func (m *Charmap) DecodeByte(b byte) rune {
|
||||
switch x := &m.decode[b]; x.len {
|
||||
case 1:
|
||||
return rune(x.data[0])
|
||||
case 2:
|
||||
return rune(x.data[0]&0x1f)<<6 | rune(x.data[1]&0x3f)
|
||||
default:
|
||||
return rune(x.data[0]&0x0f)<<12 | rune(x.data[1]&0x3f)<<6 | rune(x.data[2]&0x3f)
|
||||
}
|
||||
}
|
||||
|
||||
// charmapEncoder implements transform.Transformer by encoding from UTF-8.
|
||||
type charmapEncoder struct {
|
||||
transform.NopResetter
|
||||
charmap *Charmap
|
||||
}
|
||||
|
||||
func (m charmapEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
loop:
|
||||
for nSrc < len(src) {
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
if m.charmap.asciiSuperset {
|
||||
nSrc++
|
||||
dst[nDst] = uint8(r)
|
||||
nDst++
|
||||
continue
|
||||
}
|
||||
size = 1
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
} else {
|
||||
err = internal.RepertoireError(m.charmap.replacement)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Binary search in [low, high) for that rune in the m.charmap.encode table.
|
||||
for low, high := int(m.charmap.low), 0x100; ; {
|
||||
if low >= high {
|
||||
err = internal.RepertoireError(m.charmap.replacement)
|
||||
break loop
|
||||
}
|
||||
mid := (low + high) / 2
|
||||
got := m.charmap.encode[mid]
|
||||
gotRune := rune(got & (1<<24 - 1))
|
||||
if gotRune < r {
|
||||
low = mid + 1
|
||||
} else if gotRune > r {
|
||||
high = mid
|
||||
} else {
|
||||
dst[nDst] = byte(got >> 24)
|
||||
nDst++
|
||||
break
|
||||
}
|
||||
}
|
||||
nSrc += size
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
// EncodeRune returns the Charmap's byte encoding of the rune r. ok is whether
|
||||
// r is in the Charmap's repertoire. If not, b is set to the Charmap's
|
||||
// replacement byte. This is often the ASCII substitute character '\x1a'.
|
||||
func (m *Charmap) EncodeRune(r rune) (b byte, ok bool) {
|
||||
if r < utf8.RuneSelf && m.asciiSuperset {
|
||||
return byte(r), true
|
||||
}
|
||||
for low, high := int(m.low), 0x100; ; {
|
||||
if low >= high {
|
||||
return m.replacement, false
|
||||
}
|
||||
mid := (low + high) / 2
|
||||
got := m.encode[mid]
|
||||
gotRune := rune(got & (1<<24 - 1))
|
||||
if gotRune < r {
|
||||
low = mid + 1
|
||||
} else if gotRune > r {
|
||||
high = mid
|
||||
} else {
|
||||
return byte(got >> 24), true
|
||||
}
|
||||
}
|
||||
}
|
7410
vendor/golang.org/x/text/encoding/charmap/tables.go
generated
vendored
7410
vendor/golang.org/x/text/encoding/charmap/tables.go
generated
vendored
File diff suppressed because it is too large
Load Diff
335
vendor/golang.org/x/text/encoding/encoding.go
generated
vendored
335
vendor/golang.org/x/text/encoding/encoding.go
generated
vendored
@ -1,335 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package encoding defines an interface for character encodings, such as Shift
|
||||
// JIS and Windows 1252, that can convert to and from UTF-8.
|
||||
//
|
||||
// Encoding implementations are provided in other packages, such as
|
||||
// golang.org/x/text/encoding/charmap and
|
||||
// golang.org/x/text/encoding/japanese.
|
||||
package encoding // import "golang.org/x/text/encoding"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"strconv"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// TODO:
|
||||
// - There seems to be some inconsistency in when decoders return errors
|
||||
// and when not. Also documentation seems to suggest they shouldn't return
|
||||
// errors at all (except for UTF-16).
|
||||
// - Encoders seem to rely on or at least benefit from the input being in NFC
|
||||
// normal form. Perhaps add an example how users could prepare their output.
|
||||
|
||||
// Encoding is a character set encoding that can be transformed to and from
|
||||
// UTF-8.
|
||||
type Encoding interface {
|
||||
// NewDecoder returns a Decoder.
|
||||
NewDecoder() *Decoder
|
||||
|
||||
// NewEncoder returns an Encoder.
|
||||
NewEncoder() *Encoder
|
||||
}
|
||||
|
||||
// A Decoder converts bytes to UTF-8. It implements transform.Transformer.
|
||||
//
|
||||
// Transforming source bytes that are not of that encoding will not result in an
|
||||
// error per se. Each byte that cannot be transcoded will be represented in the
|
||||
// output by the UTF-8 encoding of '\uFFFD', the replacement rune.
|
||||
type Decoder struct {
|
||||
transform.Transformer
|
||||
|
||||
// This forces external creators of Decoders to use names in struct
|
||||
// initializers, allowing for future extendibility without having to break
|
||||
// code.
|
||||
_ struct{}
|
||||
}
|
||||
|
||||
// Bytes converts the given encoded bytes to UTF-8. It returns the converted
|
||||
// bytes or nil, err if any error occurred.
|
||||
func (d *Decoder) Bytes(b []byte) ([]byte, error) {
|
||||
b, _, err := transform.Bytes(d, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// String converts the given encoded string to UTF-8. It returns the converted
|
||||
// string or "", err if any error occurred.
|
||||
func (d *Decoder) String(s string) (string, error) {
|
||||
s, _, err := transform.String(d, s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Reader wraps another Reader to decode its bytes.
|
||||
//
|
||||
// The Decoder may not be used for any other operation as long as the returned
|
||||
// Reader is in use.
|
||||
func (d *Decoder) Reader(r io.Reader) io.Reader {
|
||||
return transform.NewReader(r, d)
|
||||
}
|
||||
|
||||
// An Encoder converts bytes from UTF-8. It implements transform.Transformer.
|
||||
//
|
||||
// Each rune that cannot be transcoded will result in an error. In this case,
|
||||
// the transform will consume all source byte up to, not including the offending
|
||||
// rune. Transforming source bytes that are not valid UTF-8 will be replaced by
|
||||
// `\uFFFD`. To return early with an error instead, use transform.Chain to
|
||||
// preprocess the data with a UTF8Validator.
|
||||
type Encoder struct {
|
||||
transform.Transformer
|
||||
|
||||
// This forces external creators of Encoders to use names in struct
|
||||
// initializers, allowing for future extendibility without having to break
|
||||
// code.
|
||||
_ struct{}
|
||||
}
|
||||
|
||||
// Bytes converts bytes from UTF-8. It returns the converted bytes or nil, err if
|
||||
// any error occurred.
|
||||
func (e *Encoder) Bytes(b []byte) ([]byte, error) {
|
||||
b, _, err := transform.Bytes(e, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// String converts a string from UTF-8. It returns the converted string or
|
||||
// "", err if any error occurred.
|
||||
func (e *Encoder) String(s string) (string, error) {
|
||||
s, _, err := transform.String(e, s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Writer wraps another Writer to encode its UTF-8 output.
|
||||
//
|
||||
// The Encoder may not be used for any other operation as long as the returned
|
||||
// Writer is in use.
|
||||
func (e *Encoder) Writer(w io.Writer) io.Writer {
|
||||
return transform.NewWriter(w, e)
|
||||
}
|
||||
|
||||
// ASCIISub is the ASCII substitute character, as recommended by
|
||||
// https://unicode.org/reports/tr36/#Text_Comparison
|
||||
const ASCIISub = '\x1a'
|
||||
|
||||
// Nop is the nop encoding. Its transformed bytes are the same as the source
|
||||
// bytes; it does not replace invalid UTF-8 sequences.
|
||||
var Nop Encoding = nop{}
|
||||
|
||||
type nop struct{}
|
||||
|
||||
func (nop) NewDecoder() *Decoder {
|
||||
return &Decoder{Transformer: transform.Nop}
|
||||
}
|
||||
func (nop) NewEncoder() *Encoder {
|
||||
return &Encoder{Transformer: transform.Nop}
|
||||
}
|
||||
|
||||
// Replacement is the replacement encoding. Decoding from the replacement
|
||||
// encoding yields a single '\uFFFD' replacement rune. Encoding from UTF-8 to
|
||||
// the replacement encoding yields the same as the source bytes except that
|
||||
// invalid UTF-8 is converted to '\uFFFD'.
|
||||
//
|
||||
// It is defined at http://encoding.spec.whatwg.org/#replacement
|
||||
var Replacement Encoding = replacement{}
|
||||
|
||||
type replacement struct{}
|
||||
|
||||
func (replacement) NewDecoder() *Decoder {
|
||||
return &Decoder{Transformer: replacementDecoder{}}
|
||||
}
|
||||
|
||||
func (replacement) NewEncoder() *Encoder {
|
||||
return &Encoder{Transformer: replacementEncoder{}}
|
||||
}
|
||||
|
||||
func (replacement) ID() (mib identifier.MIB, other string) {
|
||||
return identifier.Replacement, ""
|
||||
}
|
||||
|
||||
type replacementDecoder struct{ transform.NopResetter }
|
||||
|
||||
func (replacementDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
if len(dst) < 3 {
|
||||
return 0, 0, transform.ErrShortDst
|
||||
}
|
||||
if atEOF {
|
||||
const fffd = "\ufffd"
|
||||
dst[0] = fffd[0]
|
||||
dst[1] = fffd[1]
|
||||
dst[2] = fffd[2]
|
||||
nDst = 3
|
||||
}
|
||||
return nDst, len(src), nil
|
||||
}
|
||||
|
||||
type replacementEncoder struct{ transform.NopResetter }
|
||||
|
||||
func (replacementEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
r = '\ufffd'
|
||||
}
|
||||
}
|
||||
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
// HTMLEscapeUnsupported wraps encoders to replace source runes outside the
|
||||
// repertoire of the destination encoding with HTML escape sequences.
|
||||
//
|
||||
// This wrapper exists to comply to URL and HTML forms requiring a
|
||||
// non-terminating legacy encoder. The produced sequences may lead to data
|
||||
// loss as they are indistinguishable from legitimate input. To avoid this
|
||||
// issue, use UTF-8 encodings whenever possible.
|
||||
func HTMLEscapeUnsupported(e *Encoder) *Encoder {
|
||||
return &Encoder{Transformer: &errorHandler{e, errorToHTML}}
|
||||
}
|
||||
|
||||
// ReplaceUnsupported wraps encoders to replace source runes outside the
|
||||
// repertoire of the destination encoding with an encoding-specific
|
||||
// replacement.
|
||||
//
|
||||
// This wrapper is only provided for backwards compatibility and legacy
|
||||
// handling. Its use is strongly discouraged. Use UTF-8 whenever possible.
|
||||
func ReplaceUnsupported(e *Encoder) *Encoder {
|
||||
return &Encoder{Transformer: &errorHandler{e, errorToReplacement}}
|
||||
}
|
||||
|
||||
type errorHandler struct {
|
||||
*Encoder
|
||||
handler func(dst []byte, r rune, err repertoireError) (n int, ok bool)
|
||||
}
|
||||
|
||||
// TODO: consider making this error public in some form.
|
||||
type repertoireError interface {
|
||||
Replacement() byte
|
||||
}
|
||||
|
||||
func (h errorHandler) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
nDst, nSrc, err = h.Transformer.Transform(dst, src, atEOF)
|
||||
for err != nil {
|
||||
rerr, ok := err.(repertoireError)
|
||||
if !ok {
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
r, sz := utf8.DecodeRune(src[nSrc:])
|
||||
n, ok := h.handler(dst[nDst:], r, rerr)
|
||||
if !ok {
|
||||
return nDst, nSrc, transform.ErrShortDst
|
||||
}
|
||||
err = nil
|
||||
nDst += n
|
||||
if nSrc += sz; nSrc < len(src) {
|
||||
var dn, sn int
|
||||
dn, sn, err = h.Transformer.Transform(dst[nDst:], src[nSrc:], atEOF)
|
||||
nDst += dn
|
||||
nSrc += sn
|
||||
}
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
func errorToHTML(dst []byte, r rune, err repertoireError) (n int, ok bool) {
|
||||
buf := [8]byte{}
|
||||
b := strconv.AppendUint(buf[:0], uint64(r), 10)
|
||||
if n = len(b) + len("&#;"); n >= len(dst) {
|
||||
return 0, false
|
||||
}
|
||||
dst[0] = '&'
|
||||
dst[1] = '#'
|
||||
dst[copy(dst[2:], b)+2] = ';'
|
||||
return n, true
|
||||
}
|
||||
|
||||
func errorToReplacement(dst []byte, r rune, err repertoireError) (n int, ok bool) {
|
||||
if len(dst) == 0 {
|
||||
return 0, false
|
||||
}
|
||||
dst[0] = err.Replacement()
|
||||
return 1, true
|
||||
}
|
||||
|
||||
// ErrInvalidUTF8 means that a transformer encountered invalid UTF-8.
|
||||
var ErrInvalidUTF8 = errors.New("encoding: invalid UTF-8")
|
||||
|
||||
// UTF8Validator is a transformer that returns ErrInvalidUTF8 on the first
|
||||
// input byte that is not valid UTF-8.
|
||||
var UTF8Validator transform.Transformer = utf8Validator{}
|
||||
|
||||
type utf8Validator struct{ transform.NopResetter }
|
||||
|
||||
func (utf8Validator) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
n := len(src)
|
||||
if n > len(dst) {
|
||||
n = len(dst)
|
||||
}
|
||||
for i := 0; i < n; {
|
||||
if c := src[i]; c < utf8.RuneSelf {
|
||||
dst[i] = c
|
||||
i++
|
||||
continue
|
||||
}
|
||||
_, size := utf8.DecodeRune(src[i:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
err = ErrInvalidUTF8
|
||||
if !atEOF && !utf8.FullRune(src[i:]) {
|
||||
err = transform.ErrShortSrc
|
||||
}
|
||||
return i, i, err
|
||||
}
|
||||
if i+size > len(dst) {
|
||||
return i, i, transform.ErrShortDst
|
||||
}
|
||||
for ; size > 0; size-- {
|
||||
dst[i] = src[i]
|
||||
i++
|
||||
}
|
||||
}
|
||||
if len(src) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
}
|
||||
return n, n, err
|
||||
}
|
86
vendor/golang.org/x/text/encoding/htmlindex/htmlindex.go
generated
vendored
86
vendor/golang.org/x/text/encoding/htmlindex/htmlindex.go
generated
vendored
@ -1,86 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run gen.go
|
||||
|
||||
// Package htmlindex maps character set encoding names to Encodings as
|
||||
// recommended by the W3C for use in HTML 5. See http://www.w3.org/TR/encoding.
|
||||
package htmlindex
|
||||
|
||||
// TODO: perhaps have a "bare" version of the index (used by this package) that
|
||||
// is not pre-loaded with all encodings. Global variables in encodings prevent
|
||||
// the linker from being able to purge unneeded tables. This means that
|
||||
// referencing all encodings, as this package does for the default index, links
|
||||
// in all encodings unconditionally.
|
||||
//
|
||||
// This issue can be solved by either solving the linking issue (see
|
||||
// https://github.com/golang/go/issues/6330) or refactoring the encoding tables
|
||||
// (e.g. moving the tables to internal packages that do not use global
|
||||
// variables).
|
||||
|
||||
// TODO: allow canonicalizing names
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidName = errors.New("htmlindex: invalid encoding name")
|
||||
errUnknown = errors.New("htmlindex: unknown Encoding")
|
||||
errUnsupported = errors.New("htmlindex: this encoding is not supported")
|
||||
)
|
||||
|
||||
var (
|
||||
matcherOnce sync.Once
|
||||
matcher language.Matcher
|
||||
)
|
||||
|
||||
// LanguageDefault returns the canonical name of the default encoding for a
|
||||
// given language.
|
||||
func LanguageDefault(tag language.Tag) string {
|
||||
matcherOnce.Do(func() {
|
||||
tags := []language.Tag{}
|
||||
for _, t := range strings.Split(locales, " ") {
|
||||
tags = append(tags, language.MustParse(t))
|
||||
}
|
||||
matcher = language.NewMatcher(tags, language.PreferSameScript(true))
|
||||
})
|
||||
_, i, _ := matcher.Match(tag)
|
||||
return canonical[localeMap[i]] // Default is Windows-1252.
|
||||
}
|
||||
|
||||
// Get returns an Encoding for one of the names listed in
|
||||
// http://www.w3.org/TR/encoding using the Default Index. Matching is case-
|
||||
// insensitive.
|
||||
func Get(name string) (encoding.Encoding, error) {
|
||||
x, ok := nameMap[strings.ToLower(strings.TrimSpace(name))]
|
||||
if !ok {
|
||||
return nil, errInvalidName
|
||||
}
|
||||
return encodings[x], nil
|
||||
}
|
||||
|
||||
// Name reports the canonical name of the given Encoding. It will return
|
||||
// an error if e is not associated with a supported encoding scheme.
|
||||
func Name(e encoding.Encoding) (string, error) {
|
||||
id, ok := e.(identifier.Interface)
|
||||
if !ok {
|
||||
return "", errUnknown
|
||||
}
|
||||
mib, _ := id.ID()
|
||||
if mib == 0 {
|
||||
return "", errUnknown
|
||||
}
|
||||
v, ok := mibMap[mib]
|
||||
if !ok {
|
||||
return "", errUnsupported
|
||||
}
|
||||
return canonical[v], nil
|
||||
}
|
105
vendor/golang.org/x/text/encoding/htmlindex/map.go
generated
vendored
105
vendor/golang.org/x/text/encoding/htmlindex/map.go
generated
vendored
@ -1,105 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package htmlindex
|
||||
|
||||
import (
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/charmap"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/encoding/japanese"
|
||||
"golang.org/x/text/encoding/korean"
|
||||
"golang.org/x/text/encoding/simplifiedchinese"
|
||||
"golang.org/x/text/encoding/traditionalchinese"
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
)
|
||||
|
||||
// mibMap maps a MIB identifier to an htmlEncoding index.
|
||||
var mibMap = map[identifier.MIB]htmlEncoding{
|
||||
identifier.UTF8: utf8,
|
||||
identifier.UTF16BE: utf16be,
|
||||
identifier.UTF16LE: utf16le,
|
||||
identifier.IBM866: ibm866,
|
||||
identifier.ISOLatin2: iso8859_2,
|
||||
identifier.ISOLatin3: iso8859_3,
|
||||
identifier.ISOLatin4: iso8859_4,
|
||||
identifier.ISOLatinCyrillic: iso8859_5,
|
||||
identifier.ISOLatinArabic: iso8859_6,
|
||||
identifier.ISOLatinGreek: iso8859_7,
|
||||
identifier.ISOLatinHebrew: iso8859_8,
|
||||
identifier.ISO88598I: iso8859_8I,
|
||||
identifier.ISOLatin6: iso8859_10,
|
||||
identifier.ISO885913: iso8859_13,
|
||||
identifier.ISO885914: iso8859_14,
|
||||
identifier.ISO885915: iso8859_15,
|
||||
identifier.ISO885916: iso8859_16,
|
||||
identifier.KOI8R: koi8r,
|
||||
identifier.KOI8U: koi8u,
|
||||
identifier.Macintosh: macintosh,
|
||||
identifier.MacintoshCyrillic: macintoshCyrillic,
|
||||
identifier.Windows874: windows874,
|
||||
identifier.Windows1250: windows1250,
|
||||
identifier.Windows1251: windows1251,
|
||||
identifier.Windows1252: windows1252,
|
||||
identifier.Windows1253: windows1253,
|
||||
identifier.Windows1254: windows1254,
|
||||
identifier.Windows1255: windows1255,
|
||||
identifier.Windows1256: windows1256,
|
||||
identifier.Windows1257: windows1257,
|
||||
identifier.Windows1258: windows1258,
|
||||
identifier.XUserDefined: xUserDefined,
|
||||
identifier.GBK: gbk,
|
||||
identifier.GB18030: gb18030,
|
||||
identifier.Big5: big5,
|
||||
identifier.EUCPkdFmtJapanese: eucjp,
|
||||
identifier.ISO2022JP: iso2022jp,
|
||||
identifier.ShiftJIS: shiftJIS,
|
||||
identifier.EUCKR: euckr,
|
||||
identifier.Replacement: replacement,
|
||||
}
|
||||
|
||||
// encodings maps the internal htmlEncoding to an Encoding.
|
||||
// TODO: consider using a reusable index in encoding/internal.
|
||||
var encodings = [numEncodings]encoding.Encoding{
|
||||
utf8: unicode.UTF8,
|
||||
ibm866: charmap.CodePage866,
|
||||
iso8859_2: charmap.ISO8859_2,
|
||||
iso8859_3: charmap.ISO8859_3,
|
||||
iso8859_4: charmap.ISO8859_4,
|
||||
iso8859_5: charmap.ISO8859_5,
|
||||
iso8859_6: charmap.ISO8859_6,
|
||||
iso8859_7: charmap.ISO8859_7,
|
||||
iso8859_8: charmap.ISO8859_8,
|
||||
iso8859_8I: charmap.ISO8859_8I,
|
||||
iso8859_10: charmap.ISO8859_10,
|
||||
iso8859_13: charmap.ISO8859_13,
|
||||
iso8859_14: charmap.ISO8859_14,
|
||||
iso8859_15: charmap.ISO8859_15,
|
||||
iso8859_16: charmap.ISO8859_16,
|
||||
koi8r: charmap.KOI8R,
|
||||
koi8u: charmap.KOI8U,
|
||||
macintosh: charmap.Macintosh,
|
||||
windows874: charmap.Windows874,
|
||||
windows1250: charmap.Windows1250,
|
||||
windows1251: charmap.Windows1251,
|
||||
windows1252: charmap.Windows1252,
|
||||
windows1253: charmap.Windows1253,
|
||||
windows1254: charmap.Windows1254,
|
||||
windows1255: charmap.Windows1255,
|
||||
windows1256: charmap.Windows1256,
|
||||
windows1257: charmap.Windows1257,
|
||||
windows1258: charmap.Windows1258,
|
||||
macintoshCyrillic: charmap.MacintoshCyrillic,
|
||||
gbk: simplifiedchinese.GBK,
|
||||
gb18030: simplifiedchinese.GB18030,
|
||||
big5: traditionalchinese.Big5,
|
||||
eucjp: japanese.EUCJP,
|
||||
iso2022jp: japanese.ISO2022JP,
|
||||
shiftJIS: japanese.ShiftJIS,
|
||||
euckr: korean.EUCKR,
|
||||
replacement: encoding.Replacement,
|
||||
utf16be: unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM),
|
||||
utf16le: unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM),
|
||||
xUserDefined: charmap.XUserDefined,
|
||||
}
|
362
vendor/golang.org/x/text/encoding/htmlindex/tables.go
generated
vendored
362
vendor/golang.org/x/text/encoding/htmlindex/tables.go
generated
vendored
@ -1,362 +0,0 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
package htmlindex
|
||||
|
||||
type htmlEncoding byte
|
||||
|
||||
const (
|
||||
utf8 htmlEncoding = iota
|
||||
ibm866
|
||||
iso8859_2
|
||||
iso8859_3
|
||||
iso8859_4
|
||||
iso8859_5
|
||||
iso8859_6
|
||||
iso8859_7
|
||||
iso8859_8
|
||||
iso8859_8I
|
||||
iso8859_10
|
||||
iso8859_13
|
||||
iso8859_14
|
||||
iso8859_15
|
||||
iso8859_16
|
||||
koi8r
|
||||
koi8u
|
||||
macintosh
|
||||
windows874
|
||||
windows1250
|
||||
windows1251
|
||||
windows1252
|
||||
windows1253
|
||||
windows1254
|
||||
windows1255
|
||||
windows1256
|
||||
windows1257
|
||||
windows1258
|
||||
macintoshCyrillic
|
||||
gbk
|
||||
gb18030
|
||||
big5
|
||||
eucjp
|
||||
iso2022jp
|
||||
shiftJIS
|
||||
euckr
|
||||
replacement
|
||||
utf16be
|
||||
utf16le
|
||||
xUserDefined
|
||||
numEncodings
|
||||
)
|
||||
|
||||
var canonical = [numEncodings]string{
|
||||
"utf-8",
|
||||
"ibm866",
|
||||
"iso-8859-2",
|
||||
"iso-8859-3",
|
||||
"iso-8859-4",
|
||||
"iso-8859-5",
|
||||
"iso-8859-6",
|
||||
"iso-8859-7",
|
||||
"iso-8859-8",
|
||||
"iso-8859-8-i",
|
||||
"iso-8859-10",
|
||||
"iso-8859-13",
|
||||
"iso-8859-14",
|
||||
"iso-8859-15",
|
||||
"iso-8859-16",
|
||||
"koi8-r",
|
||||
"koi8-u",
|
||||
"macintosh",
|
||||
"windows-874",
|
||||
"windows-1250",
|
||||
"windows-1251",
|
||||
"windows-1252",
|
||||
"windows-1253",
|
||||
"windows-1254",
|
||||
"windows-1255",
|
||||
"windows-1256",
|
||||
"windows-1257",
|
||||
"windows-1258",
|
||||
"x-mac-cyrillic",
|
||||
"gbk",
|
||||
"gb18030",
|
||||
"big5",
|
||||
"euc-jp",
|
||||
"iso-2022-jp",
|
||||
"shift_jis",
|
||||
"euc-kr",
|
||||
"replacement",
|
||||
"utf-16be",
|
||||
"utf-16le",
|
||||
"x-user-defined",
|
||||
}
|
||||
|
||||
var nameMap = map[string]htmlEncoding{
|
||||
"unicode-1-1-utf-8": utf8,
|
||||
"unicode11utf8": utf8,
|
||||
"unicode20utf8": utf8,
|
||||
"utf-8": utf8,
|
||||
"utf8": utf8,
|
||||
"x-unicode20utf8": utf8,
|
||||
"866": ibm866,
|
||||
"cp866": ibm866,
|
||||
"csibm866": ibm866,
|
||||
"ibm866": ibm866,
|
||||
"csisolatin2": iso8859_2,
|
||||
"iso-8859-2": iso8859_2,
|
||||
"iso-ir-101": iso8859_2,
|
||||
"iso8859-2": iso8859_2,
|
||||
"iso88592": iso8859_2,
|
||||
"iso_8859-2": iso8859_2,
|
||||
"iso_8859-2:1987": iso8859_2,
|
||||
"l2": iso8859_2,
|
||||
"latin2": iso8859_2,
|
||||
"csisolatin3": iso8859_3,
|
||||
"iso-8859-3": iso8859_3,
|
||||
"iso-ir-109": iso8859_3,
|
||||
"iso8859-3": iso8859_3,
|
||||
"iso88593": iso8859_3,
|
||||
"iso_8859-3": iso8859_3,
|
||||
"iso_8859-3:1988": iso8859_3,
|
||||
"l3": iso8859_3,
|
||||
"latin3": iso8859_3,
|
||||
"csisolatin4": iso8859_4,
|
||||
"iso-8859-4": iso8859_4,
|
||||
"iso-ir-110": iso8859_4,
|
||||
"iso8859-4": iso8859_4,
|
||||
"iso88594": iso8859_4,
|
||||
"iso_8859-4": iso8859_4,
|
||||
"iso_8859-4:1988": iso8859_4,
|
||||
"l4": iso8859_4,
|
||||
"latin4": iso8859_4,
|
||||
"csisolatincyrillic": iso8859_5,
|
||||
"cyrillic": iso8859_5,
|
||||
"iso-8859-5": iso8859_5,
|
||||
"iso-ir-144": iso8859_5,
|
||||
"iso8859-5": iso8859_5,
|
||||
"iso88595": iso8859_5,
|
||||
"iso_8859-5": iso8859_5,
|
||||
"iso_8859-5:1988": iso8859_5,
|
||||
"arabic": iso8859_6,
|
||||
"asmo-708": iso8859_6,
|
||||
"csiso88596e": iso8859_6,
|
||||
"csiso88596i": iso8859_6,
|
||||
"csisolatinarabic": iso8859_6,
|
||||
"ecma-114": iso8859_6,
|
||||
"iso-8859-6": iso8859_6,
|
||||
"iso-8859-6-e": iso8859_6,
|
||||
"iso-8859-6-i": iso8859_6,
|
||||
"iso-ir-127": iso8859_6,
|
||||
"iso8859-6": iso8859_6,
|
||||
"iso88596": iso8859_6,
|
||||
"iso_8859-6": iso8859_6,
|
||||
"iso_8859-6:1987": iso8859_6,
|
||||
"csisolatingreek": iso8859_7,
|
||||
"ecma-118": iso8859_7,
|
||||
"elot_928": iso8859_7,
|
||||
"greek": iso8859_7,
|
||||
"greek8": iso8859_7,
|
||||
"iso-8859-7": iso8859_7,
|
||||
"iso-ir-126": iso8859_7,
|
||||
"iso8859-7": iso8859_7,
|
||||
"iso88597": iso8859_7,
|
||||
"iso_8859-7": iso8859_7,
|
||||
"iso_8859-7:1987": iso8859_7,
|
||||
"sun_eu_greek": iso8859_7,
|
||||
"csiso88598e": iso8859_8,
|
||||
"csisolatinhebrew": iso8859_8,
|
||||
"hebrew": iso8859_8,
|
||||
"iso-8859-8": iso8859_8,
|
||||
"iso-8859-8-e": iso8859_8,
|
||||
"iso-ir-138": iso8859_8,
|
||||
"iso8859-8": iso8859_8,
|
||||
"iso88598": iso8859_8,
|
||||
"iso_8859-8": iso8859_8,
|
||||
"iso_8859-8:1988": iso8859_8,
|
||||
"visual": iso8859_8,
|
||||
"csiso88598i": iso8859_8I,
|
||||
"iso-8859-8-i": iso8859_8I,
|
||||
"logical": iso8859_8I,
|
||||
"csisolatin6": iso8859_10,
|
||||
"iso-8859-10": iso8859_10,
|
||||
"iso-ir-157": iso8859_10,
|
||||
"iso8859-10": iso8859_10,
|
||||
"iso885910": iso8859_10,
|
||||
"l6": iso8859_10,
|
||||
"latin6": iso8859_10,
|
||||
"iso-8859-13": iso8859_13,
|
||||
"iso8859-13": iso8859_13,
|
||||
"iso885913": iso8859_13,
|
||||
"iso-8859-14": iso8859_14,
|
||||
"iso8859-14": iso8859_14,
|
||||
"iso885914": iso8859_14,
|
||||
"csisolatin9": iso8859_15,
|
||||
"iso-8859-15": iso8859_15,
|
||||
"iso8859-15": iso8859_15,
|
||||
"iso885915": iso8859_15,
|
||||
"iso_8859-15": iso8859_15,
|
||||
"l9": iso8859_15,
|
||||
"iso-8859-16": iso8859_16,
|
||||
"cskoi8r": koi8r,
|
||||
"koi": koi8r,
|
||||
"koi8": koi8r,
|
||||
"koi8-r": koi8r,
|
||||
"koi8_r": koi8r,
|
||||
"koi8-ru": koi8u,
|
||||
"koi8-u": koi8u,
|
||||
"csmacintosh": macintosh,
|
||||
"mac": macintosh,
|
||||
"macintosh": macintosh,
|
||||
"x-mac-roman": macintosh,
|
||||
"dos-874": windows874,
|
||||
"iso-8859-11": windows874,
|
||||
"iso8859-11": windows874,
|
||||
"iso885911": windows874,
|
||||
"tis-620": windows874,
|
||||
"windows-874": windows874,
|
||||
"cp1250": windows1250,
|
||||
"windows-1250": windows1250,
|
||||
"x-cp1250": windows1250,
|
||||
"cp1251": windows1251,
|
||||
"windows-1251": windows1251,
|
||||
"x-cp1251": windows1251,
|
||||
"ansi_x3.4-1968": windows1252,
|
||||
"ascii": windows1252,
|
||||
"cp1252": windows1252,
|
||||
"cp819": windows1252,
|
||||
"csisolatin1": windows1252,
|
||||
"ibm819": windows1252,
|
||||
"iso-8859-1": windows1252,
|
||||
"iso-ir-100": windows1252,
|
||||
"iso8859-1": windows1252,
|
||||
"iso88591": windows1252,
|
||||
"iso_8859-1": windows1252,
|
||||
"iso_8859-1:1987": windows1252,
|
||||
"l1": windows1252,
|
||||
"latin1": windows1252,
|
||||
"us-ascii": windows1252,
|
||||
"windows-1252": windows1252,
|
||||
"x-cp1252": windows1252,
|
||||
"cp1253": windows1253,
|
||||
"windows-1253": windows1253,
|
||||
"x-cp1253": windows1253,
|
||||
"cp1254": windows1254,
|
||||
"csisolatin5": windows1254,
|
||||
"iso-8859-9": windows1254,
|
||||
"iso-ir-148": windows1254,
|
||||
"iso8859-9": windows1254,
|
||||
"iso88599": windows1254,
|
||||
"iso_8859-9": windows1254,
|
||||
"iso_8859-9:1989": windows1254,
|
||||
"l5": windows1254,
|
||||
"latin5": windows1254,
|
||||
"windows-1254": windows1254,
|
||||
"x-cp1254": windows1254,
|
||||
"cp1255": windows1255,
|
||||
"windows-1255": windows1255,
|
||||
"x-cp1255": windows1255,
|
||||
"cp1256": windows1256,
|
||||
"windows-1256": windows1256,
|
||||
"x-cp1256": windows1256,
|
||||
"cp1257": windows1257,
|
||||
"windows-1257": windows1257,
|
||||
"x-cp1257": windows1257,
|
||||
"cp1258": windows1258,
|
||||
"windows-1258": windows1258,
|
||||
"x-cp1258": windows1258,
|
||||
"x-mac-cyrillic": macintoshCyrillic,
|
||||
"x-mac-ukrainian": macintoshCyrillic,
|
||||
"chinese": gbk,
|
||||
"csgb2312": gbk,
|
||||
"csiso58gb231280": gbk,
|
||||
"gb2312": gbk,
|
||||
"gb_2312": gbk,
|
||||
"gb_2312-80": gbk,
|
||||
"gbk": gbk,
|
||||
"iso-ir-58": gbk,
|
||||
"x-gbk": gbk,
|
||||
"gb18030": gb18030,
|
||||
"big5": big5,
|
||||
"big5-hkscs": big5,
|
||||
"cn-big5": big5,
|
||||
"csbig5": big5,
|
||||
"x-x-big5": big5,
|
||||
"cseucpkdfmtjapanese": eucjp,
|
||||
"euc-jp": eucjp,
|
||||
"x-euc-jp": eucjp,
|
||||
"csiso2022jp": iso2022jp,
|
||||
"iso-2022-jp": iso2022jp,
|
||||
"csshiftjis": shiftJIS,
|
||||
"ms932": shiftJIS,
|
||||
"ms_kanji": shiftJIS,
|
||||
"shift-jis": shiftJIS,
|
||||
"shift_jis": shiftJIS,
|
||||
"sjis": shiftJIS,
|
||||
"windows-31j": shiftJIS,
|
||||
"x-sjis": shiftJIS,
|
||||
"cseuckr": euckr,
|
||||
"csksc56011987": euckr,
|
||||
"euc-kr": euckr,
|
||||
"iso-ir-149": euckr,
|
||||
"korean": euckr,
|
||||
"ks_c_5601-1987": euckr,
|
||||
"ks_c_5601-1989": euckr,
|
||||
"ksc5601": euckr,
|
||||
"ksc_5601": euckr,
|
||||
"windows-949": euckr,
|
||||
"csiso2022kr": replacement,
|
||||
"hz-gb-2312": replacement,
|
||||
"iso-2022-cn": replacement,
|
||||
"iso-2022-cn-ext": replacement,
|
||||
"iso-2022-kr": replacement,
|
||||
"replacement": replacement,
|
||||
"unicodefffe": utf16be,
|
||||
"utf-16be": utf16be,
|
||||
"csunicode": utf16le,
|
||||
"iso-10646-ucs-2": utf16le,
|
||||
"ucs-2": utf16le,
|
||||
"unicode": utf16le,
|
||||
"unicodefeff": utf16le,
|
||||
"utf-16": utf16le,
|
||||
"utf-16le": utf16le,
|
||||
"x-user-defined": xUserDefined,
|
||||
}
|
||||
|
||||
var localeMap = []htmlEncoding{
|
||||
windows1252, // und_Latn
|
||||
windows1256, // ar
|
||||
windows1251, // ba
|
||||
windows1251, // be
|
||||
windows1251, // bg
|
||||
windows1250, // cs
|
||||
iso8859_7, // el
|
||||
windows1257, // et
|
||||
windows1256, // fa
|
||||
windows1255, // he
|
||||
windows1250, // hr
|
||||
iso8859_2, // hu
|
||||
shiftJIS, // ja
|
||||
windows1251, // kk
|
||||
euckr, // ko
|
||||
windows1254, // ku
|
||||
windows1251, // ky
|
||||
windows1257, // lt
|
||||
windows1257, // lv
|
||||
windows1251, // mk
|
||||
iso8859_2, // pl
|
||||
windows1251, // ru
|
||||
windows1251, // sah
|
||||
windows1250, // sk
|
||||
iso8859_2, // sl
|
||||
windows1251, // sr
|
||||
windows1251, // tg
|
||||
windows874, // th
|
||||
windows1254, // tr
|
||||
windows1251, // tt
|
||||
windows1251, // uk
|
||||
windows1258, // vi
|
||||
gb18030, // zh-hans
|
||||
big5, // zh-hant
|
||||
}
|
||||
|
||||
const locales = "und_Latn ar ba be bg cs el et fa he hr hu ja kk ko ku ky lt lv mk pl ru sah sk sl sr tg th tr tt uk vi zh-hans zh-hant"
|
81
vendor/golang.org/x/text/encoding/internal/identifier/identifier.go
generated
vendored
81
vendor/golang.org/x/text/encoding/internal/identifier/identifier.go
generated
vendored
@ -1,81 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run gen.go
|
||||
|
||||
// Package identifier defines the contract between implementations of Encoding
|
||||
// and Index by defining identifiers that uniquely identify standardized coded
|
||||
// character sets (CCS) and character encoding schemes (CES), which we will
|
||||
// together refer to as encodings, for which Encoding implementations provide
|
||||
// converters to and from UTF-8. This package is typically only of concern to
|
||||
// implementers of Indexes and Encodings.
|
||||
//
|
||||
// One part of the identifier is the MIB code, which is defined by IANA and
|
||||
// uniquely identifies a CCS or CES. Each code is associated with data that
|
||||
// references authorities, official documentation as well as aliases and MIME
|
||||
// names.
|
||||
//
|
||||
// Not all CESs are covered by the IANA registry. The "other" string that is
|
||||
// returned by ID can be used to identify other character sets or versions of
|
||||
// existing ones.
|
||||
//
|
||||
// It is recommended that each package that provides a set of Encodings provide
|
||||
// the All and Common variables to reference all supported encodings and
|
||||
// commonly used subset. This allows Index implementations to include all
|
||||
// available encodings without explicitly referencing or knowing about them.
|
||||
package identifier
|
||||
|
||||
// Note: this package is internal, but could be made public if there is a need
|
||||
// for writing third-party Indexes and Encodings.
|
||||
|
||||
// References:
|
||||
// - http://source.icu-project.org/repos/icu/icu/trunk/source/data/mappings/convrtrs.txt
|
||||
// - http://www.iana.org/assignments/character-sets/character-sets.xhtml
|
||||
// - http://www.iana.org/assignments/ianacharset-mib/ianacharset-mib
|
||||
// - http://www.ietf.org/rfc/rfc2978.txt
|
||||
// - https://www.unicode.org/reports/tr22/
|
||||
// - http://www.w3.org/TR/encoding/
|
||||
// - https://encoding.spec.whatwg.org/
|
||||
// - https://encoding.spec.whatwg.org/encodings.json
|
||||
// - https://tools.ietf.org/html/rfc6657#section-5
|
||||
|
||||
// Interface can be implemented by Encodings to define the CCS or CES for which
|
||||
// it implements conversions.
|
||||
type Interface interface {
|
||||
// ID returns an encoding identifier. Exactly one of the mib and other
|
||||
// values should be non-zero.
|
||||
//
|
||||
// In the usual case it is only necessary to indicate the MIB code. The
|
||||
// other string can be used to specify encodings for which there is no MIB,
|
||||
// such as "x-mac-dingbat".
|
||||
//
|
||||
// The other string may only contain the characters a-z, A-Z, 0-9, - and _.
|
||||
ID() (mib MIB, other string)
|
||||
|
||||
// NOTE: the restrictions on the encoding are to allow extending the syntax
|
||||
// with additional information such as versions, vendors and other variants.
|
||||
}
|
||||
|
||||
// A MIB identifies an encoding. It is derived from the IANA MIB codes and adds
|
||||
// some identifiers for some encodings that are not covered by the IANA
|
||||
// standard.
|
||||
//
|
||||
// See http://www.iana.org/assignments/ianacharset-mib.
|
||||
type MIB uint16
|
||||
|
||||
// These additional MIB types are not defined in IANA. They are added because
|
||||
// they are common and defined within the text repo.
|
||||
const (
|
||||
// Unofficial marks the start of encodings not registered by IANA.
|
||||
Unofficial MIB = 10000 + iota
|
||||
|
||||
// Replacement is the WhatWG replacement encoding.
|
||||
Replacement
|
||||
|
||||
// XUserDefined is the code for x-user-defined.
|
||||
XUserDefined
|
||||
|
||||
// MacintoshCyrillic is the code for x-mac-cyrillic.
|
||||
MacintoshCyrillic
|
||||
)
|
1627
vendor/golang.org/x/text/encoding/internal/identifier/mib.go
generated
vendored
1627
vendor/golang.org/x/text/encoding/internal/identifier/mib.go
generated
vendored
File diff suppressed because it is too large
Load Diff
75
vendor/golang.org/x/text/encoding/internal/internal.go
generated
vendored
75
vendor/golang.org/x/text/encoding/internal/internal.go
generated
vendored
@ -1,75 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package internal contains code that is shared among encoding implementations.
|
||||
package internal
|
||||
|
||||
import (
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// Encoding is an implementation of the Encoding interface that adds the String
|
||||
// and ID methods to an existing encoding.
|
||||
type Encoding struct {
|
||||
encoding.Encoding
|
||||
Name string
|
||||
MIB identifier.MIB
|
||||
}
|
||||
|
||||
// _ verifies that Encoding implements identifier.Interface.
|
||||
var _ identifier.Interface = (*Encoding)(nil)
|
||||
|
||||
func (e *Encoding) String() string {
|
||||
return e.Name
|
||||
}
|
||||
|
||||
func (e *Encoding) ID() (mib identifier.MIB, other string) {
|
||||
return e.MIB, ""
|
||||
}
|
||||
|
||||
// SimpleEncoding is an Encoding that combines two Transformers.
|
||||
type SimpleEncoding struct {
|
||||
Decoder transform.Transformer
|
||||
Encoder transform.Transformer
|
||||
}
|
||||
|
||||
func (e *SimpleEncoding) NewDecoder() *encoding.Decoder {
|
||||
return &encoding.Decoder{Transformer: e.Decoder}
|
||||
}
|
||||
|
||||
func (e *SimpleEncoding) NewEncoder() *encoding.Encoder {
|
||||
return &encoding.Encoder{Transformer: e.Encoder}
|
||||
}
|
||||
|
||||
// FuncEncoding is an Encoding that combines two functions returning a new
|
||||
// Transformer.
|
||||
type FuncEncoding struct {
|
||||
Decoder func() transform.Transformer
|
||||
Encoder func() transform.Transformer
|
||||
}
|
||||
|
||||
func (e FuncEncoding) NewDecoder() *encoding.Decoder {
|
||||
return &encoding.Decoder{Transformer: e.Decoder()}
|
||||
}
|
||||
|
||||
func (e FuncEncoding) NewEncoder() *encoding.Encoder {
|
||||
return &encoding.Encoder{Transformer: e.Encoder()}
|
||||
}
|
||||
|
||||
// A RepertoireError indicates a rune is not in the repertoire of a destination
|
||||
// encoding. It is associated with an encoding-specific suggested replacement
|
||||
// byte.
|
||||
type RepertoireError byte
|
||||
|
||||
// Error implements the error interface.
|
||||
func (r RepertoireError) Error() string {
|
||||
return "encoding: rune not supported by encoding."
|
||||
}
|
||||
|
||||
// Replacement returns the replacement string associated with this error.
|
||||
func (r RepertoireError) Replacement() byte { return byte(r) }
|
||||
|
||||
var ErrASCIIReplacement = RepertoireError(encoding.ASCIISub)
|
12
vendor/golang.org/x/text/encoding/japanese/all.go
generated
vendored
12
vendor/golang.org/x/text/encoding/japanese/all.go
generated
vendored
@ -1,12 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package japanese
|
||||
|
||||
import (
|
||||
"golang.org/x/text/encoding"
|
||||
)
|
||||
|
||||
// All is a list of all defined encodings in this package.
|
||||
var All = []encoding.Encoding{EUCJP, ISO2022JP, ShiftJIS}
|
225
vendor/golang.org/x/text/encoding/japanese/eucjp.go
generated
vendored
225
vendor/golang.org/x/text/encoding/japanese/eucjp.go
generated
vendored
@ -1,225 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package japanese
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// EUCJP is the EUC-JP encoding.
|
||||
var EUCJP encoding.Encoding = &eucJP
|
||||
|
||||
var eucJP = internal.Encoding{
|
||||
&internal.SimpleEncoding{eucJPDecoder{}, eucJPEncoder{}},
|
||||
"EUC-JP",
|
||||
identifier.EUCPkdFmtJapanese,
|
||||
}
|
||||
|
||||
type eucJPDecoder struct{ transform.NopResetter }
|
||||
|
||||
// See https://encoding.spec.whatwg.org/#euc-jp-decoder.
|
||||
func (eucJPDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
loop:
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
switch c0 := src[nSrc]; {
|
||||
case c0 < utf8.RuneSelf:
|
||||
r, size = rune(c0), 1
|
||||
|
||||
case c0 == 0x8e:
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
break
|
||||
}
|
||||
c1 := src[nSrc+1]
|
||||
switch {
|
||||
case c1 < 0xa1:
|
||||
r, size = utf8.RuneError, 1
|
||||
case c1 > 0xdf:
|
||||
r, size = utf8.RuneError, 2
|
||||
if c1 == 0xff {
|
||||
size = 1
|
||||
}
|
||||
default:
|
||||
r, size = rune(c1)+(0xff61-0xa1), 2
|
||||
}
|
||||
case c0 == 0x8f:
|
||||
if nSrc+2 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
if p := nSrc + 1; p < len(src) && 0xa1 <= src[p] && src[p] < 0xfe {
|
||||
size = 2
|
||||
}
|
||||
break
|
||||
}
|
||||
c1 := src[nSrc+1]
|
||||
if c1 < 0xa1 || 0xfe < c1 {
|
||||
r, size = utf8.RuneError, 1
|
||||
break
|
||||
}
|
||||
c2 := src[nSrc+2]
|
||||
if c2 < 0xa1 || 0xfe < c2 {
|
||||
r, size = utf8.RuneError, 2
|
||||
break
|
||||
}
|
||||
r, size = utf8.RuneError, 3
|
||||
if i := int(c1-0xa1)*94 + int(c2-0xa1); i < len(jis0212Decode) {
|
||||
r = rune(jis0212Decode[i])
|
||||
if r == 0 {
|
||||
r = utf8.RuneError
|
||||
}
|
||||
}
|
||||
|
||||
case 0xa1 <= c0 && c0 <= 0xfe:
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
break
|
||||
}
|
||||
c1 := src[nSrc+1]
|
||||
if c1 < 0xa1 || 0xfe < c1 {
|
||||
r, size = utf8.RuneError, 1
|
||||
break
|
||||
}
|
||||
r, size = utf8.RuneError, 2
|
||||
if i := int(c0-0xa1)*94 + int(c1-0xa1); i < len(jis0208Decode) {
|
||||
r = rune(jis0208Decode[i])
|
||||
if r == 0 {
|
||||
r = utf8.RuneError
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
r, size = utf8.RuneError, 1
|
||||
}
|
||||
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type eucJPEncoder struct{ transform.NopResetter }
|
||||
|
||||
func (eucJPEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// func init checks that the switch covers all tables.
|
||||
switch {
|
||||
case encode0Low <= r && r < encode0High:
|
||||
if r = rune(encode0[r-encode0Low]); r != 0 {
|
||||
goto write2or3
|
||||
}
|
||||
case encode1Low <= r && r < encode1High:
|
||||
if r = rune(encode1[r-encode1Low]); r != 0 {
|
||||
goto write2or3
|
||||
}
|
||||
case encode2Low <= r && r < encode2High:
|
||||
if r = rune(encode2[r-encode2Low]); r != 0 {
|
||||
goto write2or3
|
||||
}
|
||||
case encode3Low <= r && r < encode3High:
|
||||
if r = rune(encode3[r-encode3Low]); r != 0 {
|
||||
goto write2or3
|
||||
}
|
||||
case encode4Low <= r && r < encode4High:
|
||||
if r = rune(encode4[r-encode4Low]); r != 0 {
|
||||
goto write2or3
|
||||
}
|
||||
case encode5Low <= r && r < encode5High:
|
||||
if 0xff61 <= r && r < 0xffa0 {
|
||||
goto write2
|
||||
}
|
||||
if r = rune(encode5[r-encode5Low]); r != 0 {
|
||||
goto write2or3
|
||||
}
|
||||
}
|
||||
err = internal.ErrASCIIReplacement
|
||||
break
|
||||
}
|
||||
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r)
|
||||
nDst++
|
||||
continue
|
||||
|
||||
write2or3:
|
||||
if r>>tableShift == jis0208 {
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if nDst+3 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = 0x8f
|
||||
nDst++
|
||||
}
|
||||
dst[nDst+0] = 0xa1 + uint8(r>>codeShift)&codeMask
|
||||
dst[nDst+1] = 0xa1 + uint8(r)&codeMask
|
||||
nDst += 2
|
||||
continue
|
||||
|
||||
write2:
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = 0x8e
|
||||
dst[nDst+1] = uint8(r - (0xff61 - 0xa1))
|
||||
nDst += 2
|
||||
continue
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Check that the hard-coded encode switch covers all tables.
|
||||
if numEncodeTables != 6 {
|
||||
panic("bad numEncodeTables")
|
||||
}
|
||||
}
|
299
vendor/golang.org/x/text/encoding/japanese/iso2022jp.go
generated
vendored
299
vendor/golang.org/x/text/encoding/japanese/iso2022jp.go
generated
vendored
@ -1,299 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package japanese
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// ISO2022JP is the ISO-2022-JP encoding.
|
||||
var ISO2022JP encoding.Encoding = &iso2022JP
|
||||
|
||||
var iso2022JP = internal.Encoding{
|
||||
internal.FuncEncoding{iso2022JPNewDecoder, iso2022JPNewEncoder},
|
||||
"ISO-2022-JP",
|
||||
identifier.ISO2022JP,
|
||||
}
|
||||
|
||||
func iso2022JPNewDecoder() transform.Transformer {
|
||||
return new(iso2022JPDecoder)
|
||||
}
|
||||
|
||||
func iso2022JPNewEncoder() transform.Transformer {
|
||||
return new(iso2022JPEncoder)
|
||||
}
|
||||
|
||||
const (
|
||||
asciiState = iota
|
||||
katakanaState
|
||||
jis0208State
|
||||
jis0212State
|
||||
)
|
||||
|
||||
const asciiEsc = 0x1b
|
||||
|
||||
type iso2022JPDecoder int
|
||||
|
||||
func (d *iso2022JPDecoder) Reset() {
|
||||
*d = asciiState
|
||||
}
|
||||
|
||||
func (d *iso2022JPDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
c0 := src[nSrc]
|
||||
if c0 >= utf8.RuneSelf {
|
||||
r, size = '\ufffd', 1
|
||||
goto write
|
||||
}
|
||||
|
||||
if c0 == asciiEsc {
|
||||
if nSrc+2 >= len(src) {
|
||||
if !atEOF {
|
||||
return nDst, nSrc, transform.ErrShortSrc
|
||||
}
|
||||
// TODO: is it correct to only skip 1??
|
||||
r, size = '\ufffd', 1
|
||||
goto write
|
||||
}
|
||||
size = 3
|
||||
c1 := src[nSrc+1]
|
||||
c2 := src[nSrc+2]
|
||||
switch {
|
||||
case c1 == '$' && (c2 == '@' || c2 == 'B'): // 0x24 {0x40, 0x42}
|
||||
*d = jis0208State
|
||||
continue
|
||||
case c1 == '$' && c2 == '(': // 0x24 0x28
|
||||
if nSrc+3 >= len(src) {
|
||||
if !atEOF {
|
||||
return nDst, nSrc, transform.ErrShortSrc
|
||||
}
|
||||
r, size = '\ufffd', 1
|
||||
goto write
|
||||
}
|
||||
size = 4
|
||||
if src[nSrc+3] == 'D' {
|
||||
*d = jis0212State
|
||||
continue
|
||||
}
|
||||
case c1 == '(' && (c2 == 'B' || c2 == 'J'): // 0x28 {0x42, 0x4A}
|
||||
*d = asciiState
|
||||
continue
|
||||
case c1 == '(' && c2 == 'I': // 0x28 0x49
|
||||
*d = katakanaState
|
||||
continue
|
||||
}
|
||||
r, size = '\ufffd', 1
|
||||
goto write
|
||||
}
|
||||
|
||||
switch *d {
|
||||
case asciiState:
|
||||
r, size = rune(c0), 1
|
||||
|
||||
case katakanaState:
|
||||
if c0 < 0x21 || 0x60 <= c0 {
|
||||
r, size = '\ufffd', 1
|
||||
goto write
|
||||
}
|
||||
r, size = rune(c0)+(0xff61-0x21), 1
|
||||
|
||||
default:
|
||||
if c0 == 0x0a {
|
||||
*d = asciiState
|
||||
r, size = rune(c0), 1
|
||||
goto write
|
||||
}
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
return nDst, nSrc, transform.ErrShortSrc
|
||||
}
|
||||
r, size = '\ufffd', 1
|
||||
goto write
|
||||
}
|
||||
size = 2
|
||||
c1 := src[nSrc+1]
|
||||
i := int(c0-0x21)*94 + int(c1-0x21)
|
||||
if *d == jis0208State && i < len(jis0208Decode) {
|
||||
r = rune(jis0208Decode[i])
|
||||
} else if *d == jis0212State && i < len(jis0212Decode) {
|
||||
r = rune(jis0212Decode[i])
|
||||
} else {
|
||||
r = '\ufffd'
|
||||
goto write
|
||||
}
|
||||
if r == 0 {
|
||||
r = '\ufffd'
|
||||
}
|
||||
}
|
||||
|
||||
write:
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
return nDst, nSrc, transform.ErrShortDst
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type iso2022JPEncoder int
|
||||
|
||||
func (e *iso2022JPEncoder) Reset() {
|
||||
*e = asciiState
|
||||
}
|
||||
|
||||
func (e *iso2022JPEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// func init checks that the switch covers all tables.
|
||||
//
|
||||
// http://encoding.spec.whatwg.org/#iso-2022-jp says that "the index jis0212
|
||||
// is not used by the iso-2022-jp encoder due to lack of widespread support".
|
||||
//
|
||||
// TODO: do we have to special-case U+00A5 and U+203E, as per
|
||||
// http://encoding.spec.whatwg.org/#iso-2022-jp
|
||||
// Doing so would mean that "\u00a5" would not be preserved
|
||||
// after an encode-decode round trip.
|
||||
switch {
|
||||
case encode0Low <= r && r < encode0High:
|
||||
if r = rune(encode0[r-encode0Low]); r>>tableShift == jis0208 {
|
||||
goto writeJIS
|
||||
}
|
||||
case encode1Low <= r && r < encode1High:
|
||||
if r = rune(encode1[r-encode1Low]); r>>tableShift == jis0208 {
|
||||
goto writeJIS
|
||||
}
|
||||
case encode2Low <= r && r < encode2High:
|
||||
if r = rune(encode2[r-encode2Low]); r>>tableShift == jis0208 {
|
||||
goto writeJIS
|
||||
}
|
||||
case encode3Low <= r && r < encode3High:
|
||||
if r = rune(encode3[r-encode3Low]); r>>tableShift == jis0208 {
|
||||
goto writeJIS
|
||||
}
|
||||
case encode4Low <= r && r < encode4High:
|
||||
if r = rune(encode4[r-encode4Low]); r>>tableShift == jis0208 {
|
||||
goto writeJIS
|
||||
}
|
||||
case encode5Low <= r && r < encode5High:
|
||||
if 0xff61 <= r && r < 0xffa0 {
|
||||
goto writeKatakana
|
||||
}
|
||||
if r = rune(encode5[r-encode5Low]); r>>tableShift == jis0208 {
|
||||
goto writeJIS
|
||||
}
|
||||
}
|
||||
|
||||
// Switch back to ASCII state in case of error so that an ASCII
|
||||
// replacement character can be written in the correct state.
|
||||
if *e != asciiState {
|
||||
if nDst+3 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
*e = asciiState
|
||||
dst[nDst+0] = asciiEsc
|
||||
dst[nDst+1] = '('
|
||||
dst[nDst+2] = 'B'
|
||||
nDst += 3
|
||||
}
|
||||
err = internal.ErrASCIIReplacement
|
||||
break
|
||||
}
|
||||
|
||||
if *e != asciiState {
|
||||
if nDst+4 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
*e = asciiState
|
||||
dst[nDst+0] = asciiEsc
|
||||
dst[nDst+1] = '('
|
||||
dst[nDst+2] = 'B'
|
||||
nDst += 3
|
||||
} else if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r)
|
||||
nDst++
|
||||
continue
|
||||
|
||||
writeJIS:
|
||||
if *e != jis0208State {
|
||||
if nDst+5 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
*e = jis0208State
|
||||
dst[nDst+0] = asciiEsc
|
||||
dst[nDst+1] = '$'
|
||||
dst[nDst+2] = 'B'
|
||||
nDst += 3
|
||||
} else if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = 0x21 + uint8(r>>codeShift)&codeMask
|
||||
dst[nDst+1] = 0x21 + uint8(r)&codeMask
|
||||
nDst += 2
|
||||
continue
|
||||
|
||||
writeKatakana:
|
||||
if *e != katakanaState {
|
||||
if nDst+4 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
*e = katakanaState
|
||||
dst[nDst+0] = asciiEsc
|
||||
dst[nDst+1] = '('
|
||||
dst[nDst+2] = 'I'
|
||||
nDst += 3
|
||||
} else if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r - (0xff61 - 0x21))
|
||||
nDst++
|
||||
continue
|
||||
}
|
||||
if atEOF && err == nil && *e != asciiState {
|
||||
if nDst+3 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
} else {
|
||||
*e = asciiState
|
||||
dst[nDst+0] = asciiEsc
|
||||
dst[nDst+1] = '('
|
||||
dst[nDst+2] = 'B'
|
||||
nDst += 3
|
||||
}
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
189
vendor/golang.org/x/text/encoding/japanese/shiftjis.go
generated
vendored
189
vendor/golang.org/x/text/encoding/japanese/shiftjis.go
generated
vendored
@ -1,189 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package japanese
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// ShiftJIS is the Shift JIS encoding, also known as Code Page 932 and
|
||||
// Windows-31J.
|
||||
var ShiftJIS encoding.Encoding = &shiftJIS
|
||||
|
||||
var shiftJIS = internal.Encoding{
|
||||
&internal.SimpleEncoding{shiftJISDecoder{}, shiftJISEncoder{}},
|
||||
"Shift JIS",
|
||||
identifier.ShiftJIS,
|
||||
}
|
||||
|
||||
type shiftJISDecoder struct{ transform.NopResetter }
|
||||
|
||||
func (shiftJISDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
loop:
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
switch c0 := src[nSrc]; {
|
||||
case c0 < utf8.RuneSelf:
|
||||
r, size = rune(c0), 1
|
||||
|
||||
case 0xa1 <= c0 && c0 < 0xe0:
|
||||
r, size = rune(c0)+(0xff61-0xa1), 1
|
||||
|
||||
case (0x81 <= c0 && c0 < 0xa0) || (0xe0 <= c0 && c0 < 0xfd):
|
||||
if c0 <= 0x9f {
|
||||
c0 -= 0x70
|
||||
} else {
|
||||
c0 -= 0xb0
|
||||
}
|
||||
c0 = 2*c0 - 0x21
|
||||
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = '\ufffd', 1
|
||||
goto write
|
||||
}
|
||||
c1 := src[nSrc+1]
|
||||
switch {
|
||||
case c1 < 0x40:
|
||||
r, size = '\ufffd', 1 // c1 is ASCII so output on next round
|
||||
goto write
|
||||
case c1 < 0x7f:
|
||||
c0--
|
||||
c1 -= 0x40
|
||||
case c1 == 0x7f:
|
||||
r, size = '\ufffd', 1 // c1 is ASCII so output on next round
|
||||
goto write
|
||||
case c1 < 0x9f:
|
||||
c0--
|
||||
c1 -= 0x41
|
||||
case c1 < 0xfd:
|
||||
c1 -= 0x9f
|
||||
default:
|
||||
r, size = '\ufffd', 2
|
||||
goto write
|
||||
}
|
||||
r, size = '\ufffd', 2
|
||||
if i := int(c0)*94 + int(c1); i < len(jis0208Decode) {
|
||||
r = rune(jis0208Decode[i])
|
||||
if r == 0 {
|
||||
r = '\ufffd'
|
||||
}
|
||||
}
|
||||
|
||||
case c0 == 0x80:
|
||||
r, size = 0x80, 1
|
||||
|
||||
default:
|
||||
r, size = '\ufffd', 1
|
||||
}
|
||||
write:
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type shiftJISEncoder struct{ transform.NopResetter }
|
||||
|
||||
func (shiftJISEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
loop:
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
}
|
||||
|
||||
// func init checks that the switch covers all tables.
|
||||
switch {
|
||||
case encode0Low <= r && r < encode0High:
|
||||
if r = rune(encode0[r-encode0Low]); r>>tableShift == jis0208 {
|
||||
goto write2
|
||||
}
|
||||
case encode1Low <= r && r < encode1High:
|
||||
if r = rune(encode1[r-encode1Low]); r>>tableShift == jis0208 {
|
||||
goto write2
|
||||
}
|
||||
case encode2Low <= r && r < encode2High:
|
||||
if r = rune(encode2[r-encode2Low]); r>>tableShift == jis0208 {
|
||||
goto write2
|
||||
}
|
||||
case encode3Low <= r && r < encode3High:
|
||||
if r = rune(encode3[r-encode3Low]); r>>tableShift == jis0208 {
|
||||
goto write2
|
||||
}
|
||||
case encode4Low <= r && r < encode4High:
|
||||
if r = rune(encode4[r-encode4Low]); r>>tableShift == jis0208 {
|
||||
goto write2
|
||||
}
|
||||
case encode5Low <= r && r < encode5High:
|
||||
if 0xff61 <= r && r < 0xffa0 {
|
||||
r -= 0xff61 - 0xa1
|
||||
goto write1
|
||||
}
|
||||
if r = rune(encode5[r-encode5Low]); r>>tableShift == jis0208 {
|
||||
goto write2
|
||||
}
|
||||
}
|
||||
err = internal.ErrASCIIReplacement
|
||||
break
|
||||
}
|
||||
|
||||
write1:
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r)
|
||||
nDst++
|
||||
continue
|
||||
|
||||
write2:
|
||||
j1 := uint8(r>>codeShift) & codeMask
|
||||
j2 := uint8(r) & codeMask
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
if j1 <= 61 {
|
||||
dst[nDst+0] = 129 + j1/2
|
||||
} else {
|
||||
dst[nDst+0] = 193 + j1/2
|
||||
}
|
||||
if j1&1 == 0 {
|
||||
dst[nDst+1] = j2 + j2/63 + 64
|
||||
} else {
|
||||
dst[nDst+1] = j2 + 159
|
||||
}
|
||||
nDst += 2
|
||||
continue
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
26971
vendor/golang.org/x/text/encoding/japanese/tables.go
generated
vendored
26971
vendor/golang.org/x/text/encoding/japanese/tables.go
generated
vendored
File diff suppressed because it is too large
Load Diff
177
vendor/golang.org/x/text/encoding/korean/euckr.go
generated
vendored
177
vendor/golang.org/x/text/encoding/korean/euckr.go
generated
vendored
@ -1,177 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package korean
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// All is a list of all defined encodings in this package.
|
||||
var All = []encoding.Encoding{EUCKR}
|
||||
|
||||
// EUCKR is the EUC-KR encoding, also known as Code Page 949.
|
||||
var EUCKR encoding.Encoding = &eucKR
|
||||
|
||||
var eucKR = internal.Encoding{
|
||||
&internal.SimpleEncoding{eucKRDecoder{}, eucKREncoder{}},
|
||||
"EUC-KR",
|
||||
identifier.EUCKR,
|
||||
}
|
||||
|
||||
type eucKRDecoder struct{ transform.NopResetter }
|
||||
|
||||
func (eucKRDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
loop:
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
switch c0 := src[nSrc]; {
|
||||
case c0 < utf8.RuneSelf:
|
||||
r, size = rune(c0), 1
|
||||
|
||||
case 0x81 <= c0 && c0 < 0xff:
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
break
|
||||
}
|
||||
c1 := src[nSrc+1]
|
||||
size = 2
|
||||
if c0 < 0xc7 {
|
||||
r = 178 * rune(c0-0x81)
|
||||
switch {
|
||||
case 0x41 <= c1 && c1 < 0x5b:
|
||||
r += rune(c1) - (0x41 - 0*26)
|
||||
case 0x61 <= c1 && c1 < 0x7b:
|
||||
r += rune(c1) - (0x61 - 1*26)
|
||||
case 0x81 <= c1 && c1 < 0xff:
|
||||
r += rune(c1) - (0x81 - 2*26)
|
||||
default:
|
||||
goto decError
|
||||
}
|
||||
} else if 0xa1 <= c1 && c1 < 0xff {
|
||||
r = 178*(0xc7-0x81) + rune(c0-0xc7)*94 + rune(c1-0xa1)
|
||||
} else {
|
||||
goto decError
|
||||
}
|
||||
if int(r) < len(decode) {
|
||||
r = rune(decode[r])
|
||||
if r != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
decError:
|
||||
r = utf8.RuneError
|
||||
if c1 < utf8.RuneSelf {
|
||||
size = 1
|
||||
}
|
||||
|
||||
default:
|
||||
r, size = utf8.RuneError, 1
|
||||
break
|
||||
}
|
||||
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type eucKREncoder struct{ transform.NopResetter }
|
||||
|
||||
func (eucKREncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r)
|
||||
nDst++
|
||||
continue
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// func init checks that the switch covers all tables.
|
||||
switch {
|
||||
case encode0Low <= r && r < encode0High:
|
||||
if r = rune(encode0[r-encode0Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode1Low <= r && r < encode1High:
|
||||
if r = rune(encode1[r-encode1Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode2Low <= r && r < encode2High:
|
||||
if r = rune(encode2[r-encode2Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode3Low <= r && r < encode3High:
|
||||
if r = rune(encode3[r-encode3Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode4Low <= r && r < encode4High:
|
||||
if r = rune(encode4[r-encode4Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode5Low <= r && r < encode5High:
|
||||
if r = rune(encode5[r-encode5Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode6Low <= r && r < encode6High:
|
||||
if r = rune(encode6[r-encode6Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
}
|
||||
err = internal.ErrASCIIReplacement
|
||||
break
|
||||
}
|
||||
|
||||
write2:
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = uint8(r >> 8)
|
||||
dst[nDst+1] = uint8(r)
|
||||
nDst += 2
|
||||
continue
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Check that the hard-coded encode switch covers all tables.
|
||||
if numEncodeTables != 7 {
|
||||
panic("bad numEncodeTables")
|
||||
}
|
||||
}
|
34152
vendor/golang.org/x/text/encoding/korean/tables.go
generated
vendored
34152
vendor/golang.org/x/text/encoding/korean/tables.go
generated
vendored
File diff suppressed because it is too large
Load Diff
12
vendor/golang.org/x/text/encoding/simplifiedchinese/all.go
generated
vendored
12
vendor/golang.org/x/text/encoding/simplifiedchinese/all.go
generated
vendored
@ -1,12 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package simplifiedchinese
|
||||
|
||||
import (
|
||||
"golang.org/x/text/encoding"
|
||||
)
|
||||
|
||||
// All is a list of all defined encodings in this package.
|
||||
var All = []encoding.Encoding{GB18030, GBK, HZGB2312}
|
273
vendor/golang.org/x/text/encoding/simplifiedchinese/gbk.go
generated
vendored
273
vendor/golang.org/x/text/encoding/simplifiedchinese/gbk.go
generated
vendored
@ -1,273 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package simplifiedchinese
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
var (
|
||||
// GB18030 is the GB18030 encoding.
|
||||
GB18030 encoding.Encoding = &gbk18030
|
||||
// GBK is the GBK encoding. It encodes an extension of the GB2312 character set
|
||||
// and is also known as Code Page 936.
|
||||
GBK encoding.Encoding = &gbk
|
||||
)
|
||||
|
||||
var gbk = internal.Encoding{
|
||||
&internal.SimpleEncoding{
|
||||
gbkDecoder{gb18030: false},
|
||||
gbkEncoder{gb18030: false},
|
||||
},
|
||||
"GBK",
|
||||
identifier.GBK,
|
||||
}
|
||||
|
||||
var gbk18030 = internal.Encoding{
|
||||
&internal.SimpleEncoding{
|
||||
gbkDecoder{gb18030: true},
|
||||
gbkEncoder{gb18030: true},
|
||||
},
|
||||
"GB18030",
|
||||
identifier.GB18030,
|
||||
}
|
||||
|
||||
type gbkDecoder struct {
|
||||
transform.NopResetter
|
||||
gb18030 bool
|
||||
}
|
||||
|
||||
func (d gbkDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
loop:
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
switch c0 := src[nSrc]; {
|
||||
case c0 < utf8.RuneSelf:
|
||||
r, size = rune(c0), 1
|
||||
|
||||
// Microsoft's Code Page 936 extends GBK 1.0 to encode the euro sign U+20AC
|
||||
// as 0x80. The HTML5 specification at http://encoding.spec.whatwg.org/#gbk
|
||||
// says to treat "gbk" as Code Page 936.
|
||||
// GBK’s decoder is gb18030’s decoder. https://encoding.spec.whatwg.org/#gbk-decoder
|
||||
// If byte is 0x80, return code point U+20AC. https://encoding.spec.whatwg.org/#gb18030-decoder
|
||||
case c0 == 0x80:
|
||||
r, size = '€', 1
|
||||
|
||||
case c0 < 0xff:
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
c1 := src[nSrc+1]
|
||||
switch {
|
||||
case 0x40 <= c1 && c1 < 0x7f:
|
||||
c1 -= 0x40
|
||||
case 0x80 <= c1 && c1 < 0xff:
|
||||
c1 -= 0x41
|
||||
case d.gb18030 && 0x30 <= c1 && c1 < 0x40:
|
||||
if nSrc+3 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
// The second byte here is always ASCII, so we can set size
|
||||
// to 1 in all cases.
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
c2 := src[nSrc+2]
|
||||
if c2 < 0x81 || 0xff <= c2 {
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
c3 := src[nSrc+3]
|
||||
if c3 < 0x30 || 0x3a <= c3 {
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
size = 4
|
||||
r = ((rune(c0-0x81)*10+rune(c1-0x30))*126+rune(c2-0x81))*10 + rune(c3-0x30)
|
||||
if r < 39420 {
|
||||
i, j := 0, len(gb18030)
|
||||
for i < j {
|
||||
h := i + (j-i)/2
|
||||
if r >= rune(gb18030[h][0]) {
|
||||
i = h + 1
|
||||
} else {
|
||||
j = h
|
||||
}
|
||||
}
|
||||
dec := &gb18030[i-1]
|
||||
r += rune(dec[1]) - rune(dec[0])
|
||||
goto write
|
||||
}
|
||||
r -= 189000
|
||||
if 0 <= r && r < 0x100000 {
|
||||
r += 0x10000
|
||||
} else {
|
||||
r, size = utf8.RuneError, 1
|
||||
}
|
||||
goto write
|
||||
default:
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
r, size = '\ufffd', 2
|
||||
if i := int(c0-0x81)*190 + int(c1); i < len(decode) {
|
||||
r = rune(decode[i])
|
||||
if r == 0 {
|
||||
r = '\ufffd'
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
r, size = utf8.RuneError, 1
|
||||
}
|
||||
|
||||
write:
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type gbkEncoder struct {
|
||||
transform.NopResetter
|
||||
gb18030 bool
|
||||
}
|
||||
|
||||
func (e gbkEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, r2, size := rune(0), rune(0), 0
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// func init checks that the switch covers all tables.
|
||||
switch {
|
||||
case encode0Low <= r && r < encode0High:
|
||||
if r2 = rune(encode0[r-encode0Low]); r2 != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode1Low <= r && r < encode1High:
|
||||
// Microsoft's Code Page 936 extends GBK 1.0 to encode the euro sign U+20AC
|
||||
// as 0x80. The HTML5 specification at http://encoding.spec.whatwg.org/#gbk
|
||||
// says to treat "gbk" as Code Page 936.
|
||||
// GBK’s encoder is gb18030’s encoder with its _is GBK_ set to true. https://encoding.spec.whatwg.org/#gbk-encoder
|
||||
// If _is GBK_ is true and code point is U+20AC, return byte 0x80. https://encoding.spec.whatwg.org/#gb18030-encoder
|
||||
if !e.gb18030 && r == '€' {
|
||||
r = 0x80
|
||||
goto write1
|
||||
}
|
||||
if r2 = rune(encode1[r-encode1Low]); r2 != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode2Low <= r && r < encode2High:
|
||||
if r2 = rune(encode2[r-encode2Low]); r2 != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode3Low <= r && r < encode3High:
|
||||
if r2 = rune(encode3[r-encode3Low]); r2 != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode4Low <= r && r < encode4High:
|
||||
if r2 = rune(encode4[r-encode4Low]); r2 != 0 {
|
||||
goto write2
|
||||
}
|
||||
}
|
||||
|
||||
if e.gb18030 {
|
||||
if r < 0x10000 {
|
||||
i, j := 0, len(gb18030)
|
||||
for i < j {
|
||||
h := i + (j-i)/2
|
||||
if r >= rune(gb18030[h][1]) {
|
||||
i = h + 1
|
||||
} else {
|
||||
j = h
|
||||
}
|
||||
}
|
||||
dec := &gb18030[i-1]
|
||||
r += rune(dec[0]) - rune(dec[1])
|
||||
goto write4
|
||||
} else if r < 0x110000 {
|
||||
r += 189000 - 0x10000
|
||||
goto write4
|
||||
}
|
||||
}
|
||||
err = internal.ErrASCIIReplacement
|
||||
break
|
||||
}
|
||||
|
||||
write1:
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r)
|
||||
nDst++
|
||||
continue
|
||||
|
||||
write2:
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = uint8(r2 >> 8)
|
||||
dst[nDst+1] = uint8(r2)
|
||||
nDst += 2
|
||||
continue
|
||||
|
||||
write4:
|
||||
if nDst+4 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+3] = uint8(r%10 + 0x30)
|
||||
r /= 10
|
||||
dst[nDst+2] = uint8(r%126 + 0x81)
|
||||
r /= 126
|
||||
dst[nDst+1] = uint8(r%10 + 0x30)
|
||||
r /= 10
|
||||
dst[nDst+0] = uint8(r + 0x81)
|
||||
nDst += 4
|
||||
continue
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Check that the hard-coded encode switch covers all tables.
|
||||
if numEncodeTables != 5 {
|
||||
panic("bad numEncodeTables")
|
||||
}
|
||||
}
|
245
vendor/golang.org/x/text/encoding/simplifiedchinese/hzgb2312.go
generated
vendored
245
vendor/golang.org/x/text/encoding/simplifiedchinese/hzgb2312.go
generated
vendored
@ -1,245 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package simplifiedchinese
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// HZGB2312 is the HZ-GB2312 encoding.
|
||||
var HZGB2312 encoding.Encoding = &hzGB2312
|
||||
|
||||
var hzGB2312 = internal.Encoding{
|
||||
internal.FuncEncoding{hzGB2312NewDecoder, hzGB2312NewEncoder},
|
||||
"HZ-GB2312",
|
||||
identifier.HZGB2312,
|
||||
}
|
||||
|
||||
func hzGB2312NewDecoder() transform.Transformer {
|
||||
return new(hzGB2312Decoder)
|
||||
}
|
||||
|
||||
func hzGB2312NewEncoder() transform.Transformer {
|
||||
return new(hzGB2312Encoder)
|
||||
}
|
||||
|
||||
const (
|
||||
asciiState = iota
|
||||
gbState
|
||||
)
|
||||
|
||||
type hzGB2312Decoder int
|
||||
|
||||
func (d *hzGB2312Decoder) Reset() {
|
||||
*d = asciiState
|
||||
}
|
||||
|
||||
func (d *hzGB2312Decoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
loop:
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
c0 := src[nSrc]
|
||||
if c0 >= utf8.RuneSelf {
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
|
||||
if c0 == '~' {
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
size = 2
|
||||
switch src[nSrc+1] {
|
||||
case '{':
|
||||
*d = gbState
|
||||
continue
|
||||
case '}':
|
||||
*d = asciiState
|
||||
continue
|
||||
case '~':
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
dst[nDst] = '~'
|
||||
nDst++
|
||||
continue
|
||||
case '\n':
|
||||
continue
|
||||
default:
|
||||
r = utf8.RuneError
|
||||
goto write
|
||||
}
|
||||
}
|
||||
|
||||
if *d == asciiState {
|
||||
r, size = rune(c0), 1
|
||||
} else {
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
size = 2
|
||||
c1 := src[nSrc+1]
|
||||
if c0 < 0x21 || 0x7e <= c0 || c1 < 0x21 || 0x7f <= c1 {
|
||||
// error
|
||||
} else if i := int(c0-0x01)*190 + int(c1+0x3f); i < len(decode) {
|
||||
r = rune(decode[i])
|
||||
if r != 0 {
|
||||
goto write
|
||||
}
|
||||
}
|
||||
if c1 > utf8.RuneSelf {
|
||||
// Be consistent and always treat non-ASCII as a single error.
|
||||
size = 1
|
||||
}
|
||||
r = utf8.RuneError
|
||||
}
|
||||
|
||||
write:
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type hzGB2312Encoder int
|
||||
|
||||
func (d *hzGB2312Encoder) Reset() {
|
||||
*d = asciiState
|
||||
}
|
||||
|
||||
func (e *hzGB2312Encoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
if r == '~' {
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = '~'
|
||||
dst[nDst+1] = '~'
|
||||
nDst += 2
|
||||
continue
|
||||
} else if *e != asciiState {
|
||||
if nDst+3 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
*e = asciiState
|
||||
dst[nDst+0] = '~'
|
||||
dst[nDst+1] = '}'
|
||||
nDst += 2
|
||||
} else if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r)
|
||||
nDst += 1
|
||||
continue
|
||||
|
||||
}
|
||||
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// func init checks that the switch covers all tables.
|
||||
switch {
|
||||
case encode0Low <= r && r < encode0High:
|
||||
if r = rune(encode0[r-encode0Low]); r != 0 {
|
||||
goto writeGB
|
||||
}
|
||||
case encode1Low <= r && r < encode1High:
|
||||
if r = rune(encode1[r-encode1Low]); r != 0 {
|
||||
goto writeGB
|
||||
}
|
||||
case encode2Low <= r && r < encode2High:
|
||||
if r = rune(encode2[r-encode2Low]); r != 0 {
|
||||
goto writeGB
|
||||
}
|
||||
case encode3Low <= r && r < encode3High:
|
||||
if r = rune(encode3[r-encode3Low]); r != 0 {
|
||||
goto writeGB
|
||||
}
|
||||
case encode4Low <= r && r < encode4High:
|
||||
if r = rune(encode4[r-encode4Low]); r != 0 {
|
||||
goto writeGB
|
||||
}
|
||||
}
|
||||
|
||||
terminateInASCIIState:
|
||||
// Switch back to ASCII state in case of error so that an ASCII
|
||||
// replacement character can be written in the correct state.
|
||||
if *e != asciiState {
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = '~'
|
||||
dst[nDst+1] = '}'
|
||||
nDst += 2
|
||||
}
|
||||
err = internal.ErrASCIIReplacement
|
||||
break
|
||||
|
||||
writeGB:
|
||||
c0 := uint8(r>>8) - 0x80
|
||||
c1 := uint8(r) - 0x80
|
||||
if c0 < 0x21 || 0x7e <= c0 || c1 < 0x21 || 0x7f <= c1 {
|
||||
goto terminateInASCIIState
|
||||
}
|
||||
if *e == asciiState {
|
||||
if nDst+4 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
*e = gbState
|
||||
dst[nDst+0] = '~'
|
||||
dst[nDst+1] = '{'
|
||||
nDst += 2
|
||||
} else if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = c0
|
||||
dst[nDst+1] = c1
|
||||
nDst += 2
|
||||
continue
|
||||
}
|
||||
// TODO: should one always terminate in ASCII state to make it safe to
|
||||
// concatenate two HZ-GB2312-encoded strings?
|
||||
return nDst, nSrc, err
|
||||
}
|
43999
vendor/golang.org/x/text/encoding/simplifiedchinese/tables.go
generated
vendored
43999
vendor/golang.org/x/text/encoding/simplifiedchinese/tables.go
generated
vendored
File diff suppressed because it is too large
Load Diff
199
vendor/golang.org/x/text/encoding/traditionalchinese/big5.go
generated
vendored
199
vendor/golang.org/x/text/encoding/traditionalchinese/big5.go
generated
vendored
@ -1,199 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package traditionalchinese
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// All is a list of all defined encodings in this package.
|
||||
var All = []encoding.Encoding{Big5}
|
||||
|
||||
// Big5 is the Big5 encoding, also known as Code Page 950.
|
||||
var Big5 encoding.Encoding = &big5
|
||||
|
||||
var big5 = internal.Encoding{
|
||||
&internal.SimpleEncoding{big5Decoder{}, big5Encoder{}},
|
||||
"Big5",
|
||||
identifier.Big5,
|
||||
}
|
||||
|
||||
type big5Decoder struct{ transform.NopResetter }
|
||||
|
||||
func (big5Decoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size, s := rune(0), 0, ""
|
||||
loop:
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
switch c0 := src[nSrc]; {
|
||||
case c0 < utf8.RuneSelf:
|
||||
r, size = rune(c0), 1
|
||||
|
||||
case 0x81 <= c0 && c0 < 0xff:
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
c1 := src[nSrc+1]
|
||||
switch {
|
||||
case 0x40 <= c1 && c1 < 0x7f:
|
||||
c1 -= 0x40
|
||||
case 0xa1 <= c1 && c1 < 0xff:
|
||||
c1 -= 0x62
|
||||
case c1 < 0x40:
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
default:
|
||||
r, size = utf8.RuneError, 2
|
||||
goto write
|
||||
}
|
||||
r, size = '\ufffd', 2
|
||||
if i := int(c0-0x81)*157 + int(c1); i < len(decode) {
|
||||
if 1133 <= i && i < 1167 {
|
||||
// The two-rune special cases for LATIN CAPITAL / SMALL E WITH CIRCUMFLEX
|
||||
// AND MACRON / CARON are from http://encoding.spec.whatwg.org/#big5
|
||||
switch i {
|
||||
case 1133:
|
||||
s = "\u00CA\u0304"
|
||||
goto writeStr
|
||||
case 1135:
|
||||
s = "\u00CA\u030C"
|
||||
goto writeStr
|
||||
case 1164:
|
||||
s = "\u00EA\u0304"
|
||||
goto writeStr
|
||||
case 1166:
|
||||
s = "\u00EA\u030C"
|
||||
goto writeStr
|
||||
}
|
||||
}
|
||||
r = rune(decode[i])
|
||||
if r == 0 {
|
||||
r = '\ufffd'
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
r, size = utf8.RuneError, 1
|
||||
}
|
||||
|
||||
write:
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
continue loop
|
||||
|
||||
writeStr:
|
||||
if nDst+len(s) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
nDst += copy(dst[nDst:], s)
|
||||
continue loop
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type big5Encoder struct{ transform.NopResetter }
|
||||
|
||||
func (big5Encoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r)
|
||||
nDst++
|
||||
continue
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if r >= utf8.RuneSelf {
|
||||
// func init checks that the switch covers all tables.
|
||||
switch {
|
||||
case encode0Low <= r && r < encode0High:
|
||||
if r = rune(encode0[r-encode0Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode1Low <= r && r < encode1High:
|
||||
if r = rune(encode1[r-encode1Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode2Low <= r && r < encode2High:
|
||||
if r = rune(encode2[r-encode2Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode3Low <= r && r < encode3High:
|
||||
if r = rune(encode3[r-encode3Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode4Low <= r && r < encode4High:
|
||||
if r = rune(encode4[r-encode4Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode5Low <= r && r < encode5High:
|
||||
if r = rune(encode5[r-encode5Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode6Low <= r && r < encode6High:
|
||||
if r = rune(encode6[r-encode6Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode7Low <= r && r < encode7High:
|
||||
if r = rune(encode7[r-encode7Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
}
|
||||
err = internal.ErrASCIIReplacement
|
||||
break
|
||||
}
|
||||
|
||||
write2:
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = uint8(r >> 8)
|
||||
dst[nDst+1] = uint8(r)
|
||||
nDst += 2
|
||||
continue
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Check that the hard-coded encode switch covers all tables.
|
||||
if numEncodeTables != 8 {
|
||||
panic("bad numEncodeTables")
|
||||
}
|
||||
}
|
37142
vendor/golang.org/x/text/encoding/traditionalchinese/tables.go
generated
vendored
37142
vendor/golang.org/x/text/encoding/traditionalchinese/tables.go
generated
vendored
File diff suppressed because it is too large
Load Diff
82
vendor/golang.org/x/text/encoding/unicode/override.go
generated
vendored
82
vendor/golang.org/x/text/encoding/unicode/override.go
generated
vendored
@ -1,82 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package unicode
|
||||
|
||||
import (
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// BOMOverride returns a new decoder transformer that is identical to fallback,
|
||||
// except that the presence of a Byte Order Mark at the start of the input
|
||||
// causes it to switch to the corresponding Unicode decoding. It will only
|
||||
// consider BOMs for UTF-8, UTF-16BE, and UTF-16LE.
|
||||
//
|
||||
// This differs from using ExpectBOM by allowing a BOM to switch to UTF-8, not
|
||||
// just UTF-16 variants, and allowing falling back to any encoding scheme.
|
||||
//
|
||||
// This technique is recommended by the W3C for use in HTML 5: "For
|
||||
// compatibility with deployed content, the byte order mark (also known as BOM)
|
||||
// is considered more authoritative than anything else."
|
||||
// http://www.w3.org/TR/encoding/#specification-hooks
|
||||
//
|
||||
// Using BOMOverride is mostly intended for use cases where the first characters
|
||||
// of a fallback encoding are known to not be a BOM, for example, for valid HTML
|
||||
// and most encodings.
|
||||
func BOMOverride(fallback transform.Transformer) transform.Transformer {
|
||||
// TODO: possibly allow a variadic argument of unicode encodings to allow
|
||||
// specifying details of which fallbacks are supported as well as
|
||||
// specifying the details of the implementations. This would also allow for
|
||||
// support for UTF-32, which should not be supported by default.
|
||||
return &bomOverride{fallback: fallback}
|
||||
}
|
||||
|
||||
type bomOverride struct {
|
||||
fallback transform.Transformer
|
||||
current transform.Transformer
|
||||
}
|
||||
|
||||
func (d *bomOverride) Reset() {
|
||||
d.current = nil
|
||||
d.fallback.Reset()
|
||||
}
|
||||
|
||||
var (
|
||||
// TODO: we could use decode functions here, instead of allocating a new
|
||||
// decoder on every NewDecoder as IgnoreBOM decoders can be stateless.
|
||||
utf16le = UTF16(LittleEndian, IgnoreBOM)
|
||||
utf16be = UTF16(BigEndian, IgnoreBOM)
|
||||
)
|
||||
|
||||
const utf8BOM = "\ufeff"
|
||||
|
||||
func (d *bomOverride) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
if d.current != nil {
|
||||
return d.current.Transform(dst, src, atEOF)
|
||||
}
|
||||
if len(src) < 3 && !atEOF {
|
||||
return 0, 0, transform.ErrShortSrc
|
||||
}
|
||||
d.current = d.fallback
|
||||
bomSize := 0
|
||||
if len(src) >= 2 {
|
||||
if src[0] == 0xFF && src[1] == 0xFE {
|
||||
d.current = utf16le.NewDecoder()
|
||||
bomSize = 2
|
||||
} else if src[0] == 0xFE && src[1] == 0xFF {
|
||||
d.current = utf16be.NewDecoder()
|
||||
bomSize = 2
|
||||
} else if len(src) >= 3 &&
|
||||
src[0] == utf8BOM[0] &&
|
||||
src[1] == utf8BOM[1] &&
|
||||
src[2] == utf8BOM[2] {
|
||||
d.current = transform.Nop
|
||||
bomSize = 3
|
||||
}
|
||||
}
|
||||
if bomSize < len(src) {
|
||||
nDst, nSrc, err = d.current.Transform(dst, src[bomSize:], atEOF)
|
||||
}
|
||||
return nDst, nSrc + bomSize, err
|
||||
}
|
512
vendor/golang.org/x/text/encoding/unicode/unicode.go
generated
vendored
512
vendor/golang.org/x/text/encoding/unicode/unicode.go
generated
vendored
@ -1,512 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package unicode provides Unicode encodings such as UTF-16.
|
||||
package unicode // import "golang.org/x/text/encoding/unicode"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"unicode/utf16"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/internal/utf8internal"
|
||||
"golang.org/x/text/runes"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// TODO: I think the Transformers really should return errors on unmatched
|
||||
// surrogate pairs and odd numbers of bytes. This is not required by RFC 2781,
|
||||
// which leaves it open, but is suggested by WhatWG. It will allow for all error
|
||||
// modes as defined by WhatWG: fatal, HTML and Replacement. This would require
|
||||
// the introduction of some kind of error type for conveying the erroneous code
|
||||
// point.
|
||||
|
||||
// UTF8 is the UTF-8 encoding. It neither removes nor adds byte order marks.
|
||||
var UTF8 encoding.Encoding = utf8enc
|
||||
|
||||
// UTF8BOM is an UTF-8 encoding where the decoder strips a leading byte order
|
||||
// mark while the encoder adds one.
|
||||
//
|
||||
// Some editors add a byte order mark as a signature to UTF-8 files. Although
|
||||
// the byte order mark is not useful for detecting byte order in UTF-8, it is
|
||||
// sometimes used as a convention to mark UTF-8-encoded files. This relies on
|
||||
// the observation that the UTF-8 byte order mark is either an illegal or at
|
||||
// least very unlikely sequence in any other character encoding.
|
||||
var UTF8BOM encoding.Encoding = utf8bomEncoding{}
|
||||
|
||||
type utf8bomEncoding struct{}
|
||||
|
||||
func (utf8bomEncoding) String() string {
|
||||
return "UTF-8-BOM"
|
||||
}
|
||||
|
||||
func (utf8bomEncoding) ID() (identifier.MIB, string) {
|
||||
return identifier.Unofficial, "x-utf8bom"
|
||||
}
|
||||
|
||||
func (utf8bomEncoding) NewEncoder() *encoding.Encoder {
|
||||
return &encoding.Encoder{
|
||||
Transformer: &utf8bomEncoder{t: runes.ReplaceIllFormed()},
|
||||
}
|
||||
}
|
||||
|
||||
func (utf8bomEncoding) NewDecoder() *encoding.Decoder {
|
||||
return &encoding.Decoder{Transformer: &utf8bomDecoder{}}
|
||||
}
|
||||
|
||||
var utf8enc = &internal.Encoding{
|
||||
&internal.SimpleEncoding{utf8Decoder{}, runes.ReplaceIllFormed()},
|
||||
"UTF-8",
|
||||
identifier.UTF8,
|
||||
}
|
||||
|
||||
type utf8bomDecoder struct {
|
||||
checked bool
|
||||
}
|
||||
|
||||
func (t *utf8bomDecoder) Reset() {
|
||||
t.checked = false
|
||||
}
|
||||
|
||||
func (t *utf8bomDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
if !t.checked {
|
||||
if !atEOF && len(src) < len(utf8BOM) {
|
||||
if len(src) == 0 {
|
||||
return 0, 0, nil
|
||||
}
|
||||
return 0, 0, transform.ErrShortSrc
|
||||
}
|
||||
if bytes.HasPrefix(src, []byte(utf8BOM)) {
|
||||
nSrc += len(utf8BOM)
|
||||
src = src[len(utf8BOM):]
|
||||
}
|
||||
t.checked = true
|
||||
}
|
||||
nDst, n, err := utf8Decoder.Transform(utf8Decoder{}, dst[nDst:], src, atEOF)
|
||||
nSrc += n
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type utf8bomEncoder struct {
|
||||
written bool
|
||||
t transform.Transformer
|
||||
}
|
||||
|
||||
func (t *utf8bomEncoder) Reset() {
|
||||
t.written = false
|
||||
t.t.Reset()
|
||||
}
|
||||
|
||||
func (t *utf8bomEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
if !t.written {
|
||||
if len(dst) < len(utf8BOM) {
|
||||
return nDst, 0, transform.ErrShortDst
|
||||
}
|
||||
nDst = copy(dst, utf8BOM)
|
||||
t.written = true
|
||||
}
|
||||
n, nSrc, err := utf8Decoder.Transform(utf8Decoder{}, dst[nDst:], src, atEOF)
|
||||
nDst += n
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type utf8Decoder struct{ transform.NopResetter }
|
||||
|
||||
func (utf8Decoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
var pSrc int // point from which to start copy in src
|
||||
var accept utf8internal.AcceptRange
|
||||
|
||||
// The decoder can only make the input larger, not smaller.
|
||||
n := len(src)
|
||||
if len(dst) < n {
|
||||
err = transform.ErrShortDst
|
||||
n = len(dst)
|
||||
atEOF = false
|
||||
}
|
||||
for nSrc < n {
|
||||
c := src[nSrc]
|
||||
if c < utf8.RuneSelf {
|
||||
nSrc++
|
||||
continue
|
||||
}
|
||||
first := utf8internal.First[c]
|
||||
size := int(first & utf8internal.SizeMask)
|
||||
if first == utf8internal.FirstInvalid {
|
||||
goto handleInvalid // invalid starter byte
|
||||
}
|
||||
accept = utf8internal.AcceptRanges[first>>utf8internal.AcceptShift]
|
||||
if nSrc+size > n {
|
||||
if !atEOF {
|
||||
// We may stop earlier than necessary here if the short sequence
|
||||
// has invalid bytes. Not checking for this simplifies the code
|
||||
// and may avoid duplicate computations in certain conditions.
|
||||
if err == nil {
|
||||
err = transform.ErrShortSrc
|
||||
}
|
||||
break
|
||||
}
|
||||
// Determine the maximal subpart of an ill-formed subsequence.
|
||||
switch {
|
||||
case nSrc+1 >= n || src[nSrc+1] < accept.Lo || accept.Hi < src[nSrc+1]:
|
||||
size = 1
|
||||
case nSrc+2 >= n || src[nSrc+2] < utf8internal.LoCB || utf8internal.HiCB < src[nSrc+2]:
|
||||
size = 2
|
||||
default:
|
||||
size = 3 // As we are short, the maximum is 3.
|
||||
}
|
||||
goto handleInvalid
|
||||
}
|
||||
if c = src[nSrc+1]; c < accept.Lo || accept.Hi < c {
|
||||
size = 1
|
||||
goto handleInvalid // invalid continuation byte
|
||||
} else if size == 2 {
|
||||
} else if c = src[nSrc+2]; c < utf8internal.LoCB || utf8internal.HiCB < c {
|
||||
size = 2
|
||||
goto handleInvalid // invalid continuation byte
|
||||
} else if size == 3 {
|
||||
} else if c = src[nSrc+3]; c < utf8internal.LoCB || utf8internal.HiCB < c {
|
||||
size = 3
|
||||
goto handleInvalid // invalid continuation byte
|
||||
}
|
||||
nSrc += size
|
||||
continue
|
||||
|
||||
handleInvalid:
|
||||
// Copy the scanned input so far.
|
||||
nDst += copy(dst[nDst:], src[pSrc:nSrc])
|
||||
|
||||
// Append RuneError to the destination.
|
||||
const runeError = "\ufffd"
|
||||
if nDst+len(runeError) > len(dst) {
|
||||
return nDst, nSrc, transform.ErrShortDst
|
||||
}
|
||||
nDst += copy(dst[nDst:], runeError)
|
||||
|
||||
// Skip the maximal subpart of an ill-formed subsequence according to
|
||||
// the W3C standard way instead of the Go way. This Transform is
|
||||
// probably the only place in the text repo where it is warranted.
|
||||
nSrc += size
|
||||
pSrc = nSrc
|
||||
|
||||
// Recompute the maximum source length.
|
||||
if sz := len(dst) - nDst; sz < len(src)-nSrc {
|
||||
err = transform.ErrShortDst
|
||||
n = nSrc + sz
|
||||
atEOF = false
|
||||
}
|
||||
}
|
||||
return nDst + copy(dst[nDst:], src[pSrc:nSrc]), nSrc, err
|
||||
}
|
||||
|
||||
// UTF16 returns a UTF-16 Encoding for the given default endianness and byte
|
||||
// order mark (BOM) policy.
|
||||
//
|
||||
// When decoding from UTF-16 to UTF-8, if the BOMPolicy is IgnoreBOM then
|
||||
// neither BOMs U+FEFF nor noncharacters U+FFFE in the input stream will affect
|
||||
// the endianness used for decoding, and will instead be output as their
|
||||
// standard UTF-8 encodings: "\xef\xbb\xbf" and "\xef\xbf\xbe". If the BOMPolicy
|
||||
// is UseBOM or ExpectBOM a staring BOM is not written to the UTF-8 output.
|
||||
// Instead, it overrides the default endianness e for the remainder of the
|
||||
// transformation. Any subsequent BOMs U+FEFF or noncharacters U+FFFE will not
|
||||
// affect the endianness used, and will instead be output as their standard
|
||||
// UTF-8 encodings. For UseBOM, if there is no starting BOM, it will proceed
|
||||
// with the default Endianness. For ExpectBOM, in that case, the transformation
|
||||
// will return early with an ErrMissingBOM error.
|
||||
//
|
||||
// When encoding from UTF-8 to UTF-16, a BOM will be inserted at the start of
|
||||
// the output if the BOMPolicy is UseBOM or ExpectBOM. Otherwise, a BOM will not
|
||||
// be inserted. The UTF-8 input does not need to contain a BOM.
|
||||
//
|
||||
// There is no concept of a 'native' endianness. If the UTF-16 data is produced
|
||||
// and consumed in a greater context that implies a certain endianness, use
|
||||
// IgnoreBOM. Otherwise, use ExpectBOM and always produce and consume a BOM.
|
||||
//
|
||||
// In the language of https://www.unicode.org/faq/utf_bom.html#bom10, IgnoreBOM
|
||||
// corresponds to "Where the precise type of the data stream is known... the
|
||||
// BOM should not be used" and ExpectBOM corresponds to "A particular
|
||||
// protocol... may require use of the BOM".
|
||||
func UTF16(e Endianness, b BOMPolicy) encoding.Encoding {
|
||||
return utf16Encoding{config{e, b}, mibValue[e][b&bomMask]}
|
||||
}
|
||||
|
||||
// mibValue maps Endianness and BOMPolicy settings to MIB constants. Note that
|
||||
// some configurations map to the same MIB identifier. RFC 2781 has requirements
|
||||
// and recommendations. Some of the "configurations" are merely recommendations,
|
||||
// so multiple configurations could match.
|
||||
var mibValue = map[Endianness][numBOMValues]identifier.MIB{
|
||||
BigEndian: [numBOMValues]identifier.MIB{
|
||||
IgnoreBOM: identifier.UTF16BE,
|
||||
UseBOM: identifier.UTF16, // BigEnding default is preferred by RFC 2781.
|
||||
// TODO: acceptBOM | strictBOM would map to UTF16BE as well.
|
||||
},
|
||||
LittleEndian: [numBOMValues]identifier.MIB{
|
||||
IgnoreBOM: identifier.UTF16LE,
|
||||
UseBOM: identifier.UTF16, // LittleEndian default is allowed and preferred on Windows.
|
||||
// TODO: acceptBOM | strictBOM would map to UTF16LE as well.
|
||||
},
|
||||
// ExpectBOM is not widely used and has no valid MIB identifier.
|
||||
}
|
||||
|
||||
// All lists a configuration for each IANA-defined UTF-16 variant.
|
||||
var All = []encoding.Encoding{
|
||||
UTF8,
|
||||
UTF16(BigEndian, UseBOM),
|
||||
UTF16(BigEndian, IgnoreBOM),
|
||||
UTF16(LittleEndian, IgnoreBOM),
|
||||
}
|
||||
|
||||
// BOMPolicy is a UTF-16 encoding's byte order mark policy.
|
||||
type BOMPolicy uint8
|
||||
|
||||
const (
|
||||
writeBOM BOMPolicy = 0x01
|
||||
acceptBOM BOMPolicy = 0x02
|
||||
requireBOM BOMPolicy = 0x04
|
||||
bomMask BOMPolicy = 0x07
|
||||
|
||||
// HACK: numBOMValues == 8 triggers a bug in the 1.4 compiler (cannot have a
|
||||
// map of an array of length 8 of a type that is also used as a key or value
|
||||
// in another map). See golang.org/issue/11354.
|
||||
// TODO: consider changing this value back to 8 if the use of 1.4.* has
|
||||
// been minimized.
|
||||
numBOMValues = 8 + 1
|
||||
|
||||
// IgnoreBOM means to ignore any byte order marks.
|
||||
IgnoreBOM BOMPolicy = 0
|
||||
// Common and RFC 2781-compliant interpretation for UTF-16BE/LE.
|
||||
|
||||
// UseBOM means that the UTF-16 form may start with a byte order mark, which
|
||||
// will be used to override the default encoding.
|
||||
UseBOM BOMPolicy = writeBOM | acceptBOM
|
||||
// Common and RFC 2781-compliant interpretation for UTF-16.
|
||||
|
||||
// ExpectBOM means that the UTF-16 form must start with a byte order mark,
|
||||
// which will be used to override the default encoding.
|
||||
ExpectBOM BOMPolicy = writeBOM | acceptBOM | requireBOM
|
||||
// Used in Java as Unicode (not to be confused with Java's UTF-16) and
|
||||
// ICU's UTF-16,version=1. Not compliant with RFC 2781.
|
||||
|
||||
// TODO (maybe): strictBOM: BOM must match Endianness. This would allow:
|
||||
// - UTF-16(B|L)E,version=1: writeBOM | acceptBOM | requireBOM | strictBOM
|
||||
// (UnicodeBig and UnicodeLittle in Java)
|
||||
// - RFC 2781-compliant, but less common interpretation for UTF-16(B|L)E:
|
||||
// acceptBOM | strictBOM (e.g. assigned to CheckBOM).
|
||||
// This addition would be consistent with supporting ExpectBOM.
|
||||
)
|
||||
|
||||
// Endianness is a UTF-16 encoding's default endianness.
|
||||
type Endianness bool
|
||||
|
||||
const (
|
||||
// BigEndian is UTF-16BE.
|
||||
BigEndian Endianness = false
|
||||
// LittleEndian is UTF-16LE.
|
||||
LittleEndian Endianness = true
|
||||
)
|
||||
|
||||
// ErrMissingBOM means that decoding UTF-16 input with ExpectBOM did not find a
|
||||
// starting byte order mark.
|
||||
var ErrMissingBOM = errors.New("encoding: missing byte order mark")
|
||||
|
||||
type utf16Encoding struct {
|
||||
config
|
||||
mib identifier.MIB
|
||||
}
|
||||
|
||||
type config struct {
|
||||
endianness Endianness
|
||||
bomPolicy BOMPolicy
|
||||
}
|
||||
|
||||
func (u utf16Encoding) NewDecoder() *encoding.Decoder {
|
||||
return &encoding.Decoder{Transformer: &utf16Decoder{
|
||||
initial: u.config,
|
||||
current: u.config,
|
||||
}}
|
||||
}
|
||||
|
||||
func (u utf16Encoding) NewEncoder() *encoding.Encoder {
|
||||
return &encoding.Encoder{Transformer: &utf16Encoder{
|
||||
endianness: u.endianness,
|
||||
initialBOMPolicy: u.bomPolicy,
|
||||
currentBOMPolicy: u.bomPolicy,
|
||||
}}
|
||||
}
|
||||
|
||||
func (u utf16Encoding) ID() (mib identifier.MIB, other string) {
|
||||
return u.mib, ""
|
||||
}
|
||||
|
||||
func (u utf16Encoding) String() string {
|
||||
e, b := "B", ""
|
||||
if u.endianness == LittleEndian {
|
||||
e = "L"
|
||||
}
|
||||
switch u.bomPolicy {
|
||||
case ExpectBOM:
|
||||
b = "Expect"
|
||||
case UseBOM:
|
||||
b = "Use"
|
||||
case IgnoreBOM:
|
||||
b = "Ignore"
|
||||
}
|
||||
return "UTF-16" + e + "E (" + b + " BOM)"
|
||||
}
|
||||
|
||||
type utf16Decoder struct {
|
||||
initial config
|
||||
current config
|
||||
}
|
||||
|
||||
func (u *utf16Decoder) Reset() {
|
||||
u.current = u.initial
|
||||
}
|
||||
|
||||
func (u *utf16Decoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
if len(src) < 2 && atEOF && u.current.bomPolicy&requireBOM != 0 {
|
||||
return 0, 0, ErrMissingBOM
|
||||
}
|
||||
if len(src) == 0 {
|
||||
return 0, 0, nil
|
||||
}
|
||||
if len(src) >= 2 && u.current.bomPolicy&acceptBOM != 0 {
|
||||
switch {
|
||||
case src[0] == 0xfe && src[1] == 0xff:
|
||||
u.current.endianness = BigEndian
|
||||
nSrc = 2
|
||||
case src[0] == 0xff && src[1] == 0xfe:
|
||||
u.current.endianness = LittleEndian
|
||||
nSrc = 2
|
||||
default:
|
||||
if u.current.bomPolicy&requireBOM != 0 {
|
||||
return 0, 0, ErrMissingBOM
|
||||
}
|
||||
}
|
||||
u.current.bomPolicy = IgnoreBOM
|
||||
}
|
||||
|
||||
var r rune
|
||||
var dSize, sSize int
|
||||
for nSrc < len(src) {
|
||||
if nSrc+1 < len(src) {
|
||||
x := uint16(src[nSrc+0])<<8 | uint16(src[nSrc+1])
|
||||
if u.current.endianness == LittleEndian {
|
||||
x = x>>8 | x<<8
|
||||
}
|
||||
r, sSize = rune(x), 2
|
||||
if utf16.IsSurrogate(r) {
|
||||
if nSrc+3 < len(src) {
|
||||
x = uint16(src[nSrc+2])<<8 | uint16(src[nSrc+3])
|
||||
if u.current.endianness == LittleEndian {
|
||||
x = x>>8 | x<<8
|
||||
}
|
||||
// Save for next iteration if it is not a high surrogate.
|
||||
if isHighSurrogate(rune(x)) {
|
||||
r, sSize = utf16.DecodeRune(r, rune(x)), 4
|
||||
}
|
||||
} else if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
if dSize = utf8.RuneLen(r); dSize < 0 {
|
||||
r, dSize = utf8.RuneError, 3
|
||||
}
|
||||
} else if atEOF {
|
||||
// Single trailing byte.
|
||||
r, dSize, sSize = utf8.RuneError, 3, 1
|
||||
} else {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
if nDst+dSize > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
nSrc += sSize
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
func isHighSurrogate(r rune) bool {
|
||||
return 0xDC00 <= r && r <= 0xDFFF
|
||||
}
|
||||
|
||||
type utf16Encoder struct {
|
||||
endianness Endianness
|
||||
initialBOMPolicy BOMPolicy
|
||||
currentBOMPolicy BOMPolicy
|
||||
}
|
||||
|
||||
func (u *utf16Encoder) Reset() {
|
||||
u.currentBOMPolicy = u.initialBOMPolicy
|
||||
}
|
||||
|
||||
func (u *utf16Encoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
if u.currentBOMPolicy&writeBOM != 0 {
|
||||
if len(dst) < 2 {
|
||||
return 0, 0, transform.ErrShortDst
|
||||
}
|
||||
dst[0], dst[1] = 0xfe, 0xff
|
||||
u.currentBOMPolicy = IgnoreBOM
|
||||
nDst = 2
|
||||
}
|
||||
|
||||
r, size := rune(0), 0
|
||||
for nSrc < len(src) {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if r <= 0xffff {
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = uint8(r >> 8)
|
||||
dst[nDst+1] = uint8(r)
|
||||
nDst += 2
|
||||
} else {
|
||||
if nDst+4 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
r1, r2 := utf16.EncodeRune(r)
|
||||
dst[nDst+0] = uint8(r1 >> 8)
|
||||
dst[nDst+1] = uint8(r1)
|
||||
dst[nDst+2] = uint8(r2 >> 8)
|
||||
dst[nDst+3] = uint8(r2)
|
||||
nDst += 4
|
||||
}
|
||||
nSrc += size
|
||||
}
|
||||
|
||||
if u.endianness == LittleEndian {
|
||||
for i := 0; i < nDst; i += 2 {
|
||||
dst[i], dst[i+1] = dst[i+1], dst[i]
|
||||
}
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
70
vendor/golang.org/x/text/feature/plural/common.go
generated
vendored
70
vendor/golang.org/x/text/feature/plural/common.go
generated
vendored
@ -1,70 +0,0 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
package plural
|
||||
|
||||
// Form defines a plural form.
|
||||
//
|
||||
// Not all languages support all forms. Also, the meaning of each form varies
|
||||
// per language. It is important to note that the name of a form does not
|
||||
// necessarily correspond one-to-one with the set of numbers. For instance,
|
||||
// for Croation, One matches not only 1, but also 11, 21, etc.
|
||||
//
|
||||
// Each language must at least support the form "other".
|
||||
type Form byte
|
||||
|
||||
const (
|
||||
Other Form = iota
|
||||
Zero
|
||||
One
|
||||
Two
|
||||
Few
|
||||
Many
|
||||
)
|
||||
|
||||
var countMap = map[string]Form{
|
||||
"other": Other,
|
||||
"zero": Zero,
|
||||
"one": One,
|
||||
"two": Two,
|
||||
"few": Few,
|
||||
"many": Many,
|
||||
}
|
||||
|
||||
type pluralCheck struct {
|
||||
// category:
|
||||
// 3..7: opID
|
||||
// 0..2: category
|
||||
cat byte
|
||||
setID byte
|
||||
}
|
||||
|
||||
// opID identifies the type of operand in the plural rule, being i, n or f.
|
||||
// (v, w, and t are treated as filters in our implementation.)
|
||||
type opID byte
|
||||
|
||||
const (
|
||||
opMod opID = 0x1 // is '%' used?
|
||||
opNotEqual opID = 0x2 // using "!=" to compare
|
||||
opI opID = 0 << 2 // integers after taking the absolute value
|
||||
opN opID = 1 << 2 // full number (must be integer)
|
||||
opF opID = 2 << 2 // fraction
|
||||
opV opID = 3 << 2 // number of visible digits
|
||||
opW opID = 4 << 2 // number of visible digits without trailing zeros
|
||||
opBretonM opID = 5 << 2 // hard-wired rule for Breton
|
||||
opItalian800 opID = 6 << 2 // hard-wired rule for Italian
|
||||
opAzerbaijan00s opID = 7 << 2 // hard-wired rule for Azerbaijan
|
||||
)
|
||||
const (
|
||||
// Use this plural form to indicate the next rule needs to match as well.
|
||||
// The last condition in the list will have the correct plural form.
|
||||
andNext = 0x7
|
||||
formMask = 0x7
|
||||
|
||||
opShift = 3
|
||||
|
||||
// numN indicates the maximum integer, or maximum mod value, for which we
|
||||
// have inclusion masks.
|
||||
numN = 100
|
||||
// The common denominator of the modulo that is taken.
|
||||
maxMod = 100
|
||||
)
|
244
vendor/golang.org/x/text/feature/plural/message.go
generated
vendored
244
vendor/golang.org/x/text/feature/plural/message.go
generated
vendored
@ -1,244 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package plural
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/text/internal/catmsg"
|
||||
"golang.org/x/text/internal/number"
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message/catalog"
|
||||
)
|
||||
|
||||
// TODO: consider deleting this interface. Maybe VisibleDigits is always
|
||||
// sufficient and practical.
|
||||
|
||||
// Interface is used for types that can determine their own plural form.
|
||||
type Interface interface {
|
||||
// PluralForm reports the plural form for the given language of the
|
||||
// underlying value. It also returns the integer value. If the integer value
|
||||
// is larger than fits in n, PluralForm may return a value modulo
|
||||
// 10,000,000.
|
||||
PluralForm(t language.Tag, scale int) (f Form, n int)
|
||||
}
|
||||
|
||||
// Selectf returns the first case for which its selector is a match for the
|
||||
// arg-th substitution argument to a formatting call, formatting it as indicated
|
||||
// by format.
|
||||
//
|
||||
// The cases argument are pairs of selectors and messages. Selectors are of type
|
||||
// string or Form. Messages are of type string or catalog.Message. A selector
|
||||
// matches an argument if:
|
||||
// - it is "other" or Other
|
||||
// - it matches the plural form of the argument: "zero", "one", "two", "few",
|
||||
// or "many", or the equivalent Form
|
||||
// - it is of the form "=x" where x is an integer that matches the value of
|
||||
// the argument.
|
||||
// - it is of the form "<x" where x is an integer that is larger than the
|
||||
// argument.
|
||||
//
|
||||
// The format argument determines the formatting parameters for which to
|
||||
// determine the plural form. This is especially relevant for non-integer
|
||||
// values.
|
||||
//
|
||||
// The format string may be "", in which case a best-effort attempt is made to
|
||||
// find a reasonable representation on which to base the plural form. Examples
|
||||
// of format strings are:
|
||||
// - %.2f decimal with scale 2
|
||||
// - %.2e scientific notation with precision 3 (scale + 1)
|
||||
// - %d integer
|
||||
func Selectf(arg int, format string, cases ...interface{}) catalog.Message {
|
||||
var p parser
|
||||
// Intercept the formatting parameters of format by doing a dummy print.
|
||||
fmt.Fprintf(io.Discard, format, &p)
|
||||
m := &message{arg, kindDefault, 0, cases}
|
||||
switch p.verb {
|
||||
case 'g':
|
||||
m.kind = kindPrecision
|
||||
m.scale = p.scale
|
||||
case 'f':
|
||||
m.kind = kindScale
|
||||
m.scale = p.scale
|
||||
case 'e':
|
||||
m.kind = kindScientific
|
||||
m.scale = p.scale
|
||||
case 'd':
|
||||
m.kind = kindScale
|
||||
m.scale = 0
|
||||
default:
|
||||
// TODO: do we need to handle errors?
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
type parser struct {
|
||||
verb rune
|
||||
scale int
|
||||
}
|
||||
|
||||
func (p *parser) Format(s fmt.State, verb rune) {
|
||||
p.verb = verb
|
||||
p.scale = -1
|
||||
if prec, ok := s.Precision(); ok {
|
||||
p.scale = prec
|
||||
}
|
||||
}
|
||||
|
||||
type message struct {
|
||||
arg int
|
||||
kind int
|
||||
scale int
|
||||
cases []interface{}
|
||||
}
|
||||
|
||||
const (
|
||||
// Start with non-ASCII to allow skipping values.
|
||||
kindDefault = 0x80 + iota
|
||||
kindScale // verb f, number of fraction digits follows
|
||||
kindScientific // verb e, number of fraction digits follows
|
||||
kindPrecision // verb g, number of significant digits follows
|
||||
)
|
||||
|
||||
var handle = catmsg.Register("golang.org/x/text/feature/plural:plural", execute)
|
||||
|
||||
func (m *message) Compile(e *catmsg.Encoder) error {
|
||||
e.EncodeMessageType(handle)
|
||||
|
||||
e.EncodeUint(uint64(m.arg))
|
||||
|
||||
e.EncodeUint(uint64(m.kind))
|
||||
if m.kind > kindDefault {
|
||||
e.EncodeUint(uint64(m.scale))
|
||||
}
|
||||
|
||||
forms := validForms(cardinal, e.Language())
|
||||
|
||||
for i := 0; i < len(m.cases); {
|
||||
if err := compileSelector(e, forms, m.cases[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
if i++; i >= len(m.cases) {
|
||||
return fmt.Errorf("plural: no message defined for selector %v", m.cases[i-1])
|
||||
}
|
||||
var msg catalog.Message
|
||||
switch x := m.cases[i].(type) {
|
||||
case string:
|
||||
msg = catalog.String(x)
|
||||
case catalog.Message:
|
||||
msg = x
|
||||
default:
|
||||
return fmt.Errorf("plural: message of type %T; must be string or catalog.Message", x)
|
||||
}
|
||||
if err := e.EncodeMessage(msg); err != nil {
|
||||
return err
|
||||
}
|
||||
i++
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func compileSelector(e *catmsg.Encoder, valid []Form, selector interface{}) error {
|
||||
form := Other
|
||||
switch x := selector.(type) {
|
||||
case string:
|
||||
if x == "" {
|
||||
return fmt.Errorf("plural: empty selector")
|
||||
}
|
||||
if c := x[0]; c == '=' || c == '<' {
|
||||
val, err := strconv.ParseUint(x[1:], 10, 16)
|
||||
if err != nil {
|
||||
return fmt.Errorf("plural: invalid number in selector %q: %v", selector, err)
|
||||
}
|
||||
e.EncodeUint(uint64(c))
|
||||
e.EncodeUint(val)
|
||||
return nil
|
||||
}
|
||||
var ok bool
|
||||
form, ok = countMap[x]
|
||||
if !ok {
|
||||
return fmt.Errorf("plural: invalid plural form %q", selector)
|
||||
}
|
||||
case Form:
|
||||
form = x
|
||||
default:
|
||||
return fmt.Errorf("plural: selector of type %T; want string or Form", selector)
|
||||
}
|
||||
|
||||
ok := false
|
||||
for _, f := range valid {
|
||||
if f == form {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf("plural: form %q not supported for language %q", selector, e.Language())
|
||||
}
|
||||
e.EncodeUint(uint64(form))
|
||||
return nil
|
||||
}
|
||||
|
||||
func execute(d *catmsg.Decoder) bool {
|
||||
lang := d.Language()
|
||||
argN := int(d.DecodeUint())
|
||||
kind := int(d.DecodeUint())
|
||||
scale := -1 // default
|
||||
if kind > kindDefault {
|
||||
scale = int(d.DecodeUint())
|
||||
}
|
||||
form := Other
|
||||
n := -1
|
||||
if arg := d.Arg(argN); arg == nil {
|
||||
// Default to Other.
|
||||
} else if x, ok := arg.(number.VisibleDigits); ok {
|
||||
d := x.Digits(nil, lang, scale)
|
||||
form, n = cardinal.matchDisplayDigits(lang, &d)
|
||||
} else if x, ok := arg.(Interface); ok {
|
||||
// This covers lists and formatters from the number package.
|
||||
form, n = x.PluralForm(lang, scale)
|
||||
} else {
|
||||
var f number.Formatter
|
||||
switch kind {
|
||||
case kindScale:
|
||||
f.InitDecimal(lang)
|
||||
f.SetScale(scale)
|
||||
case kindScientific:
|
||||
f.InitScientific(lang)
|
||||
f.SetScale(scale)
|
||||
case kindPrecision:
|
||||
f.InitDecimal(lang)
|
||||
f.SetPrecision(scale)
|
||||
case kindDefault:
|
||||
// sensible default
|
||||
f.InitDecimal(lang)
|
||||
if k := reflect.TypeOf(arg).Kind(); reflect.Int <= k && k <= reflect.Uintptr {
|
||||
f.SetScale(0)
|
||||
} else {
|
||||
f.SetScale(2)
|
||||
}
|
||||
}
|
||||
var dec number.Decimal // TODO: buffer in Printer
|
||||
dec.Convert(f.RoundingContext, arg)
|
||||
v := number.FormatDigits(&dec, f.RoundingContext)
|
||||
if !v.NaN && !v.Inf {
|
||||
form, n = cardinal.matchDisplayDigits(d.Language(), &v)
|
||||
}
|
||||
}
|
||||
for !d.Done() {
|
||||
f := d.DecodeUint()
|
||||
if (f == '=' && n == int(d.DecodeUint())) ||
|
||||
(f == '<' && 0 <= n && n < int(d.DecodeUint())) ||
|
||||
form == Form(f) ||
|
||||
Other == Form(f) {
|
||||
return d.ExecuteMessage()
|
||||
}
|
||||
d.SkipMessage()
|
||||
}
|
||||
return false
|
||||
}
|
262
vendor/golang.org/x/text/feature/plural/plural.go
generated
vendored
262
vendor/golang.org/x/text/feature/plural/plural.go
generated
vendored
@ -1,262 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run gen.go gen_common.go
|
||||
|
||||
// Package plural provides utilities for handling linguistic plurals in text.
|
||||
//
|
||||
// The definitions in this package are based on the plural rule handling defined
|
||||
// in CLDR. See
|
||||
// https://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules for
|
||||
// details.
|
||||
package plural
|
||||
|
||||
import (
|
||||
"golang.org/x/text/internal/language/compact"
|
||||
"golang.org/x/text/internal/number"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// Rules defines the plural rules for all languages for a certain plural type.
|
||||
//
|
||||
// This package is UNDER CONSTRUCTION and its API may change.
|
||||
type Rules struct {
|
||||
rules []pluralCheck
|
||||
index []byte
|
||||
langToIndex []byte
|
||||
inclusionMasks []uint64
|
||||
}
|
||||
|
||||
var (
|
||||
// Cardinal defines the plural rules for numbers indicating quantities.
|
||||
Cardinal *Rules = cardinal
|
||||
|
||||
// Ordinal defines the plural rules for numbers indicating position
|
||||
// (first, second, etc.).
|
||||
Ordinal *Rules = ordinal
|
||||
|
||||
ordinal = &Rules{
|
||||
ordinalRules,
|
||||
ordinalIndex,
|
||||
ordinalLangToIndex,
|
||||
ordinalInclusionMasks[:],
|
||||
}
|
||||
|
||||
cardinal = &Rules{
|
||||
cardinalRules,
|
||||
cardinalIndex,
|
||||
cardinalLangToIndex,
|
||||
cardinalInclusionMasks[:],
|
||||
}
|
||||
)
|
||||
|
||||
// getIntApprox converts the digits in slice digits[start:end] to an integer
|
||||
// according to the following rules:
|
||||
// - Let i be asInt(digits[start:end]), where out-of-range digits are assumed
|
||||
// to be zero.
|
||||
// - Result n is big if i / 10^nMod > 1.
|
||||
// - Otherwise the result is i % 10^nMod.
|
||||
//
|
||||
// For example, if digits is {1, 2, 3} and start:end is 0:5, then the result
|
||||
// for various values of nMod is:
|
||||
// - when nMod == 2, n == big
|
||||
// - when nMod == 3, n == big
|
||||
// - when nMod == 4, n == big
|
||||
// - when nMod == 5, n == 12300
|
||||
// - when nMod == 6, n == 12300
|
||||
// - when nMod == 7, n == 12300
|
||||
func getIntApprox(digits []byte, start, end, nMod, big int) (n int) {
|
||||
// Leading 0 digits just result in 0.
|
||||
p := start
|
||||
if p < 0 {
|
||||
p = 0
|
||||
}
|
||||
// Range only over the part for which we have digits.
|
||||
mid := end
|
||||
if mid >= len(digits) {
|
||||
mid = len(digits)
|
||||
}
|
||||
// Check digits more significant that nMod.
|
||||
if q := end - nMod; q > 0 {
|
||||
if q > mid {
|
||||
q = mid
|
||||
}
|
||||
for ; p < q; p++ {
|
||||
if digits[p] != 0 {
|
||||
return big
|
||||
}
|
||||
}
|
||||
}
|
||||
for ; p < mid; p++ {
|
||||
n = 10*n + int(digits[p])
|
||||
}
|
||||
// Multiply for trailing zeros.
|
||||
for ; p < end; p++ {
|
||||
n *= 10
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// MatchDigits computes the plural form for the given language and the given
|
||||
// decimal floating point digits. The digits are stored in big-endian order and
|
||||
// are of value byte(0) - byte(9). The floating point position is indicated by
|
||||
// exp and the number of visible decimals is scale. All leading and trailing
|
||||
// zeros may be omitted from digits.
|
||||
//
|
||||
// The following table contains examples of possible arguments to represent
|
||||
// the given numbers.
|
||||
//
|
||||
// decimal digits exp scale
|
||||
// 123 []byte{1, 2, 3} 3 0
|
||||
// 123.4 []byte{1, 2, 3, 4} 3 1
|
||||
// 123.40 []byte{1, 2, 3, 4} 3 2
|
||||
// 100000 []byte{1} 6 0
|
||||
// 100000.00 []byte{1} 6 3
|
||||
func (p *Rules) MatchDigits(t language.Tag, digits []byte, exp, scale int) Form {
|
||||
index := tagToID(t)
|
||||
|
||||
// Differentiate up to including mod 1000000 for the integer part.
|
||||
n := getIntApprox(digits, 0, exp, 6, 1000000)
|
||||
|
||||
// Differentiate up to including mod 100 for the fractional part.
|
||||
f := getIntApprox(digits, exp, exp+scale, 2, 100)
|
||||
|
||||
return matchPlural(p, index, n, f, scale)
|
||||
}
|
||||
|
||||
func (p *Rules) matchDisplayDigits(t language.Tag, d *number.Digits) (Form, int) {
|
||||
n := getIntApprox(d.Digits, 0, int(d.Exp), 6, 1000000)
|
||||
return p.MatchDigits(t, d.Digits, int(d.Exp), d.NumFracDigits()), n
|
||||
}
|
||||
|
||||
func validForms(p *Rules, t language.Tag) (forms []Form) {
|
||||
offset := p.langToIndex[tagToID(t)]
|
||||
rules := p.rules[p.index[offset]:p.index[offset+1]]
|
||||
|
||||
forms = append(forms, Other)
|
||||
last := Other
|
||||
for _, r := range rules {
|
||||
if cat := Form(r.cat & formMask); cat != andNext && last != cat {
|
||||
forms = append(forms, cat)
|
||||
last = cat
|
||||
}
|
||||
}
|
||||
return forms
|
||||
}
|
||||
|
||||
func (p *Rules) matchComponents(t language.Tag, n, f, scale int) Form {
|
||||
return matchPlural(p, tagToID(t), n, f, scale)
|
||||
}
|
||||
|
||||
// MatchPlural returns the plural form for the given language and plural
|
||||
// operands (as defined in
|
||||
// https://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules):
|
||||
//
|
||||
// where
|
||||
// n absolute value of the source number (integer and decimals)
|
||||
// input
|
||||
// i integer digits of n.
|
||||
// v number of visible fraction digits in n, with trailing zeros.
|
||||
// w number of visible fraction digits in n, without trailing zeros.
|
||||
// f visible fractional digits in n, with trailing zeros (f = t * 10^(v-w))
|
||||
// t visible fractional digits in n, without trailing zeros.
|
||||
//
|
||||
// If any of the operand values is too large to fit in an int, it is okay to
|
||||
// pass the value modulo 10,000,000.
|
||||
func (p *Rules) MatchPlural(lang language.Tag, i, v, w, f, t int) Form {
|
||||
return matchPlural(p, tagToID(lang), i, f, v)
|
||||
}
|
||||
|
||||
func matchPlural(p *Rules, index compact.ID, n, f, v int) Form {
|
||||
nMask := p.inclusionMasks[n%maxMod]
|
||||
// Compute the fMask inline in the rules below, as it is relatively rare.
|
||||
// fMask := p.inclusionMasks[f%maxMod]
|
||||
vMask := p.inclusionMasks[v%maxMod]
|
||||
|
||||
// Do the matching
|
||||
offset := p.langToIndex[index]
|
||||
rules := p.rules[p.index[offset]:p.index[offset+1]]
|
||||
for i := 0; i < len(rules); i++ {
|
||||
rule := rules[i]
|
||||
setBit := uint64(1 << rule.setID)
|
||||
var skip bool
|
||||
switch op := opID(rule.cat >> opShift); op {
|
||||
case opI: // i = x
|
||||
skip = n >= numN || nMask&setBit == 0
|
||||
|
||||
case opI | opNotEqual: // i != x
|
||||
skip = n < numN && nMask&setBit != 0
|
||||
|
||||
case opI | opMod: // i % m = x
|
||||
skip = nMask&setBit == 0
|
||||
|
||||
case opI | opMod | opNotEqual: // i % m != x
|
||||
skip = nMask&setBit != 0
|
||||
|
||||
case opN: // n = x
|
||||
skip = f != 0 || n >= numN || nMask&setBit == 0
|
||||
|
||||
case opN | opNotEqual: // n != x
|
||||
skip = f == 0 && n < numN && nMask&setBit != 0
|
||||
|
||||
case opN | opMod: // n % m = x
|
||||
skip = f != 0 || nMask&setBit == 0
|
||||
|
||||
case opN | opMod | opNotEqual: // n % m != x
|
||||
skip = f == 0 && nMask&setBit != 0
|
||||
|
||||
case opF: // f = x
|
||||
skip = f >= numN || p.inclusionMasks[f%maxMod]&setBit == 0
|
||||
|
||||
case opF | opNotEqual: // f != x
|
||||
skip = f < numN && p.inclusionMasks[f%maxMod]&setBit != 0
|
||||
|
||||
case opF | opMod: // f % m = x
|
||||
skip = p.inclusionMasks[f%maxMod]&setBit == 0
|
||||
|
||||
case opF | opMod | opNotEqual: // f % m != x
|
||||
skip = p.inclusionMasks[f%maxMod]&setBit != 0
|
||||
|
||||
case opV: // v = x
|
||||
skip = v < numN && vMask&setBit == 0
|
||||
|
||||
case opV | opNotEqual: // v != x
|
||||
skip = v < numN && vMask&setBit != 0
|
||||
|
||||
case opW: // w == 0
|
||||
skip = f != 0
|
||||
|
||||
case opW | opNotEqual: // w != 0
|
||||
skip = f == 0
|
||||
|
||||
// Hard-wired rules that cannot be handled by our algorithm.
|
||||
|
||||
case opBretonM:
|
||||
skip = f != 0 || n == 0 || n%1000000 != 0
|
||||
|
||||
case opAzerbaijan00s:
|
||||
// 100,200,300,400,500,600,700,800,900
|
||||
skip = n == 0 || n >= 1000 || n%100 != 0
|
||||
|
||||
case opItalian800:
|
||||
skip = (f != 0 || n >= numN || nMask&setBit == 0) && n != 800
|
||||
}
|
||||
if skip {
|
||||
// advance over AND entries.
|
||||
for ; i < len(rules) && rules[i].cat&formMask == andNext; i++ {
|
||||
}
|
||||
continue
|
||||
}
|
||||
// return if we have a final entry.
|
||||
if cat := rule.cat & formMask; cat != andNext {
|
||||
return Form(cat)
|
||||
}
|
||||
}
|
||||
return Other
|
||||
}
|
||||
|
||||
func tagToID(t language.Tag) compact.ID {
|
||||
id, _ := compact.RegionalID(compact.Tag(t))
|
||||
return id
|
||||
}
|
552
vendor/golang.org/x/text/feature/plural/tables.go
generated
vendored
552
vendor/golang.org/x/text/feature/plural/tables.go
generated
vendored
@ -1,552 +0,0 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
package plural
|
||||
|
||||
// CLDRVersion is the CLDR version from which the tables in this package are derived.
|
||||
const CLDRVersion = "32"
|
||||
|
||||
var ordinalRules = []pluralCheck{ // 64 elements
|
||||
0: {cat: 0x2f, setID: 0x4},
|
||||
1: {cat: 0x3a, setID: 0x5},
|
||||
2: {cat: 0x22, setID: 0x1},
|
||||
3: {cat: 0x22, setID: 0x6},
|
||||
4: {cat: 0x22, setID: 0x7},
|
||||
5: {cat: 0x2f, setID: 0x8},
|
||||
6: {cat: 0x3c, setID: 0x9},
|
||||
7: {cat: 0x2f, setID: 0xa},
|
||||
8: {cat: 0x3c, setID: 0xb},
|
||||
9: {cat: 0x2c, setID: 0xc},
|
||||
10: {cat: 0x24, setID: 0xd},
|
||||
11: {cat: 0x2d, setID: 0xe},
|
||||
12: {cat: 0x2d, setID: 0xf},
|
||||
13: {cat: 0x2f, setID: 0x10},
|
||||
14: {cat: 0x35, setID: 0x3},
|
||||
15: {cat: 0xc5, setID: 0x11},
|
||||
16: {cat: 0x2, setID: 0x1},
|
||||
17: {cat: 0x5, setID: 0x3},
|
||||
18: {cat: 0xd, setID: 0x12},
|
||||
19: {cat: 0x22, setID: 0x1},
|
||||
20: {cat: 0x2f, setID: 0x13},
|
||||
21: {cat: 0x3d, setID: 0x14},
|
||||
22: {cat: 0x2f, setID: 0x15},
|
||||
23: {cat: 0x3a, setID: 0x16},
|
||||
24: {cat: 0x2f, setID: 0x17},
|
||||
25: {cat: 0x3b, setID: 0x18},
|
||||
26: {cat: 0x2f, setID: 0xa},
|
||||
27: {cat: 0x3c, setID: 0xb},
|
||||
28: {cat: 0x22, setID: 0x1},
|
||||
29: {cat: 0x23, setID: 0x19},
|
||||
30: {cat: 0x24, setID: 0x1a},
|
||||
31: {cat: 0x22, setID: 0x1b},
|
||||
32: {cat: 0x23, setID: 0x2},
|
||||
33: {cat: 0x24, setID: 0x1a},
|
||||
34: {cat: 0xf, setID: 0x15},
|
||||
35: {cat: 0x1a, setID: 0x16},
|
||||
36: {cat: 0xf, setID: 0x17},
|
||||
37: {cat: 0x1b, setID: 0x18},
|
||||
38: {cat: 0xf, setID: 0x1c},
|
||||
39: {cat: 0x1d, setID: 0x1d},
|
||||
40: {cat: 0xa, setID: 0x1e},
|
||||
41: {cat: 0xa, setID: 0x1f},
|
||||
42: {cat: 0xc, setID: 0x20},
|
||||
43: {cat: 0xe4, setID: 0x0},
|
||||
44: {cat: 0x5, setID: 0x3},
|
||||
45: {cat: 0xd, setID: 0xe},
|
||||
46: {cat: 0xd, setID: 0x21},
|
||||
47: {cat: 0x22, setID: 0x1},
|
||||
48: {cat: 0x23, setID: 0x19},
|
||||
49: {cat: 0x24, setID: 0x1a},
|
||||
50: {cat: 0x25, setID: 0x22},
|
||||
51: {cat: 0x22, setID: 0x23},
|
||||
52: {cat: 0x23, setID: 0x19},
|
||||
53: {cat: 0x24, setID: 0x1a},
|
||||
54: {cat: 0x25, setID: 0x22},
|
||||
55: {cat: 0x22, setID: 0x24},
|
||||
56: {cat: 0x23, setID: 0x19},
|
||||
57: {cat: 0x24, setID: 0x1a},
|
||||
58: {cat: 0x25, setID: 0x22},
|
||||
59: {cat: 0x21, setID: 0x25},
|
||||
60: {cat: 0x22, setID: 0x1},
|
||||
61: {cat: 0x23, setID: 0x2},
|
||||
62: {cat: 0x24, setID: 0x26},
|
||||
63: {cat: 0x25, setID: 0x27},
|
||||
} // Size: 152 bytes
|
||||
|
||||
var ordinalIndex = []uint8{ // 22 elements
|
||||
0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x07, 0x09,
|
||||
0x0b, 0x0f, 0x10, 0x13, 0x16, 0x1c, 0x1f, 0x22,
|
||||
0x28, 0x2f, 0x33, 0x37, 0x3b, 0x40,
|
||||
} // Size: 46 bytes
|
||||
|
||||
var ordinalLangToIndex = []uint8{ // 775 elements
|
||||
// Entry 0 - 3F
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0x00, 0x00, 0x05, 0x05, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Entry 40 - 7F
|
||||
0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e,
|
||||
0x0e, 0x0e, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Entry 80 - BF
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
// Entry C0 - FF
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Entry 100 - 13F
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
|
||||
0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
// Entry 140 - 17F
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
|
||||
0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
|
||||
0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Entry 180 - 1BF
|
||||
0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09,
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Entry 1C0 - 1FF
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00,
|
||||
0x00, 0x00, 0x02, 0x0d, 0x0d, 0x02, 0x02, 0x02,
|
||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Entry 200 - 23F
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x13, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Entry 240 - 27F
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||
0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Entry 280 - 2BF
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0b, 0x0b, 0x0b, 0x0b, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x07, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||
// Entry 2C0 - 2FF
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Entry 300 - 33F
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0c,
|
||||
} // Size: 799 bytes
|
||||
|
||||
var ordinalInclusionMasks = []uint64{ // 100 elements
|
||||
// Entry 0 - 1F
|
||||
0x0000002000010009, 0x00000018482000d3, 0x0000000042840195, 0x000000410a040581,
|
||||
0x00000041040c0081, 0x0000009840040041, 0x0000008400045001, 0x0000003850040001,
|
||||
0x0000003850060001, 0x0000003800049001, 0x0000000800052001, 0x0000000040660031,
|
||||
0x0000000041840331, 0x0000000100040f01, 0x00000001001c0001, 0x0000000040040001,
|
||||
0x0000000000045001, 0x0000000070040001, 0x0000000070040001, 0x0000000000049001,
|
||||
0x0000000080050001, 0x0000000040200011, 0x0000000040800111, 0x0000000100000501,
|
||||
0x0000000100080001, 0x0000000040000001, 0x0000000000005001, 0x0000000050000001,
|
||||
0x0000000050000001, 0x0000000000009001, 0x0000000000010001, 0x0000000040200011,
|
||||
// Entry 20 - 3F
|
||||
0x0000000040800111, 0x0000000100000501, 0x0000000100080001, 0x0000000040000001,
|
||||
0x0000000000005001, 0x0000000050000001, 0x0000000050000001, 0x0000000000009001,
|
||||
0x0000000200050001, 0x0000000040200011, 0x0000000040800111, 0x0000000100000501,
|
||||
0x0000000100080001, 0x0000000040000001, 0x0000000000005001, 0x0000000050000001,
|
||||
0x0000000050000001, 0x0000000000009001, 0x0000000080010001, 0x0000000040200011,
|
||||
0x0000000040800111, 0x0000000100000501, 0x0000000100080001, 0x0000000040000001,
|
||||
0x0000000000005001, 0x0000000050000001, 0x0000000050000001, 0x0000000000009001,
|
||||
0x0000000200050001, 0x0000000040200011, 0x0000000040800111, 0x0000000100000501,
|
||||
// Entry 40 - 5F
|
||||
0x0000000100080001, 0x0000000040000001, 0x0000000000005001, 0x0000000050000001,
|
||||
0x0000000050000001, 0x0000000000009001, 0x0000000080010001, 0x0000000040200011,
|
||||
0x0000000040800111, 0x0000000100000501, 0x0000000100080001, 0x0000000040000001,
|
||||
0x0000000000005001, 0x0000000050000001, 0x0000000050000001, 0x0000000000009001,
|
||||
0x0000000080070001, 0x0000000040200011, 0x0000000040800111, 0x0000000100000501,
|
||||
0x0000000100080001, 0x0000000040000001, 0x0000000000005001, 0x0000000050000001,
|
||||
0x0000000050000001, 0x0000000000009001, 0x0000000200010001, 0x0000000040200011,
|
||||
0x0000000040800111, 0x0000000100000501, 0x0000000100080001, 0x0000000040000001,
|
||||
// Entry 60 - 7F
|
||||
0x0000000000005001, 0x0000000050000001, 0x0000000050000001, 0x0000000000009001,
|
||||
} // Size: 824 bytes
|
||||
|
||||
// Slots used for ordinal: 40 of 0xFF rules; 16 of 0xFF indexes; 40 of 64 sets
|
||||
|
||||
var cardinalRules = []pluralCheck{ // 166 elements
|
||||
0: {cat: 0x2, setID: 0x3},
|
||||
1: {cat: 0x22, setID: 0x1},
|
||||
2: {cat: 0x2, setID: 0x4},
|
||||
3: {cat: 0x2, setID: 0x4},
|
||||
4: {cat: 0x7, setID: 0x1},
|
||||
5: {cat: 0x62, setID: 0x3},
|
||||
6: {cat: 0x22, setID: 0x4},
|
||||
7: {cat: 0x7, setID: 0x3},
|
||||
8: {cat: 0x42, setID: 0x1},
|
||||
9: {cat: 0x22, setID: 0x4},
|
||||
10: {cat: 0x22, setID: 0x4},
|
||||
11: {cat: 0x22, setID: 0x5},
|
||||
12: {cat: 0x22, setID: 0x1},
|
||||
13: {cat: 0x22, setID: 0x1},
|
||||
14: {cat: 0x7, setID: 0x4},
|
||||
15: {cat: 0x92, setID: 0x3},
|
||||
16: {cat: 0xf, setID: 0x6},
|
||||
17: {cat: 0x1f, setID: 0x7},
|
||||
18: {cat: 0x82, setID: 0x3},
|
||||
19: {cat: 0x92, setID: 0x3},
|
||||
20: {cat: 0xf, setID: 0x6},
|
||||
21: {cat: 0x62, setID: 0x3},
|
||||
22: {cat: 0x4a, setID: 0x6},
|
||||
23: {cat: 0x7, setID: 0x8},
|
||||
24: {cat: 0x62, setID: 0x3},
|
||||
25: {cat: 0x1f, setID: 0x9},
|
||||
26: {cat: 0x62, setID: 0x3},
|
||||
27: {cat: 0x5f, setID: 0x9},
|
||||
28: {cat: 0x72, setID: 0x3},
|
||||
29: {cat: 0x29, setID: 0xa},
|
||||
30: {cat: 0x29, setID: 0xb},
|
||||
31: {cat: 0x4f, setID: 0xb},
|
||||
32: {cat: 0x61, setID: 0x2},
|
||||
33: {cat: 0x2f, setID: 0x6},
|
||||
34: {cat: 0x3a, setID: 0x7},
|
||||
35: {cat: 0x4f, setID: 0x6},
|
||||
36: {cat: 0x5f, setID: 0x7},
|
||||
37: {cat: 0x62, setID: 0x2},
|
||||
38: {cat: 0x4f, setID: 0x6},
|
||||
39: {cat: 0x72, setID: 0x2},
|
||||
40: {cat: 0x21, setID: 0x3},
|
||||
41: {cat: 0x7, setID: 0x4},
|
||||
42: {cat: 0x32, setID: 0x3},
|
||||
43: {cat: 0x21, setID: 0x3},
|
||||
44: {cat: 0x22, setID: 0x1},
|
||||
45: {cat: 0x22, setID: 0x1},
|
||||
46: {cat: 0x23, setID: 0x2},
|
||||
47: {cat: 0x2, setID: 0x3},
|
||||
48: {cat: 0x22, setID: 0x1},
|
||||
49: {cat: 0x24, setID: 0xc},
|
||||
50: {cat: 0x7, setID: 0x1},
|
||||
51: {cat: 0x62, setID: 0x3},
|
||||
52: {cat: 0x74, setID: 0x3},
|
||||
53: {cat: 0x24, setID: 0x3},
|
||||
54: {cat: 0x2f, setID: 0xd},
|
||||
55: {cat: 0x34, setID: 0x1},
|
||||
56: {cat: 0xf, setID: 0x6},
|
||||
57: {cat: 0x1f, setID: 0x7},
|
||||
58: {cat: 0x62, setID: 0x3},
|
||||
59: {cat: 0x4f, setID: 0x6},
|
||||
60: {cat: 0x5a, setID: 0x7},
|
||||
61: {cat: 0xf, setID: 0xe},
|
||||
62: {cat: 0x1f, setID: 0xf},
|
||||
63: {cat: 0x64, setID: 0x3},
|
||||
64: {cat: 0x4f, setID: 0xe},
|
||||
65: {cat: 0x5c, setID: 0xf},
|
||||
66: {cat: 0x22, setID: 0x10},
|
||||
67: {cat: 0x23, setID: 0x11},
|
||||
68: {cat: 0x24, setID: 0x12},
|
||||
69: {cat: 0xf, setID: 0x1},
|
||||
70: {cat: 0x62, setID: 0x3},
|
||||
71: {cat: 0xf, setID: 0x2},
|
||||
72: {cat: 0x63, setID: 0x3},
|
||||
73: {cat: 0xf, setID: 0x13},
|
||||
74: {cat: 0x64, setID: 0x3},
|
||||
75: {cat: 0x74, setID: 0x3},
|
||||
76: {cat: 0xf, setID: 0x1},
|
||||
77: {cat: 0x62, setID: 0x3},
|
||||
78: {cat: 0x4a, setID: 0x1},
|
||||
79: {cat: 0xf, setID: 0x2},
|
||||
80: {cat: 0x63, setID: 0x3},
|
||||
81: {cat: 0x4b, setID: 0x2},
|
||||
82: {cat: 0xf, setID: 0x13},
|
||||
83: {cat: 0x64, setID: 0x3},
|
||||
84: {cat: 0x4c, setID: 0x13},
|
||||
85: {cat: 0x7, setID: 0x1},
|
||||
86: {cat: 0x62, setID: 0x3},
|
||||
87: {cat: 0x7, setID: 0x2},
|
||||
88: {cat: 0x63, setID: 0x3},
|
||||
89: {cat: 0x2f, setID: 0xa},
|
||||
90: {cat: 0x37, setID: 0x14},
|
||||
91: {cat: 0x65, setID: 0x3},
|
||||
92: {cat: 0x7, setID: 0x1},
|
||||
93: {cat: 0x62, setID: 0x3},
|
||||
94: {cat: 0x7, setID: 0x15},
|
||||
95: {cat: 0x64, setID: 0x3},
|
||||
96: {cat: 0x75, setID: 0x3},
|
||||
97: {cat: 0x7, setID: 0x1},
|
||||
98: {cat: 0x62, setID: 0x3},
|
||||
99: {cat: 0xf, setID: 0xe},
|
||||
100: {cat: 0x1f, setID: 0xf},
|
||||
101: {cat: 0x64, setID: 0x3},
|
||||
102: {cat: 0xf, setID: 0x16},
|
||||
103: {cat: 0x17, setID: 0x1},
|
||||
104: {cat: 0x65, setID: 0x3},
|
||||
105: {cat: 0xf, setID: 0x17},
|
||||
106: {cat: 0x65, setID: 0x3},
|
||||
107: {cat: 0xf, setID: 0xf},
|
||||
108: {cat: 0x65, setID: 0x3},
|
||||
109: {cat: 0x2f, setID: 0x6},
|
||||
110: {cat: 0x3a, setID: 0x7},
|
||||
111: {cat: 0x2f, setID: 0xe},
|
||||
112: {cat: 0x3c, setID: 0xf},
|
||||
113: {cat: 0x2d, setID: 0xa},
|
||||
114: {cat: 0x2d, setID: 0x17},
|
||||
115: {cat: 0x2d, setID: 0x18},
|
||||
116: {cat: 0x2f, setID: 0x6},
|
||||
117: {cat: 0x3a, setID: 0xb},
|
||||
118: {cat: 0x2f, setID: 0x19},
|
||||
119: {cat: 0x3c, setID: 0xb},
|
||||
120: {cat: 0x55, setID: 0x3},
|
||||
121: {cat: 0x22, setID: 0x1},
|
||||
122: {cat: 0x24, setID: 0x3},
|
||||
123: {cat: 0x2c, setID: 0xc},
|
||||
124: {cat: 0x2d, setID: 0xb},
|
||||
125: {cat: 0xf, setID: 0x6},
|
||||
126: {cat: 0x1f, setID: 0x7},
|
||||
127: {cat: 0x62, setID: 0x3},
|
||||
128: {cat: 0xf, setID: 0xe},
|
||||
129: {cat: 0x1f, setID: 0xf},
|
||||
130: {cat: 0x64, setID: 0x3},
|
||||
131: {cat: 0xf, setID: 0xa},
|
||||
132: {cat: 0x65, setID: 0x3},
|
||||
133: {cat: 0xf, setID: 0x17},
|
||||
134: {cat: 0x65, setID: 0x3},
|
||||
135: {cat: 0xf, setID: 0x18},
|
||||
136: {cat: 0x65, setID: 0x3},
|
||||
137: {cat: 0x2f, setID: 0x6},
|
||||
138: {cat: 0x3a, setID: 0x1a},
|
||||
139: {cat: 0x2f, setID: 0x1b},
|
||||
140: {cat: 0x3b, setID: 0x1c},
|
||||
141: {cat: 0x2f, setID: 0x1d},
|
||||
142: {cat: 0x3c, setID: 0x1e},
|
||||
143: {cat: 0x37, setID: 0x3},
|
||||
144: {cat: 0xa5, setID: 0x0},
|
||||
145: {cat: 0x22, setID: 0x1},
|
||||
146: {cat: 0x23, setID: 0x2},
|
||||
147: {cat: 0x24, setID: 0x1f},
|
||||
148: {cat: 0x25, setID: 0x20},
|
||||
149: {cat: 0xf, setID: 0x6},
|
||||
150: {cat: 0x62, setID: 0x3},
|
||||
151: {cat: 0xf, setID: 0x1b},
|
||||
152: {cat: 0x63, setID: 0x3},
|
||||
153: {cat: 0xf, setID: 0x21},
|
||||
154: {cat: 0x64, setID: 0x3},
|
||||
155: {cat: 0x75, setID: 0x3},
|
||||
156: {cat: 0x21, setID: 0x3},
|
||||
157: {cat: 0x22, setID: 0x1},
|
||||
158: {cat: 0x23, setID: 0x2},
|
||||
159: {cat: 0x2c, setID: 0x22},
|
||||
160: {cat: 0x2d, setID: 0x5},
|
||||
161: {cat: 0x21, setID: 0x3},
|
||||
162: {cat: 0x22, setID: 0x1},
|
||||
163: {cat: 0x23, setID: 0x2},
|
||||
164: {cat: 0x24, setID: 0x23},
|
||||
165: {cat: 0x25, setID: 0x24},
|
||||
} // Size: 356 bytes
|
||||
|
||||
var cardinalIndex = []uint8{ // 36 elements
|
||||
0x00, 0x00, 0x02, 0x03, 0x04, 0x06, 0x09, 0x0a,
|
||||
0x0c, 0x0d, 0x10, 0x14, 0x17, 0x1d, 0x28, 0x2b,
|
||||
0x2d, 0x2f, 0x32, 0x38, 0x42, 0x45, 0x4c, 0x55,
|
||||
0x5c, 0x61, 0x6d, 0x74, 0x79, 0x7d, 0x89, 0x91,
|
||||
0x95, 0x9c, 0xa1, 0xa6,
|
||||
} // Size: 60 bytes
|
||||
|
||||
var cardinalLangToIndex = []uint8{ // 775 elements
|
||||
// Entry 0 - 3F
|
||||
0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x06, 0x06,
|
||||
0x01, 0x01, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
|
||||
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
|
||||
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
|
||||
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
|
||||
0x01, 0x01, 0x08, 0x08, 0x04, 0x04, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x00, 0x00, 0x1a, 0x1a, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x06, 0x00, 0x00,
|
||||
// Entry 40 - 7F
|
||||
0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x1e,
|
||||
0x08, 0x08, 0x13, 0x13, 0x13, 0x13, 0x13, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
0x18, 0x18, 0x00, 0x00, 0x22, 0x22, 0x09, 0x09,
|
||||
0x09, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x00, 0x00, 0x16, 0x16, 0x00,
|
||||
0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Entry 80 - BF
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
// Entry C0 - FF
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
// Entry 100 - 13F
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04,
|
||||
0x08, 0x08, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x0c, 0x0c,
|
||||
0x08, 0x08, 0x08, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
// Entry 140 - 17F
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x08, 0x08, 0x04, 0x04, 0x1f, 0x1f,
|
||||
0x14, 0x14, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08,
|
||||
0x01, 0x01, 0x06, 0x00, 0x00, 0x20, 0x20, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x17, 0x17, 0x01,
|
||||
0x01, 0x13, 0x13, 0x13, 0x16, 0x16, 0x08, 0x08,
|
||||
0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Entry 180 - 1BF
|
||||
0x00, 0x04, 0x0a, 0x0a, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x10, 0x17, 0x00, 0x00, 0x00, 0x08, 0x08,
|
||||
0x04, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x02,
|
||||
0x02, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
|
||||
0x08, 0x08, 0x00, 0x00, 0x0f, 0x0f, 0x08, 0x10,
|
||||
// Entry 1C0 - 1FF
|
||||
0x10, 0x08, 0x08, 0x0e, 0x0e, 0x08, 0x08, 0x08,
|
||||
0x08, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x1b, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0d, 0x08,
|
||||
0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06,
|
||||
0x00, 0x00, 0x08, 0x08, 0x0b, 0x0b, 0x08, 0x08,
|
||||
0x08, 0x08, 0x12, 0x01, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Entry 200 - 23F
|
||||
0x00, 0x08, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00,
|
||||
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08,
|
||||
0x06, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x06, 0x06,
|
||||
0x06, 0x06, 0x06, 0x08, 0x19, 0x19, 0x0d, 0x0d,
|
||||
0x08, 0x08, 0x03, 0x04, 0x03, 0x04, 0x04, 0x04,
|
||||
// Entry 240 - 27F
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00,
|
||||
0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x12,
|
||||
0x12, 0x12, 0x08, 0x08, 0x1d, 0x1d, 0x1d, 0x1d,
|
||||
0x1d, 0x1d, 0x1d, 0x00, 0x00, 0x08, 0x08, 0x00,
|
||||
0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08,
|
||||
0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00,
|
||||
0x00, 0x00, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x05, 0x05, 0x18, 0x18, 0x15, 0x15, 0x10, 0x10,
|
||||
// Entry 280 - 2BF
|
||||
0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x13,
|
||||
0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
|
||||
0x13, 0x13, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06,
|
||||
0x08, 0x08, 0x08, 0x0c, 0x08, 0x00, 0x00, 0x08,
|
||||
// Entry 2C0 - 2FF
|
||||
0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x07,
|
||||
0x07, 0x08, 0x08, 0x1d, 0x1d, 0x04, 0x04, 0x04,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08,
|
||||
0x08, 0x08, 0x08, 0x06, 0x08, 0x08, 0x00, 0x00,
|
||||
0x08, 0x08, 0x08, 0x00, 0x00, 0x04, 0x04, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Entry 300 - 33F
|
||||
0x00, 0x00, 0x00, 0x01, 0x01, 0x04, 0x04,
|
||||
} // Size: 799 bytes
|
||||
|
||||
var cardinalInclusionMasks = []uint64{ // 100 elements
|
||||
// Entry 0 - 1F
|
||||
0x0000000200500419, 0x0000000000512153, 0x000000000a327105, 0x0000000ca23c7101,
|
||||
0x00000004a23c7201, 0x0000000482943001, 0x0000001482943201, 0x0000000502943001,
|
||||
0x0000000502943001, 0x0000000522943201, 0x0000000540543401, 0x00000000454128e1,
|
||||
0x000000005b02e821, 0x000000006304e821, 0x000000006304ea21, 0x0000000042842821,
|
||||
0x0000000042842a21, 0x0000000042842821, 0x0000000042842821, 0x0000000062842a21,
|
||||
0x0000000200400421, 0x0000000000400061, 0x000000000a004021, 0x0000000022004021,
|
||||
0x0000000022004221, 0x0000000002800021, 0x0000000002800221, 0x0000000002800021,
|
||||
0x0000000002800021, 0x0000000022800221, 0x0000000000400421, 0x0000000000400061,
|
||||
// Entry 20 - 3F
|
||||
0x000000000a004021, 0x0000000022004021, 0x0000000022004221, 0x0000000002800021,
|
||||
0x0000000002800221, 0x0000000002800021, 0x0000000002800021, 0x0000000022800221,
|
||||
0x0000000200400421, 0x0000000000400061, 0x000000000a004021, 0x0000000022004021,
|
||||
0x0000000022004221, 0x0000000002800021, 0x0000000002800221, 0x0000000002800021,
|
||||
0x0000000002800021, 0x0000000022800221, 0x0000000000400421, 0x0000000000400061,
|
||||
0x000000000a004021, 0x0000000022004021, 0x0000000022004221, 0x0000000002800021,
|
||||
0x0000000002800221, 0x0000000002800021, 0x0000000002800021, 0x0000000022800221,
|
||||
0x0000000200400421, 0x0000000000400061, 0x000000000a004021, 0x0000000022004021,
|
||||
// Entry 40 - 5F
|
||||
0x0000000022004221, 0x0000000002800021, 0x0000000002800221, 0x0000000002800021,
|
||||
0x0000000002800021, 0x0000000022800221, 0x0000000040400421, 0x0000000044400061,
|
||||
0x000000005a004021, 0x0000000062004021, 0x0000000062004221, 0x0000000042800021,
|
||||
0x0000000042800221, 0x0000000042800021, 0x0000000042800021, 0x0000000062800221,
|
||||
0x0000000200400421, 0x0000000000400061, 0x000000000a004021, 0x0000000022004021,
|
||||
0x0000000022004221, 0x0000000002800021, 0x0000000002800221, 0x0000000002800021,
|
||||
0x0000000002800021, 0x0000000022800221, 0x0000000040400421, 0x0000000044400061,
|
||||
0x000000005a004021, 0x0000000062004021, 0x0000000062004221, 0x0000000042800021,
|
||||
// Entry 60 - 7F
|
||||
0x0000000042800221, 0x0000000042800021, 0x0000000042800021, 0x0000000062800221,
|
||||
} // Size: 824 bytes
|
||||
|
||||
// Slots used for cardinal: A6 of 0xFF rules; 24 of 0xFF indexes; 37 of 64 sets
|
||||
|
||||
// Total table size 3860 bytes (3KiB); checksum: AAFBF21
|
417
vendor/golang.org/x/text/internal/catmsg/catmsg.go
generated
vendored
417
vendor/golang.org/x/text/internal/catmsg/catmsg.go
generated
vendored
@ -1,417 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package catmsg contains support types for package x/text/message/catalog.
|
||||
//
|
||||
// This package contains the low-level implementations of Message used by the
|
||||
// catalog package and provides primitives for other packages to implement their
|
||||
// own. For instance, the plural package provides functionality for selecting
|
||||
// translation strings based on the plural category of substitution arguments.
|
||||
//
|
||||
// # Encoding and Decoding
|
||||
//
|
||||
// Catalogs store Messages encoded as a single string. Compiling a message into
|
||||
// a string both results in compacter representation and speeds up evaluation.
|
||||
//
|
||||
// A Message must implement a Compile method to convert its arbitrary
|
||||
// representation to a string. The Compile method takes an Encoder which
|
||||
// facilitates serializing the message. Encoders also provide more context of
|
||||
// the messages's creation (such as for which language the message is intended),
|
||||
// which may not be known at the time of the creation of the message.
|
||||
//
|
||||
// Each message type must also have an accompanying decoder registered to decode
|
||||
// the message. This decoder takes a Decoder argument which provides the
|
||||
// counterparts for the decoding.
|
||||
//
|
||||
// # Renderers
|
||||
//
|
||||
// A Decoder must be initialized with a Renderer implementation. These
|
||||
// implementations must be provided by packages that use Catalogs, typically
|
||||
// formatting packages such as x/text/message. A typical user will not need to
|
||||
// worry about this type; it is only relevant to packages that do string
|
||||
// formatting and want to use the catalog package to handle localized strings.
|
||||
//
|
||||
// A package that uses catalogs for selecting strings receives selection results
|
||||
// as sequence of substrings passed to the Renderer. The following snippet shows
|
||||
// how to express the above example using the message package.
|
||||
//
|
||||
// message.Set(language.English, "You are %d minute(s) late.",
|
||||
// catalog.Var("minutes", plural.Select(1, "one", "minute")),
|
||||
// catalog.String("You are %[1]d ${minutes} late."))
|
||||
//
|
||||
// p := message.NewPrinter(language.English)
|
||||
// p.Printf("You are %d minute(s) late.", 5) // always 5 minutes late.
|
||||
//
|
||||
// To evaluate the Printf, package message wraps the arguments in a Renderer
|
||||
// that is passed to the catalog for message decoding. The call sequence that
|
||||
// results from evaluating the above message, assuming the person is rather
|
||||
// tardy, is:
|
||||
//
|
||||
// Render("You are %[1]d ")
|
||||
// Arg(1)
|
||||
// Render("minutes")
|
||||
// Render(" late.")
|
||||
//
|
||||
// The calls to Arg is caused by the plural.Select execution, which evaluates
|
||||
// the argument to determine whether the singular or plural message form should
|
||||
// be selected. The calls to Render reports the partial results to the message
|
||||
// package for further evaluation.
|
||||
package catmsg
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// A Handle refers to a registered message type.
|
||||
type Handle int
|
||||
|
||||
// A Handler decodes and evaluates data compiled by a Message and sends the
|
||||
// result to the Decoder. The output may depend on the value of the substitution
|
||||
// arguments, accessible by the Decoder's Arg method. The Handler returns false
|
||||
// if there is no translation for the given substitution arguments.
|
||||
type Handler func(d *Decoder) bool
|
||||
|
||||
// Register records the existence of a message type and returns a Handle that
|
||||
// can be used in the Encoder's EncodeMessageType method to create such
|
||||
// messages. The prefix of the name should be the package path followed by
|
||||
// an optional disambiguating string.
|
||||
// Register will panic if a handle for the same name was already registered.
|
||||
func Register(name string, handler Handler) Handle {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
if _, ok := names[name]; ok {
|
||||
panic(fmt.Errorf("catmsg: handler for %q already exists", name))
|
||||
}
|
||||
h := Handle(len(handlers))
|
||||
names[name] = h
|
||||
handlers = append(handlers, handler)
|
||||
return h
|
||||
}
|
||||
|
||||
// These handlers require fixed positions in the handlers slice.
|
||||
const (
|
||||
msgVars Handle = iota
|
||||
msgFirst
|
||||
msgRaw
|
||||
msgString
|
||||
msgAffix
|
||||
// Leave some arbitrary room for future expansion: 20 should suffice.
|
||||
numInternal = 20
|
||||
)
|
||||
|
||||
const prefix = "golang.org/x/text/internal/catmsg."
|
||||
|
||||
var (
|
||||
// TODO: find a more stable way to link handles to message types.
|
||||
mutex sync.Mutex
|
||||
names = map[string]Handle{
|
||||
prefix + "Vars": msgVars,
|
||||
prefix + "First": msgFirst,
|
||||
prefix + "Raw": msgRaw,
|
||||
prefix + "String": msgString,
|
||||
prefix + "Affix": msgAffix,
|
||||
}
|
||||
handlers = make([]Handler, numInternal)
|
||||
)
|
||||
|
||||
func init() {
|
||||
// This handler is a message type wrapper that initializes a decoder
|
||||
// with a variable block. This message type, if present, is always at the
|
||||
// start of an encoded message.
|
||||
handlers[msgVars] = func(d *Decoder) bool {
|
||||
blockSize := int(d.DecodeUint())
|
||||
d.vars = d.data[:blockSize]
|
||||
d.data = d.data[blockSize:]
|
||||
return d.executeMessage()
|
||||
}
|
||||
|
||||
// First takes the first message in a sequence that results in a match for
|
||||
// the given substitution arguments.
|
||||
handlers[msgFirst] = func(d *Decoder) bool {
|
||||
for !d.Done() {
|
||||
if d.ExecuteMessage() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
handlers[msgRaw] = func(d *Decoder) bool {
|
||||
d.Render(d.data)
|
||||
return true
|
||||
}
|
||||
|
||||
// A String message alternates between a string constant and a variable
|
||||
// substitution.
|
||||
handlers[msgString] = func(d *Decoder) bool {
|
||||
for !d.Done() {
|
||||
if str := d.DecodeString(); str != "" {
|
||||
d.Render(str)
|
||||
}
|
||||
if d.Done() {
|
||||
break
|
||||
}
|
||||
d.ExecuteSubstitution()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
handlers[msgAffix] = func(d *Decoder) bool {
|
||||
// TODO: use an alternative method for common cases.
|
||||
prefix := d.DecodeString()
|
||||
suffix := d.DecodeString()
|
||||
if prefix != "" {
|
||||
d.Render(prefix)
|
||||
}
|
||||
ret := d.ExecuteMessage()
|
||||
if suffix != "" {
|
||||
d.Render(suffix)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrIncomplete indicates a compiled message does not define translations
|
||||
// for all possible argument values. If this message is returned, evaluating
|
||||
// a message may result in the ErrNoMatch error.
|
||||
ErrIncomplete = errors.New("catmsg: incomplete message; may not give result for all inputs")
|
||||
|
||||
// ErrNoMatch indicates no translation message matched the given input
|
||||
// parameters when evaluating a message.
|
||||
ErrNoMatch = errors.New("catmsg: no translation for inputs")
|
||||
)
|
||||
|
||||
// A Message holds a collection of translations for the same phrase that may
|
||||
// vary based on the values of substitution arguments.
|
||||
type Message interface {
|
||||
// Compile encodes the format string(s) of the message as a string for later
|
||||
// evaluation.
|
||||
//
|
||||
// The first call Compile makes on the encoder must be EncodeMessageType.
|
||||
// The handle passed to this call may either be a handle returned by
|
||||
// Register to encode a single custom message, or HandleFirst followed by
|
||||
// a sequence of calls to EncodeMessage.
|
||||
//
|
||||
// Compile must return ErrIncomplete if it is possible for evaluation to
|
||||
// not match any translation for a given set of formatting parameters.
|
||||
// For example, selecting a translation based on plural form may not yield
|
||||
// a match if the form "Other" is not one of the selectors.
|
||||
//
|
||||
// Compile may return any other application-specific error. For backwards
|
||||
// compatibility with package like fmt, which often do not do sanity
|
||||
// checking of format strings ahead of time, Compile should still make an
|
||||
// effort to have some sensible fallback in case of an error.
|
||||
Compile(e *Encoder) error
|
||||
}
|
||||
|
||||
// Compile converts a Message to a data string that can be stored in a Catalog.
|
||||
// The resulting string can subsequently be decoded by passing to the Execute
|
||||
// method of a Decoder.
|
||||
func Compile(tag language.Tag, macros Dictionary, m Message) (data string, err error) {
|
||||
// TODO: pass macros so they can be used for validation.
|
||||
v := &Encoder{inBody: true} // encoder for variables
|
||||
v.root = v
|
||||
e := &Encoder{root: v, parent: v, tag: tag} // encoder for messages
|
||||
err = m.Compile(e)
|
||||
// This package serves te message package, which in turn is meant to be a
|
||||
// drop-in replacement for fmt. With the fmt package, format strings are
|
||||
// evaluated lazily and errors are handled by substituting strings in the
|
||||
// result, rather then returning an error. Dealing with multiple languages
|
||||
// makes it more important to check errors ahead of time. We chose to be
|
||||
// consistent and compatible and allow graceful degradation in case of
|
||||
// errors.
|
||||
buf := e.buf[stripPrefix(e.buf):]
|
||||
if len(v.buf) > 0 {
|
||||
// Prepend variable block.
|
||||
b := make([]byte, 1+maxVarintBytes+len(v.buf)+len(buf))
|
||||
b[0] = byte(msgVars)
|
||||
b = b[:1+encodeUint(b[1:], uint64(len(v.buf)))]
|
||||
b = append(b, v.buf...)
|
||||
b = append(b, buf...)
|
||||
buf = b
|
||||
}
|
||||
if err == nil {
|
||||
err = v.err
|
||||
}
|
||||
return string(buf), err
|
||||
}
|
||||
|
||||
// FirstOf is a message type that prints the first message in the sequence that
|
||||
// resolves to a match for the given substitution arguments.
|
||||
type FirstOf []Message
|
||||
|
||||
// Compile implements Message.
|
||||
func (s FirstOf) Compile(e *Encoder) error {
|
||||
e.EncodeMessageType(msgFirst)
|
||||
err := ErrIncomplete
|
||||
for i, m := range s {
|
||||
if err == nil {
|
||||
return fmt.Errorf("catalog: message argument %d is complete and blocks subsequent messages", i-1)
|
||||
}
|
||||
err = e.EncodeMessage(m)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Var defines a message that can be substituted for a placeholder of the same
|
||||
// name. If an expression does not result in a string after evaluation, Name is
|
||||
// used as the substitution. For example:
|
||||
//
|
||||
// Var{
|
||||
// Name: "minutes",
|
||||
// Message: plural.Select(1, "one", "minute"),
|
||||
// }
|
||||
//
|
||||
// will resolve to minute for singular and minutes for plural forms.
|
||||
type Var struct {
|
||||
Name string
|
||||
Message Message
|
||||
}
|
||||
|
||||
var errIsVar = errors.New("catmsg: variable used as message")
|
||||
|
||||
// Compile implements Message.
|
||||
//
|
||||
// Note that this method merely registers a variable; it does not create an
|
||||
// encoded message.
|
||||
func (v *Var) Compile(e *Encoder) error {
|
||||
if err := e.addVar(v.Name, v.Message); err != nil {
|
||||
return err
|
||||
}
|
||||
// Using a Var by itself is an error. If it is in a sequence followed by
|
||||
// other messages referring to it, this error will be ignored.
|
||||
return errIsVar
|
||||
}
|
||||
|
||||
// Raw is a message consisting of a single format string that is passed as is
|
||||
// to the Renderer.
|
||||
//
|
||||
// Note that a Renderer may still do its own variable substitution.
|
||||
type Raw string
|
||||
|
||||
// Compile implements Message.
|
||||
func (r Raw) Compile(e *Encoder) (err error) {
|
||||
e.EncodeMessageType(msgRaw)
|
||||
// Special case: raw strings don't have a size encoding and so don't use
|
||||
// EncodeString.
|
||||
e.buf = append(e.buf, r...)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String is a message consisting of a single format string which contains
|
||||
// placeholders that may be substituted with variables.
|
||||
//
|
||||
// Variable substitutions are marked with placeholders and a variable name of
|
||||
// the form ${name}. Any other substitutions such as Go templates or
|
||||
// printf-style substitutions are left to be done by the Renderer.
|
||||
//
|
||||
// When evaluation a string interpolation, a Renderer will receive separate
|
||||
// calls for each placeholder and interstitial string. For example, for the
|
||||
// message: "%[1]v ${invites} %[2]v to ${their} party." The sequence of calls
|
||||
// is:
|
||||
//
|
||||
// d.Render("%[1]v ")
|
||||
// d.Arg(1)
|
||||
// d.Render(resultOfInvites)
|
||||
// d.Render(" %[2]v to ")
|
||||
// d.Arg(2)
|
||||
// d.Render(resultOfTheir)
|
||||
// d.Render(" party.")
|
||||
//
|
||||
// where the messages for "invites" and "their" both use a plural.Select
|
||||
// referring to the first argument.
|
||||
//
|
||||
// Strings may also invoke macros. Macros are essentially variables that can be
|
||||
// reused. Macros may, for instance, be used to make selections between
|
||||
// different conjugations of a verb. See the catalog package description for an
|
||||
// overview of macros.
|
||||
type String string
|
||||
|
||||
// Compile implements Message. It parses the placeholder formats and returns
|
||||
// any error.
|
||||
func (s String) Compile(e *Encoder) (err error) {
|
||||
msg := string(s)
|
||||
const subStart = "${"
|
||||
hasHeader := false
|
||||
p := 0
|
||||
b := []byte{}
|
||||
for {
|
||||
i := strings.Index(msg[p:], subStart)
|
||||
if i == -1 {
|
||||
break
|
||||
}
|
||||
b = append(b, msg[p:p+i]...)
|
||||
p += i + len(subStart)
|
||||
if i = strings.IndexByte(msg[p:], '}'); i == -1 {
|
||||
b = append(b, "$!(MISSINGBRACE)"...)
|
||||
err = fmt.Errorf("catmsg: missing '}'")
|
||||
p = len(msg)
|
||||
break
|
||||
}
|
||||
name := strings.TrimSpace(msg[p : p+i])
|
||||
if q := strings.IndexByte(name, '('); q == -1 {
|
||||
if !hasHeader {
|
||||
hasHeader = true
|
||||
e.EncodeMessageType(msgString)
|
||||
}
|
||||
e.EncodeString(string(b))
|
||||
e.EncodeSubstitution(name)
|
||||
b = b[:0]
|
||||
} else if j := strings.IndexByte(name[q:], ')'); j == -1 {
|
||||
// TODO: what should the error be?
|
||||
b = append(b, "$!(MISSINGPAREN)"...)
|
||||
err = fmt.Errorf("catmsg: missing ')'")
|
||||
} else if x, sErr := strconv.ParseUint(strings.TrimSpace(name[q+1:q+j]), 10, 32); sErr != nil {
|
||||
// TODO: handle more than one argument
|
||||
b = append(b, "$!(BADNUM)"...)
|
||||
err = fmt.Errorf("catmsg: invalid number %q", strings.TrimSpace(name[q+1:q+j]))
|
||||
} else {
|
||||
if !hasHeader {
|
||||
hasHeader = true
|
||||
e.EncodeMessageType(msgString)
|
||||
}
|
||||
e.EncodeString(string(b))
|
||||
e.EncodeSubstitution(name[:q], int(x))
|
||||
b = b[:0]
|
||||
}
|
||||
p += i + 1
|
||||
}
|
||||
b = append(b, msg[p:]...)
|
||||
if !hasHeader {
|
||||
// Simplify string to a raw string.
|
||||
Raw(string(b)).Compile(e)
|
||||
} else if len(b) > 0 {
|
||||
e.EncodeString(string(b))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Affix is a message that adds a prefix and suffix to another message.
|
||||
// This is mostly used add back whitespace to a translation that was stripped
|
||||
// before sending it out.
|
||||
type Affix struct {
|
||||
Message Message
|
||||
Prefix string
|
||||
Suffix string
|
||||
}
|
||||
|
||||
// Compile implements Message.
|
||||
func (a Affix) Compile(e *Encoder) (err error) {
|
||||
// TODO: consider adding a special message type that just adds a single
|
||||
// return. This is probably common enough to handle the majority of cases.
|
||||
// Get some stats first, though.
|
||||
e.EncodeMessageType(msgAffix)
|
||||
e.EncodeString(a.Prefix)
|
||||
e.EncodeString(a.Suffix)
|
||||
e.EncodeMessage(a.Message)
|
||||
return nil
|
||||
}
|
407
vendor/golang.org/x/text/internal/catmsg/codec.go
generated
vendored
407
vendor/golang.org/x/text/internal/catmsg/codec.go
generated
vendored
@ -1,407 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package catmsg
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// A Renderer renders a Message.
|
||||
type Renderer interface {
|
||||
// Render renders the given string. The given string may be interpreted as a
|
||||
// format string, such as the one used by the fmt package or a template.
|
||||
Render(s string)
|
||||
|
||||
// Arg returns the i-th argument passed to format a message. This method
|
||||
// should return nil if there is no such argument. Messages need access to
|
||||
// arguments to allow selecting a message based on linguistic features of
|
||||
// those arguments.
|
||||
Arg(i int) interface{}
|
||||
}
|
||||
|
||||
// A Dictionary specifies a source of messages, including variables or macros.
|
||||
type Dictionary interface {
|
||||
// Lookup returns the message for the given key. It returns false for ok if
|
||||
// such a message could not be found.
|
||||
Lookup(key string) (data string, ok bool)
|
||||
|
||||
// TODO: consider returning an interface, instead of a string. This will
|
||||
// allow implementations to do their own message type decoding.
|
||||
}
|
||||
|
||||
// An Encoder serializes a Message to a string.
|
||||
type Encoder struct {
|
||||
// The root encoder is used for storing encoded variables.
|
||||
root *Encoder
|
||||
// The parent encoder provides the surrounding scopes for resolving variable
|
||||
// names.
|
||||
parent *Encoder
|
||||
|
||||
tag language.Tag
|
||||
|
||||
// buf holds the encoded message so far. After a message completes encoding,
|
||||
// the contents of buf, prefixed by the encoded length, are flushed to the
|
||||
// parent buffer.
|
||||
buf []byte
|
||||
|
||||
// vars is the lookup table of variables in the current scope.
|
||||
vars []keyVal
|
||||
|
||||
err error
|
||||
inBody bool // if false next call must be EncodeMessageType
|
||||
}
|
||||
|
||||
type keyVal struct {
|
||||
key string
|
||||
offset int
|
||||
}
|
||||
|
||||
// Language reports the language for which the encoded message will be stored
|
||||
// in the Catalog.
|
||||
func (e *Encoder) Language() language.Tag { return e.tag }
|
||||
|
||||
func (e *Encoder) setError(err error) {
|
||||
if e.root.err == nil {
|
||||
e.root.err = err
|
||||
}
|
||||
}
|
||||
|
||||
// EncodeUint encodes x.
|
||||
func (e *Encoder) EncodeUint(x uint64) {
|
||||
e.checkInBody()
|
||||
var buf [maxVarintBytes]byte
|
||||
n := encodeUint(buf[:], x)
|
||||
e.buf = append(e.buf, buf[:n]...)
|
||||
}
|
||||
|
||||
// EncodeString encodes s.
|
||||
func (e *Encoder) EncodeString(s string) {
|
||||
e.checkInBody()
|
||||
e.EncodeUint(uint64(len(s)))
|
||||
e.buf = append(e.buf, s...)
|
||||
}
|
||||
|
||||
// EncodeMessageType marks the current message to be of type h.
|
||||
//
|
||||
// It must be the first call of a Message's Compile method.
|
||||
func (e *Encoder) EncodeMessageType(h Handle) {
|
||||
if e.inBody {
|
||||
panic("catmsg: EncodeMessageType not the first method called")
|
||||
}
|
||||
e.inBody = true
|
||||
e.EncodeUint(uint64(h))
|
||||
}
|
||||
|
||||
// EncodeMessage serializes the given message inline at the current position.
|
||||
func (e *Encoder) EncodeMessage(m Message) error {
|
||||
e = &Encoder{root: e.root, parent: e, tag: e.tag}
|
||||
err := m.Compile(e)
|
||||
if _, ok := m.(*Var); !ok {
|
||||
e.flushTo(e.parent)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *Encoder) checkInBody() {
|
||||
if !e.inBody {
|
||||
panic("catmsg: expected prior call to EncodeMessageType")
|
||||
}
|
||||
}
|
||||
|
||||
// stripPrefix indicates the number of prefix bytes that must be stripped to
|
||||
// turn a single-element sequence into a message that is just this single member
|
||||
// without its size prefix. If the message can be stripped, b[1:n] contains the
|
||||
// size prefix.
|
||||
func stripPrefix(b []byte) (n int) {
|
||||
if len(b) > 0 && Handle(b[0]) == msgFirst {
|
||||
x, n, _ := decodeUint(b[1:])
|
||||
if 1+n+int(x) == len(b) {
|
||||
return 1 + n
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Encoder) flushTo(dst *Encoder) {
|
||||
data := e.buf
|
||||
p := stripPrefix(data)
|
||||
if p > 0 {
|
||||
data = data[1:]
|
||||
} else {
|
||||
// Prefix the size.
|
||||
dst.EncodeUint(uint64(len(data)))
|
||||
}
|
||||
dst.buf = append(dst.buf, data...)
|
||||
}
|
||||
|
||||
func (e *Encoder) addVar(key string, m Message) error {
|
||||
for _, v := range e.parent.vars {
|
||||
if v.key == key {
|
||||
err := fmt.Errorf("catmsg: duplicate variable %q", key)
|
||||
e.setError(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
scope := e.parent
|
||||
// If a variable message is Incomplete, and does not evaluate to a message
|
||||
// during execution, we fall back to the variable name. We encode this by
|
||||
// appending the variable name if the message reports it's incomplete.
|
||||
|
||||
err := m.Compile(e)
|
||||
if err != ErrIncomplete {
|
||||
e.setError(err)
|
||||
}
|
||||
switch {
|
||||
case len(e.buf) == 1 && Handle(e.buf[0]) == msgFirst: // empty sequence
|
||||
e.buf = e.buf[:0]
|
||||
e.inBody = false
|
||||
fallthrough
|
||||
case len(e.buf) == 0:
|
||||
// Empty message.
|
||||
if err := String(key).Compile(e); err != nil {
|
||||
e.setError(err)
|
||||
}
|
||||
case err == ErrIncomplete:
|
||||
if Handle(e.buf[0]) != msgFirst {
|
||||
seq := &Encoder{root: e.root, parent: e}
|
||||
seq.EncodeMessageType(msgFirst)
|
||||
e.flushTo(seq)
|
||||
e = seq
|
||||
}
|
||||
// e contains a sequence; append the fallback string.
|
||||
e.EncodeMessage(String(key))
|
||||
}
|
||||
|
||||
// Flush result to variable heap.
|
||||
offset := len(e.root.buf)
|
||||
e.flushTo(e.root)
|
||||
e.buf = e.buf[:0]
|
||||
|
||||
// Record variable offset in current scope.
|
||||
scope.vars = append(scope.vars, keyVal{key: key, offset: offset})
|
||||
return err
|
||||
}
|
||||
|
||||
const (
|
||||
substituteVar = iota
|
||||
substituteMacro
|
||||
substituteError
|
||||
)
|
||||
|
||||
// EncodeSubstitution inserts a resolved reference to a variable or macro.
|
||||
//
|
||||
// This call must be matched with a call to ExecuteSubstitution at decoding
|
||||
// time.
|
||||
func (e *Encoder) EncodeSubstitution(name string, arguments ...int) {
|
||||
if arity := len(arguments); arity > 0 {
|
||||
// TODO: also resolve macros.
|
||||
e.EncodeUint(substituteMacro)
|
||||
e.EncodeString(name)
|
||||
for _, a := range arguments {
|
||||
e.EncodeUint(uint64(a))
|
||||
}
|
||||
return
|
||||
}
|
||||
for scope := e; scope != nil; scope = scope.parent {
|
||||
for _, v := range scope.vars {
|
||||
if v.key != name {
|
||||
continue
|
||||
}
|
||||
e.EncodeUint(substituteVar) // TODO: support arity > 0
|
||||
e.EncodeUint(uint64(v.offset))
|
||||
return
|
||||
}
|
||||
}
|
||||
// TODO: refer to dictionary-wide scoped variables.
|
||||
e.EncodeUint(substituteError)
|
||||
e.EncodeString(name)
|
||||
e.setError(fmt.Errorf("catmsg: unknown var %q", name))
|
||||
}
|
||||
|
||||
// A Decoder deserializes and evaluates messages that are encoded by an encoder.
|
||||
type Decoder struct {
|
||||
tag language.Tag
|
||||
dst Renderer
|
||||
macros Dictionary
|
||||
|
||||
err error
|
||||
vars string
|
||||
data string
|
||||
|
||||
macroArg int // TODO: allow more than one argument
|
||||
}
|
||||
|
||||
// NewDecoder returns a new Decoder.
|
||||
//
|
||||
// Decoders are designed to be reused for multiple invocations of Execute.
|
||||
// Only one goroutine may call Execute concurrently.
|
||||
func NewDecoder(tag language.Tag, r Renderer, macros Dictionary) *Decoder {
|
||||
return &Decoder{
|
||||
tag: tag,
|
||||
dst: r,
|
||||
macros: macros,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Decoder) setError(err error) {
|
||||
if d.err == nil {
|
||||
d.err = err
|
||||
}
|
||||
}
|
||||
|
||||
// Language returns the language in which the message is being rendered.
|
||||
//
|
||||
// The destination language may be a child language of the language used for
|
||||
// encoding. For instance, a decoding language of "pt-PT" is consistent with an
|
||||
// encoding language of "pt".
|
||||
func (d *Decoder) Language() language.Tag { return d.tag }
|
||||
|
||||
// Done reports whether there are more bytes to process in this message.
|
||||
func (d *Decoder) Done() bool { return len(d.data) == 0 }
|
||||
|
||||
// Render implements Renderer.
|
||||
func (d *Decoder) Render(s string) { d.dst.Render(s) }
|
||||
|
||||
// Arg implements Renderer.
|
||||
//
|
||||
// During evaluation of macros, the argument positions may be mapped to
|
||||
// arguments that differ from the original call.
|
||||
func (d *Decoder) Arg(i int) interface{} {
|
||||
if d.macroArg != 0 {
|
||||
if i != 1 {
|
||||
panic("catmsg: only macros with single argument supported")
|
||||
}
|
||||
i = d.macroArg
|
||||
}
|
||||
return d.dst.Arg(i)
|
||||
}
|
||||
|
||||
// DecodeUint decodes a number that was encoded with EncodeUint and advances the
|
||||
// position.
|
||||
func (d *Decoder) DecodeUint() uint64 {
|
||||
x, n, err := decodeUintString(d.data)
|
||||
d.data = d.data[n:]
|
||||
if err != nil {
|
||||
d.setError(err)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
// DecodeString decodes a string that was encoded with EncodeString and advances
|
||||
// the position.
|
||||
func (d *Decoder) DecodeString() string {
|
||||
size := d.DecodeUint()
|
||||
s := d.data[:size]
|
||||
d.data = d.data[size:]
|
||||
return s
|
||||
}
|
||||
|
||||
// SkipMessage skips the message at the current location and advances the
|
||||
// position.
|
||||
func (d *Decoder) SkipMessage() {
|
||||
n := int(d.DecodeUint())
|
||||
d.data = d.data[n:]
|
||||
}
|
||||
|
||||
// Execute decodes and evaluates msg.
|
||||
//
|
||||
// Only one goroutine may call execute.
|
||||
func (d *Decoder) Execute(msg string) error {
|
||||
d.err = nil
|
||||
if !d.execute(msg) {
|
||||
return ErrNoMatch
|
||||
}
|
||||
return d.err
|
||||
}
|
||||
|
||||
func (d *Decoder) execute(msg string) bool {
|
||||
saved := d.data
|
||||
d.data = msg
|
||||
ok := d.executeMessage()
|
||||
d.data = saved
|
||||
return ok
|
||||
}
|
||||
|
||||
// executeMessageFromData is like execute, but also decodes a leading message
|
||||
// size and clips the given string accordingly.
|
||||
//
|
||||
// It reports the number of bytes consumed and whether a message was selected.
|
||||
func (d *Decoder) executeMessageFromData(s string) (n int, ok bool) {
|
||||
saved := d.data
|
||||
d.data = s
|
||||
size := int(d.DecodeUint())
|
||||
n = len(s) - len(d.data)
|
||||
// Sanitize the setting. This allows skipping a size argument for
|
||||
// RawString and method Done.
|
||||
d.data = d.data[:size]
|
||||
ok = d.executeMessage()
|
||||
n += size - len(d.data)
|
||||
d.data = saved
|
||||
return n, ok
|
||||
}
|
||||
|
||||
var errUnknownHandler = errors.New("catmsg: string contains unsupported handler")
|
||||
|
||||
// executeMessage reads the handle id, initializes the decoder and executes the
|
||||
// message. It is assumed that all of d.data[d.p:] is the single message.
|
||||
func (d *Decoder) executeMessage() bool {
|
||||
if d.Done() {
|
||||
// We interpret no data as a valid empty message.
|
||||
return true
|
||||
}
|
||||
handle := d.DecodeUint()
|
||||
|
||||
var fn Handler
|
||||
mutex.Lock()
|
||||
if int(handle) < len(handlers) {
|
||||
fn = handlers[handle]
|
||||
}
|
||||
mutex.Unlock()
|
||||
if fn == nil {
|
||||
d.setError(errUnknownHandler)
|
||||
d.execute(fmt.Sprintf("\x02$!(UNKNOWNMSGHANDLER=%#x)", handle))
|
||||
return true
|
||||
}
|
||||
return fn(d)
|
||||
}
|
||||
|
||||
// ExecuteMessage decodes and executes the message at the current position.
|
||||
func (d *Decoder) ExecuteMessage() bool {
|
||||
n, ok := d.executeMessageFromData(d.data)
|
||||
d.data = d.data[n:]
|
||||
return ok
|
||||
}
|
||||
|
||||
// ExecuteSubstitution executes the message corresponding to the substitution
|
||||
// as encoded by EncodeSubstitution.
|
||||
func (d *Decoder) ExecuteSubstitution() {
|
||||
switch x := d.DecodeUint(); x {
|
||||
case substituteVar:
|
||||
offset := d.DecodeUint()
|
||||
d.executeMessageFromData(d.vars[offset:])
|
||||
case substituteMacro:
|
||||
name := d.DecodeString()
|
||||
data, ok := d.macros.Lookup(name)
|
||||
old := d.macroArg
|
||||
// TODO: support macros of arity other than 1.
|
||||
d.macroArg = int(d.DecodeUint())
|
||||
switch {
|
||||
case !ok:
|
||||
// TODO: detect this at creation time.
|
||||
d.setError(fmt.Errorf("catmsg: undefined macro %q", name))
|
||||
fallthrough
|
||||
case !d.execute(data):
|
||||
d.dst.Render(name) // fall back to macro name.
|
||||
}
|
||||
d.macroArg = old
|
||||
case substituteError:
|
||||
d.dst.Render(d.DecodeString())
|
||||
default:
|
||||
panic("catmsg: unreachable")
|
||||
}
|
||||
}
|
62
vendor/golang.org/x/text/internal/catmsg/varint.go
generated
vendored
62
vendor/golang.org/x/text/internal/catmsg/varint.go
generated
vendored
@ -1,62 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package catmsg
|
||||
|
||||
// This file implements varint encoding analogous to the one in encoding/binary.
|
||||
// We need a string version of this function, so we add that here and then add
|
||||
// the rest for consistency.
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
errIllegalVarint = errors.New("catmsg: illegal varint")
|
||||
errVarintTooLarge = errors.New("catmsg: varint too large for uint64")
|
||||
)
|
||||
|
||||
const maxVarintBytes = 10 // maximum length of a varint
|
||||
|
||||
// encodeUint encodes x as a variable-sized integer into buf and returns the
|
||||
// number of bytes written. buf must be at least maxVarintBytes long
|
||||
func encodeUint(buf []byte, x uint64) (n int) {
|
||||
for ; x > 127; n++ {
|
||||
buf[n] = 0x80 | uint8(x&0x7F)
|
||||
x >>= 7
|
||||
}
|
||||
buf[n] = uint8(x)
|
||||
n++
|
||||
return n
|
||||
}
|
||||
|
||||
func decodeUintString(s string) (x uint64, size int, err error) {
|
||||
i := 0
|
||||
for shift := uint(0); shift < 64; shift += 7 {
|
||||
if i >= len(s) {
|
||||
return 0, i, errIllegalVarint
|
||||
}
|
||||
b := uint64(s[i])
|
||||
i++
|
||||
x |= (b & 0x7F) << shift
|
||||
if b&0x80 == 0 {
|
||||
return x, i, nil
|
||||
}
|
||||
}
|
||||
return 0, i, errVarintTooLarge
|
||||
}
|
||||
|
||||
func decodeUint(b []byte) (x uint64, size int, err error) {
|
||||
i := 0
|
||||
for shift := uint(0); shift < 64; shift += 7 {
|
||||
if i >= len(b) {
|
||||
return 0, i, errIllegalVarint
|
||||
}
|
||||
c := uint64(b[i])
|
||||
i++
|
||||
x |= (c & 0x7F) << shift
|
||||
if c&0x80 == 0 {
|
||||
return x, i, nil
|
||||
}
|
||||
}
|
||||
return 0, i, errVarintTooLarge
|
||||
}
|
41
vendor/golang.org/x/text/internal/format/format.go
generated
vendored
41
vendor/golang.org/x/text/internal/format/format.go
generated
vendored
@ -1,41 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package format contains types for defining language-specific formatting of
|
||||
// values.
|
||||
//
|
||||
// This package is internal now, but will eventually be exposed after the API
|
||||
// settles.
|
||||
package format // import "golang.org/x/text/internal/format"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// State represents the printer state passed to custom formatters. It provides
|
||||
// access to the fmt.State interface and the sentence and language-related
|
||||
// context.
|
||||
type State interface {
|
||||
fmt.State
|
||||
|
||||
// Language reports the requested language in which to render a message.
|
||||
Language() language.Tag
|
||||
|
||||
// TODO: consider this and removing rune from the Format method in the
|
||||
// Formatter interface.
|
||||
//
|
||||
// Verb returns the format variant to render, analogous to the types used
|
||||
// in fmt. Use 'v' for the default or only variant.
|
||||
// Verb() rune
|
||||
|
||||
// TODO: more info:
|
||||
// - sentence context such as linguistic features passed by the translator.
|
||||
}
|
||||
|
||||
// Formatter is analogous to fmt.Formatter.
|
||||
type Formatter interface {
|
||||
Format(state State, verb rune)
|
||||
}
|
358
vendor/golang.org/x/text/internal/format/parser.go
generated
vendored
358
vendor/golang.org/x/text/internal/format/parser.go
generated
vendored
@ -1,358 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package format
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// A Parser parses a format string. The result from the parse are set in the
|
||||
// struct fields.
|
||||
type Parser struct {
|
||||
Verb rune
|
||||
|
||||
WidthPresent bool
|
||||
PrecPresent bool
|
||||
Minus bool
|
||||
Plus bool
|
||||
Sharp bool
|
||||
Space bool
|
||||
Zero bool
|
||||
|
||||
// For the formats %+v %#v, we set the plusV/sharpV flags
|
||||
// and clear the plus/sharp flags since %+v and %#v are in effect
|
||||
// different, flagless formats set at the top level.
|
||||
PlusV bool
|
||||
SharpV bool
|
||||
|
||||
HasIndex bool
|
||||
|
||||
Width int
|
||||
Prec int // precision
|
||||
|
||||
// retain arguments across calls.
|
||||
Args []interface{}
|
||||
// retain current argument number across calls
|
||||
ArgNum int
|
||||
|
||||
// reordered records whether the format string used argument reordering.
|
||||
Reordered bool
|
||||
// goodArgNum records whether the most recent reordering directive was valid.
|
||||
goodArgNum bool
|
||||
|
||||
// position info
|
||||
format string
|
||||
startPos int
|
||||
endPos int
|
||||
Status Status
|
||||
}
|
||||
|
||||
// Reset initializes a parser to scan format strings for the given args.
|
||||
func (p *Parser) Reset(args []interface{}) {
|
||||
p.Args = args
|
||||
p.ArgNum = 0
|
||||
p.startPos = 0
|
||||
p.Reordered = false
|
||||
}
|
||||
|
||||
// Text returns the part of the format string that was parsed by the last call
|
||||
// to Scan. It returns the original substitution clause if the current scan
|
||||
// parsed a substitution.
|
||||
func (p *Parser) Text() string { return p.format[p.startPos:p.endPos] }
|
||||
|
||||
// SetFormat sets a new format string to parse. It does not reset the argument
|
||||
// count.
|
||||
func (p *Parser) SetFormat(format string) {
|
||||
p.format = format
|
||||
p.startPos = 0
|
||||
p.endPos = 0
|
||||
}
|
||||
|
||||
// Status indicates the result type of a call to Scan.
|
||||
type Status int
|
||||
|
||||
const (
|
||||
StatusText Status = iota
|
||||
StatusSubstitution
|
||||
StatusBadWidthSubstitution
|
||||
StatusBadPrecSubstitution
|
||||
StatusNoVerb
|
||||
StatusBadArgNum
|
||||
StatusMissingArg
|
||||
)
|
||||
|
||||
// ClearFlags reset the parser to default behavior.
|
||||
func (p *Parser) ClearFlags() {
|
||||
p.WidthPresent = false
|
||||
p.PrecPresent = false
|
||||
p.Minus = false
|
||||
p.Plus = false
|
||||
p.Sharp = false
|
||||
p.Space = false
|
||||
p.Zero = false
|
||||
|
||||
p.PlusV = false
|
||||
p.SharpV = false
|
||||
|
||||
p.HasIndex = false
|
||||
}
|
||||
|
||||
// Scan scans the next part of the format string and sets the status to
|
||||
// indicate whether it scanned a string literal, substitution or error.
|
||||
func (p *Parser) Scan() bool {
|
||||
p.Status = StatusText
|
||||
format := p.format
|
||||
end := len(format)
|
||||
if p.endPos >= end {
|
||||
return false
|
||||
}
|
||||
afterIndex := false // previous item in format was an index like [3].
|
||||
|
||||
p.startPos = p.endPos
|
||||
p.goodArgNum = true
|
||||
i := p.startPos
|
||||
for i < end && format[i] != '%' {
|
||||
i++
|
||||
}
|
||||
if i > p.startPos {
|
||||
p.endPos = i
|
||||
return true
|
||||
}
|
||||
// Process one verb
|
||||
i++
|
||||
|
||||
p.Status = StatusSubstitution
|
||||
|
||||
// Do we have flags?
|
||||
p.ClearFlags()
|
||||
|
||||
simpleFormat:
|
||||
for ; i < end; i++ {
|
||||
c := p.format[i]
|
||||
switch c {
|
||||
case '#':
|
||||
p.Sharp = true
|
||||
case '0':
|
||||
p.Zero = !p.Minus // Only allow zero padding to the left.
|
||||
case '+':
|
||||
p.Plus = true
|
||||
case '-':
|
||||
p.Minus = true
|
||||
p.Zero = false // Do not pad with zeros to the right.
|
||||
case ' ':
|
||||
p.Space = true
|
||||
default:
|
||||
// Fast path for common case of ascii lower case simple verbs
|
||||
// without precision or width or argument indices.
|
||||
if 'a' <= c && c <= 'z' && p.ArgNum < len(p.Args) {
|
||||
if c == 'v' {
|
||||
// Go syntax
|
||||
p.SharpV = p.Sharp
|
||||
p.Sharp = false
|
||||
// Struct-field syntax
|
||||
p.PlusV = p.Plus
|
||||
p.Plus = false
|
||||
}
|
||||
p.Verb = rune(c)
|
||||
p.ArgNum++
|
||||
p.endPos = i + 1
|
||||
return true
|
||||
}
|
||||
// Format is more complex than simple flags and a verb or is malformed.
|
||||
break simpleFormat
|
||||
}
|
||||
}
|
||||
|
||||
// Do we have an explicit argument index?
|
||||
i, afterIndex = p.updateArgNumber(format, i)
|
||||
|
||||
// Do we have width?
|
||||
if i < end && format[i] == '*' {
|
||||
i++
|
||||
p.Width, p.WidthPresent = p.intFromArg()
|
||||
|
||||
if !p.WidthPresent {
|
||||
p.Status = StatusBadWidthSubstitution
|
||||
}
|
||||
|
||||
// We have a negative width, so take its value and ensure
|
||||
// that the minus flag is set
|
||||
if p.Width < 0 {
|
||||
p.Width = -p.Width
|
||||
p.Minus = true
|
||||
p.Zero = false // Do not pad with zeros to the right.
|
||||
}
|
||||
afterIndex = false
|
||||
} else {
|
||||
p.Width, p.WidthPresent, i = parsenum(format, i, end)
|
||||
if afterIndex && p.WidthPresent { // "%[3]2d"
|
||||
p.goodArgNum = false
|
||||
}
|
||||
}
|
||||
|
||||
// Do we have precision?
|
||||
if i+1 < end && format[i] == '.' {
|
||||
i++
|
||||
if afterIndex { // "%[3].2d"
|
||||
p.goodArgNum = false
|
||||
}
|
||||
i, afterIndex = p.updateArgNumber(format, i)
|
||||
if i < end && format[i] == '*' {
|
||||
i++
|
||||
p.Prec, p.PrecPresent = p.intFromArg()
|
||||
// Negative precision arguments don't make sense
|
||||
if p.Prec < 0 {
|
||||
p.Prec = 0
|
||||
p.PrecPresent = false
|
||||
}
|
||||
if !p.PrecPresent {
|
||||
p.Status = StatusBadPrecSubstitution
|
||||
}
|
||||
afterIndex = false
|
||||
} else {
|
||||
p.Prec, p.PrecPresent, i = parsenum(format, i, end)
|
||||
if !p.PrecPresent {
|
||||
p.Prec = 0
|
||||
p.PrecPresent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !afterIndex {
|
||||
i, afterIndex = p.updateArgNumber(format, i)
|
||||
}
|
||||
p.HasIndex = afterIndex
|
||||
|
||||
if i >= end {
|
||||
p.endPos = i
|
||||
p.Status = StatusNoVerb
|
||||
return true
|
||||
}
|
||||
|
||||
verb, w := utf8.DecodeRuneInString(format[i:])
|
||||
p.endPos = i + w
|
||||
p.Verb = verb
|
||||
|
||||
switch {
|
||||
case verb == '%': // Percent does not absorb operands and ignores f.wid and f.prec.
|
||||
p.startPos = p.endPos - 1
|
||||
p.Status = StatusText
|
||||
case !p.goodArgNum:
|
||||
p.Status = StatusBadArgNum
|
||||
case p.ArgNum >= len(p.Args): // No argument left over to print for the current verb.
|
||||
p.Status = StatusMissingArg
|
||||
p.ArgNum++
|
||||
case verb == 'v':
|
||||
// Go syntax
|
||||
p.SharpV = p.Sharp
|
||||
p.Sharp = false
|
||||
// Struct-field syntax
|
||||
p.PlusV = p.Plus
|
||||
p.Plus = false
|
||||
fallthrough
|
||||
default:
|
||||
p.ArgNum++
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// intFromArg gets the ArgNumth element of Args. On return, isInt reports
|
||||
// whether the argument has integer type.
|
||||
func (p *Parser) intFromArg() (num int, isInt bool) {
|
||||
if p.ArgNum < len(p.Args) {
|
||||
arg := p.Args[p.ArgNum]
|
||||
num, isInt = arg.(int) // Almost always OK.
|
||||
if !isInt {
|
||||
// Work harder.
|
||||
switch v := reflect.ValueOf(arg); v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
n := v.Int()
|
||||
if int64(int(n)) == n {
|
||||
num = int(n)
|
||||
isInt = true
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
n := v.Uint()
|
||||
if int64(n) >= 0 && uint64(int(n)) == n {
|
||||
num = int(n)
|
||||
isInt = true
|
||||
}
|
||||
default:
|
||||
// Already 0, false.
|
||||
}
|
||||
}
|
||||
p.ArgNum++
|
||||
if tooLarge(num) {
|
||||
num = 0
|
||||
isInt = false
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// parseArgNumber returns the value of the bracketed number, minus 1
|
||||
// (explicit argument numbers are one-indexed but we want zero-indexed).
|
||||
// The opening bracket is known to be present at format[0].
|
||||
// The returned values are the index, the number of bytes to consume
|
||||
// up to the closing paren, if present, and whether the number parsed
|
||||
// ok. The bytes to consume will be 1 if no closing paren is present.
|
||||
func parseArgNumber(format string) (index int, wid int, ok bool) {
|
||||
// There must be at least 3 bytes: [n].
|
||||
if len(format) < 3 {
|
||||
return 0, 1, false
|
||||
}
|
||||
|
||||
// Find closing bracket.
|
||||
for i := 1; i < len(format); i++ {
|
||||
if format[i] == ']' {
|
||||
width, ok, newi := parsenum(format, 1, i)
|
||||
if !ok || newi != i {
|
||||
return 0, i + 1, false
|
||||
}
|
||||
return width - 1, i + 1, true // arg numbers are one-indexed and skip paren.
|
||||
}
|
||||
}
|
||||
return 0, 1, false
|
||||
}
|
||||
|
||||
// updateArgNumber returns the next argument to evaluate, which is either the value of the passed-in
|
||||
// argNum or the value of the bracketed integer that begins format[i:]. It also returns
|
||||
// the new value of i, that is, the index of the next byte of the format to process.
|
||||
func (p *Parser) updateArgNumber(format string, i int) (newi int, found bool) {
|
||||
if len(format) <= i || format[i] != '[' {
|
||||
return i, false
|
||||
}
|
||||
p.Reordered = true
|
||||
index, wid, ok := parseArgNumber(format[i:])
|
||||
if ok && 0 <= index && index < len(p.Args) {
|
||||
p.ArgNum = index
|
||||
return i + wid, true
|
||||
}
|
||||
p.goodArgNum = false
|
||||
return i + wid, ok
|
||||
}
|
||||
|
||||
// tooLarge reports whether the magnitude of the integer is
|
||||
// too large to be used as a formatting width or precision.
|
||||
func tooLarge(x int) bool {
|
||||
const max int = 1e6
|
||||
return x > max || x < -max
|
||||
}
|
||||
|
||||
// parsenum converts ASCII to integer. num is 0 (and isnum is false) if no number present.
|
||||
func parsenum(s string, start, end int) (num int, isnum bool, newi int) {
|
||||
if start >= end {
|
||||
return 0, false, end
|
||||
}
|
||||
for newi = start; newi < end && '0' <= s[newi] && s[newi] <= '9'; newi++ {
|
||||
if tooLarge(num) {
|
||||
return 0, false, end // Overflow; crazy long number most likely.
|
||||
}
|
||||
num = num*10 + int(s[newi]-'0')
|
||||
isnum = true
|
||||
}
|
||||
return
|
||||
}
|
55
vendor/golang.org/x/text/internal/number/common.go
generated
vendored
55
vendor/golang.org/x/text/internal/number/common.go
generated
vendored
@ -1,55 +0,0 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
package number
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/internal/language/compact"
|
||||
)
|
||||
|
||||
// A system identifies a CLDR numbering system.
|
||||
type system byte
|
||||
|
||||
type systemData struct {
|
||||
id system
|
||||
digitSize byte // number of UTF-8 bytes per digit
|
||||
zero [utf8.UTFMax]byte // UTF-8 sequence of zero digit.
|
||||
}
|
||||
|
||||
// A SymbolType identifies a symbol of a specific kind.
|
||||
type SymbolType int
|
||||
|
||||
const (
|
||||
SymDecimal SymbolType = iota
|
||||
SymGroup
|
||||
SymList
|
||||
SymPercentSign
|
||||
SymPlusSign
|
||||
SymMinusSign
|
||||
SymExponential
|
||||
SymSuperscriptingExponent
|
||||
SymPerMille
|
||||
SymInfinity
|
||||
SymNan
|
||||
SymTimeSeparator
|
||||
|
||||
NumSymbolTypes
|
||||
)
|
||||
|
||||
const hasNonLatnMask = 0x8000
|
||||
|
||||
// symOffset is an offset into altSymData if the bit indicated by hasNonLatnMask
|
||||
// is not 0 (with this bit masked out), and an offset into symIndex otherwise.
|
||||
//
|
||||
// TODO: this type can be a byte again if we use an indirection into altsymData
|
||||
// and introduce an alt -> offset slice (the length of this will be number of
|
||||
// alternatives plus 1). This also allows getting rid of the compactTag field
|
||||
// in altSymData. In total this will save about 1K.
|
||||
type symOffset uint16
|
||||
|
||||
type altSymData struct {
|
||||
compactTag compact.ID
|
||||
symIndex symOffset
|
||||
system system
|
||||
}
|
500
vendor/golang.org/x/text/internal/number/decimal.go
generated
vendored
500
vendor/golang.org/x/text/internal/number/decimal.go
generated
vendored
@ -1,500 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate stringer -type RoundingMode
|
||||
|
||||
package number
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// RoundingMode determines how a number is rounded to the desired precision.
|
||||
type RoundingMode byte
|
||||
|
||||
const (
|
||||
ToNearestEven RoundingMode = iota // towards the nearest integer, or towards an even number if equidistant.
|
||||
ToNearestZero // towards the nearest integer, or towards zero if equidistant.
|
||||
ToNearestAway // towards the nearest integer, or away from zero if equidistant.
|
||||
ToPositiveInf // towards infinity
|
||||
ToNegativeInf // towards negative infinity
|
||||
ToZero // towards zero
|
||||
AwayFromZero // away from zero
|
||||
numModes
|
||||
)
|
||||
|
||||
const maxIntDigits = 20
|
||||
|
||||
// A Decimal represents a floating point number in decimal format.
|
||||
// Digits represents a number [0, 1.0), and the absolute value represented by
|
||||
// Decimal is Digits * 10^Exp. Leading and trailing zeros may be omitted and Exp
|
||||
// may point outside a valid position in Digits.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// Number Decimal
|
||||
// 12345 Digits: [1, 2, 3, 4, 5], Exp: 5
|
||||
// 12.345 Digits: [1, 2, 3, 4, 5], Exp: 2
|
||||
// 12000 Digits: [1, 2], Exp: 5
|
||||
// 12000.00 Digits: [1, 2], Exp: 5
|
||||
// 0.00123 Digits: [1, 2, 3], Exp: -2
|
||||
// 0 Digits: [], Exp: 0
|
||||
type Decimal struct {
|
||||
digits
|
||||
|
||||
buf [maxIntDigits]byte
|
||||
}
|
||||
|
||||
type digits struct {
|
||||
Digits []byte // mantissa digits, big-endian
|
||||
Exp int32 // exponent
|
||||
Neg bool
|
||||
Inf bool // Takes precedence over Digits and Exp.
|
||||
NaN bool // Takes precedence over Inf.
|
||||
}
|
||||
|
||||
// Digits represents a floating point number represented in digits of the
|
||||
// base in which a number is to be displayed. It is similar to Decimal, but
|
||||
// keeps track of trailing fraction zeros and the comma placement for
|
||||
// engineering notation. Digits must have at least one digit.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// Number Decimal
|
||||
// decimal
|
||||
// 12345 Digits: [1, 2, 3, 4, 5], Exp: 5 End: 5
|
||||
// 12.345 Digits: [1, 2, 3, 4, 5], Exp: 2 End: 5
|
||||
// 12000 Digits: [1, 2], Exp: 5 End: 5
|
||||
// 12000.00 Digits: [1, 2], Exp: 5 End: 7
|
||||
// 0.00123 Digits: [1, 2, 3], Exp: -2 End: 3
|
||||
// 0 Digits: [], Exp: 0 End: 1
|
||||
// scientific (actual exp is Exp - Comma)
|
||||
// 0e0 Digits: [0], Exp: 1, End: 1, Comma: 1
|
||||
// .0e0 Digits: [0], Exp: 0, End: 1, Comma: 0
|
||||
// 0.0e0 Digits: [0], Exp: 1, End: 2, Comma: 1
|
||||
// 1.23e4 Digits: [1, 2, 3], Exp: 5, End: 3, Comma: 1
|
||||
// .123e5 Digits: [1, 2, 3], Exp: 5, End: 3, Comma: 0
|
||||
// engineering
|
||||
// 12.3e3 Digits: [1, 2, 3], Exp: 5, End: 3, Comma: 2
|
||||
type Digits struct {
|
||||
digits
|
||||
// End indicates the end position of the number.
|
||||
End int32 // For decimals Exp <= End. For scientific len(Digits) <= End.
|
||||
// Comma is used for the comma position for scientific (always 0 or 1) and
|
||||
// engineering notation (always 0, 1, 2, or 3).
|
||||
Comma uint8
|
||||
// IsScientific indicates whether this number is to be rendered as a
|
||||
// scientific number.
|
||||
IsScientific bool
|
||||
}
|
||||
|
||||
func (d *Digits) NumFracDigits() int {
|
||||
if d.Exp >= d.End {
|
||||
return 0
|
||||
}
|
||||
return int(d.End - d.Exp)
|
||||
}
|
||||
|
||||
// normalize returns a new Decimal with leading and trailing zeros removed.
|
||||
func (d *Decimal) normalize() (n Decimal) {
|
||||
n = *d
|
||||
b := n.Digits
|
||||
// Strip leading zeros. Resulting number of digits is significant digits.
|
||||
for len(b) > 0 && b[0] == 0 {
|
||||
b = b[1:]
|
||||
n.Exp--
|
||||
}
|
||||
// Strip trailing zeros
|
||||
for len(b) > 0 && b[len(b)-1] == 0 {
|
||||
b = b[:len(b)-1]
|
||||
}
|
||||
if len(b) == 0 {
|
||||
n.Exp = 0
|
||||
}
|
||||
n.Digits = b
|
||||
return n
|
||||
}
|
||||
|
||||
func (d *Decimal) clear() {
|
||||
b := d.Digits
|
||||
if b == nil {
|
||||
b = d.buf[:0]
|
||||
}
|
||||
*d = Decimal{}
|
||||
d.Digits = b[:0]
|
||||
}
|
||||
|
||||
func (x *Decimal) String() string {
|
||||
if x.NaN {
|
||||
return "NaN"
|
||||
}
|
||||
var buf []byte
|
||||
if x.Neg {
|
||||
buf = append(buf, '-')
|
||||
}
|
||||
if x.Inf {
|
||||
buf = append(buf, "Inf"...)
|
||||
return string(buf)
|
||||
}
|
||||
switch {
|
||||
case len(x.Digits) == 0:
|
||||
buf = append(buf, '0')
|
||||
case x.Exp <= 0:
|
||||
// 0.00ddd
|
||||
buf = append(buf, "0."...)
|
||||
buf = appendZeros(buf, -int(x.Exp))
|
||||
buf = appendDigits(buf, x.Digits)
|
||||
|
||||
case /* 0 < */ int(x.Exp) < len(x.Digits):
|
||||
// dd.ddd
|
||||
buf = appendDigits(buf, x.Digits[:x.Exp])
|
||||
buf = append(buf, '.')
|
||||
buf = appendDigits(buf, x.Digits[x.Exp:])
|
||||
|
||||
default: // len(x.Digits) <= x.Exp
|
||||
// ddd00
|
||||
buf = appendDigits(buf, x.Digits)
|
||||
buf = appendZeros(buf, int(x.Exp)-len(x.Digits))
|
||||
}
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
func appendDigits(buf []byte, digits []byte) []byte {
|
||||
for _, c := range digits {
|
||||
buf = append(buf, c+'0')
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
// appendZeros appends n 0 digits to buf and returns buf.
|
||||
func appendZeros(buf []byte, n int) []byte {
|
||||
for ; n > 0; n-- {
|
||||
buf = append(buf, '0')
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
func (d *digits) round(mode RoundingMode, n int) {
|
||||
if n >= len(d.Digits) {
|
||||
return
|
||||
}
|
||||
// Make rounding decision: The result mantissa is truncated ("rounded down")
|
||||
// by default. Decide if we need to increment, or "round up", the (unsigned)
|
||||
// mantissa.
|
||||
inc := false
|
||||
switch mode {
|
||||
case ToNegativeInf:
|
||||
inc = d.Neg
|
||||
case ToPositiveInf:
|
||||
inc = !d.Neg
|
||||
case ToZero:
|
||||
// nothing to do
|
||||
case AwayFromZero:
|
||||
inc = true
|
||||
case ToNearestEven:
|
||||
inc = d.Digits[n] > 5 || d.Digits[n] == 5 &&
|
||||
(len(d.Digits) > n+1 || n == 0 || d.Digits[n-1]&1 != 0)
|
||||
case ToNearestAway:
|
||||
inc = d.Digits[n] >= 5
|
||||
case ToNearestZero:
|
||||
inc = d.Digits[n] > 5 || d.Digits[n] == 5 && len(d.Digits) > n+1
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
if inc {
|
||||
d.roundUp(n)
|
||||
} else {
|
||||
d.roundDown(n)
|
||||
}
|
||||
}
|
||||
|
||||
// roundFloat rounds a floating point number.
|
||||
func (r RoundingMode) roundFloat(x float64) float64 {
|
||||
// Make rounding decision: The result mantissa is truncated ("rounded down")
|
||||
// by default. Decide if we need to increment, or "round up", the (unsigned)
|
||||
// mantissa.
|
||||
abs := x
|
||||
if x < 0 {
|
||||
abs = -x
|
||||
}
|
||||
i, f := math.Modf(abs)
|
||||
if f == 0.0 {
|
||||
return x
|
||||
}
|
||||
inc := false
|
||||
switch r {
|
||||
case ToNegativeInf:
|
||||
inc = x < 0
|
||||
case ToPositiveInf:
|
||||
inc = x >= 0
|
||||
case ToZero:
|
||||
// nothing to do
|
||||
case AwayFromZero:
|
||||
inc = true
|
||||
case ToNearestEven:
|
||||
// TODO: check overflow
|
||||
inc = f > 0.5 || f == 0.5 && int64(i)&1 != 0
|
||||
case ToNearestAway:
|
||||
inc = f >= 0.5
|
||||
case ToNearestZero:
|
||||
inc = f > 0.5
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
if inc {
|
||||
i += 1
|
||||
}
|
||||
if abs != x {
|
||||
i = -i
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func (x *digits) roundUp(n int) {
|
||||
if n < 0 || n >= len(x.Digits) {
|
||||
return // nothing to do
|
||||
}
|
||||
// find first digit < 9
|
||||
for n > 0 && x.Digits[n-1] >= 9 {
|
||||
n--
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
// all digits are 9s => round up to 1 and update exponent
|
||||
x.Digits[0] = 1 // ok since len(x.Digits) > n
|
||||
x.Digits = x.Digits[:1]
|
||||
x.Exp++
|
||||
return
|
||||
}
|
||||
x.Digits[n-1]++
|
||||
x.Digits = x.Digits[:n]
|
||||
// x already trimmed
|
||||
}
|
||||
|
||||
func (x *digits) roundDown(n int) {
|
||||
if n < 0 || n >= len(x.Digits) {
|
||||
return // nothing to do
|
||||
}
|
||||
x.Digits = x.Digits[:n]
|
||||
trim(x)
|
||||
}
|
||||
|
||||
// trim cuts off any trailing zeros from x's mantissa;
|
||||
// they are meaningless for the value of x.
|
||||
func trim(x *digits) {
|
||||
i := len(x.Digits)
|
||||
for i > 0 && x.Digits[i-1] == 0 {
|
||||
i--
|
||||
}
|
||||
x.Digits = x.Digits[:i]
|
||||
if i == 0 {
|
||||
x.Exp = 0
|
||||
}
|
||||
}
|
||||
|
||||
// A Converter converts a number into decimals according to the given rounding
|
||||
// criteria.
|
||||
type Converter interface {
|
||||
Convert(d *Decimal, r RoundingContext)
|
||||
}
|
||||
|
||||
const (
|
||||
signed = true
|
||||
unsigned = false
|
||||
)
|
||||
|
||||
// Convert converts the given number to the decimal representation using the
|
||||
// supplied RoundingContext.
|
||||
func (d *Decimal) Convert(r RoundingContext, number interface{}) {
|
||||
switch f := number.(type) {
|
||||
case Converter:
|
||||
d.clear()
|
||||
f.Convert(d, r)
|
||||
case float32:
|
||||
d.ConvertFloat(r, float64(f), 32)
|
||||
case float64:
|
||||
d.ConvertFloat(r, f, 64)
|
||||
case int:
|
||||
d.ConvertInt(r, signed, uint64(f))
|
||||
case int8:
|
||||
d.ConvertInt(r, signed, uint64(f))
|
||||
case int16:
|
||||
d.ConvertInt(r, signed, uint64(f))
|
||||
case int32:
|
||||
d.ConvertInt(r, signed, uint64(f))
|
||||
case int64:
|
||||
d.ConvertInt(r, signed, uint64(f))
|
||||
case uint:
|
||||
d.ConvertInt(r, unsigned, uint64(f))
|
||||
case uint8:
|
||||
d.ConvertInt(r, unsigned, uint64(f))
|
||||
case uint16:
|
||||
d.ConvertInt(r, unsigned, uint64(f))
|
||||
case uint32:
|
||||
d.ConvertInt(r, unsigned, uint64(f))
|
||||
case uint64:
|
||||
d.ConvertInt(r, unsigned, f)
|
||||
|
||||
default:
|
||||
d.NaN = true
|
||||
// TODO:
|
||||
// case string: if produced by strconv, allows for easy arbitrary pos.
|
||||
// case reflect.Value:
|
||||
// case big.Float
|
||||
// case big.Int
|
||||
// case big.Rat?
|
||||
// catch underlyings using reflect or will this already be done by the
|
||||
// message package?
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertInt converts an integer to decimals.
|
||||
func (d *Decimal) ConvertInt(r RoundingContext, signed bool, x uint64) {
|
||||
if r.Increment > 0 {
|
||||
// TODO: if uint64 is too large, fall back to float64
|
||||
if signed {
|
||||
d.ConvertFloat(r, float64(int64(x)), 64)
|
||||
} else {
|
||||
d.ConvertFloat(r, float64(x), 64)
|
||||
}
|
||||
return
|
||||
}
|
||||
d.clear()
|
||||
if signed && int64(x) < 0 {
|
||||
x = uint64(-int64(x))
|
||||
d.Neg = true
|
||||
}
|
||||
d.fillIntDigits(x)
|
||||
d.Exp = int32(len(d.Digits))
|
||||
}
|
||||
|
||||
// ConvertFloat converts a floating point number to decimals.
|
||||
func (d *Decimal) ConvertFloat(r RoundingContext, x float64, size int) {
|
||||
d.clear()
|
||||
if math.IsNaN(x) {
|
||||
d.NaN = true
|
||||
return
|
||||
}
|
||||
// Simple case: decimal notation
|
||||
if r.Increment > 0 {
|
||||
scale := int(r.IncrementScale)
|
||||
mult := 1.0
|
||||
if scale >= len(scales) {
|
||||
mult = math.Pow(10, float64(scale))
|
||||
} else {
|
||||
mult = scales[scale]
|
||||
}
|
||||
// We multiply x instead of dividing inc as it gives less rounding
|
||||
// issues.
|
||||
x *= mult
|
||||
x /= float64(r.Increment)
|
||||
x = r.Mode.roundFloat(x)
|
||||
x *= float64(r.Increment)
|
||||
x /= mult
|
||||
}
|
||||
|
||||
abs := x
|
||||
if x < 0 {
|
||||
d.Neg = true
|
||||
abs = -x
|
||||
}
|
||||
if math.IsInf(abs, 1) {
|
||||
d.Inf = true
|
||||
return
|
||||
}
|
||||
|
||||
// By default we get the exact decimal representation.
|
||||
verb := byte('g')
|
||||
prec := -1
|
||||
// As the strconv API does not return the rounding accuracy, we can only
|
||||
// round using ToNearestEven.
|
||||
if r.Mode == ToNearestEven {
|
||||
if n := r.RoundSignificantDigits(); n >= 0 {
|
||||
prec = n
|
||||
} else if n = r.RoundFractionDigits(); n >= 0 {
|
||||
prec = n
|
||||
verb = 'f'
|
||||
}
|
||||
} else {
|
||||
// TODO: At this point strconv's rounding is imprecise to the point that
|
||||
// it is not usable for this purpose.
|
||||
// See https://github.com/golang/go/issues/21714
|
||||
// If rounding is requested, we ask for a large number of digits and
|
||||
// round from there to simulate rounding only once.
|
||||
// Ideally we would have strconv export an AppendDigits that would take
|
||||
// a rounding mode and/or return an accuracy. Something like this would
|
||||
// work:
|
||||
// AppendDigits(dst []byte, x float64, base, size, prec int) (digits []byte, exp, accuracy int)
|
||||
hasPrec := r.RoundSignificantDigits() >= 0
|
||||
hasScale := r.RoundFractionDigits() >= 0
|
||||
if hasPrec || hasScale {
|
||||
// prec is the number of mantissa bits plus some extra for safety.
|
||||
// We need at least the number of mantissa bits as decimals to
|
||||
// accurately represent the floating point without rounding, as each
|
||||
// bit requires one more decimal to represent: 0.5, 0.25, 0.125, ...
|
||||
prec = 60
|
||||
}
|
||||
}
|
||||
|
||||
b := strconv.AppendFloat(d.Digits[:0], abs, verb, prec, size)
|
||||
i := 0
|
||||
k := 0
|
||||
beforeDot := 1
|
||||
for i < len(b) {
|
||||
if c := b[i]; '0' <= c && c <= '9' {
|
||||
b[k] = c - '0'
|
||||
k++
|
||||
d.Exp += int32(beforeDot)
|
||||
} else if c == '.' {
|
||||
beforeDot = 0
|
||||
d.Exp = int32(k)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
d.Digits = b[:k]
|
||||
if i != len(b) {
|
||||
i += len("e")
|
||||
pSign := i
|
||||
exp := 0
|
||||
for i++; i < len(b); i++ {
|
||||
exp *= 10
|
||||
exp += int(b[i] - '0')
|
||||
}
|
||||
if b[pSign] == '-' {
|
||||
exp = -exp
|
||||
}
|
||||
d.Exp = int32(exp) + 1
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Decimal) fillIntDigits(x uint64) {
|
||||
if cap(d.Digits) < maxIntDigits {
|
||||
d.Digits = d.buf[:]
|
||||
} else {
|
||||
d.Digits = d.buf[:maxIntDigits]
|
||||
}
|
||||
i := 0
|
||||
for ; x > 0; x /= 10 {
|
||||
d.Digits[i] = byte(x % 10)
|
||||
i++
|
||||
}
|
||||
d.Digits = d.Digits[:i]
|
||||
for p := 0; p < i; p++ {
|
||||
i--
|
||||
d.Digits[p], d.Digits[i] = d.Digits[i], d.Digits[p]
|
||||
}
|
||||
}
|
||||
|
||||
var scales [70]float64
|
||||
|
||||
func init() {
|
||||
x := 1.0
|
||||
for i := range scales {
|
||||
scales[i] = x
|
||||
x *= 10
|
||||
}
|
||||
}
|
535
vendor/golang.org/x/text/internal/number/format.go
generated
vendored
535
vendor/golang.org/x/text/internal/number/format.go
generated
vendored
@ -1,535 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package number
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// TODO:
|
||||
// - grouping of fractions
|
||||
// - allow user-defined superscript notation (such as <sup>4</sup>)
|
||||
// - same for non-breaking spaces, like
|
||||
|
||||
// A VisibleDigits computes digits, comma placement and trailing zeros as they
|
||||
// will be shown to the user.
|
||||
type VisibleDigits interface {
|
||||
Digits(buf []byte, t language.Tag, scale int) Digits
|
||||
// TODO: Do we also need to add the verb or pass a format.State?
|
||||
}
|
||||
|
||||
// Formatting proceeds along the following lines:
|
||||
// 0) Compose rounding information from format and context.
|
||||
// 1) Convert a number into a Decimal.
|
||||
// 2) Sanitize Decimal by adding trailing zeros, removing leading digits, and
|
||||
// (non-increment) rounding. The Decimal that results from this is suitable
|
||||
// for determining the plural form.
|
||||
// 3) Render the Decimal in the localized form.
|
||||
|
||||
// Formatter contains all the information needed to render a number.
|
||||
type Formatter struct {
|
||||
Pattern
|
||||
Info
|
||||
}
|
||||
|
||||
func (f *Formatter) init(t language.Tag, index []uint8) {
|
||||
f.Info = InfoFromTag(t)
|
||||
f.Pattern = formats[index[tagToID(t)]]
|
||||
}
|
||||
|
||||
// InitPattern initializes a Formatter for the given Pattern.
|
||||
func (f *Formatter) InitPattern(t language.Tag, pat *Pattern) {
|
||||
f.Info = InfoFromTag(t)
|
||||
f.Pattern = *pat
|
||||
}
|
||||
|
||||
// InitDecimal initializes a Formatter using the default Pattern for the given
|
||||
// language.
|
||||
func (f *Formatter) InitDecimal(t language.Tag) {
|
||||
f.init(t, tagToDecimal)
|
||||
}
|
||||
|
||||
// InitScientific initializes a Formatter using the default Pattern for the
|
||||
// given language.
|
||||
func (f *Formatter) InitScientific(t language.Tag) {
|
||||
f.init(t, tagToScientific)
|
||||
f.Pattern.MinFractionDigits = 0
|
||||
f.Pattern.MaxFractionDigits = -1
|
||||
}
|
||||
|
||||
// InitEngineering initializes a Formatter using the default Pattern for the
|
||||
// given language.
|
||||
func (f *Formatter) InitEngineering(t language.Tag) {
|
||||
f.init(t, tagToScientific)
|
||||
f.Pattern.MinFractionDigits = 0
|
||||
f.Pattern.MaxFractionDigits = -1
|
||||
f.Pattern.MaxIntegerDigits = 3
|
||||
f.Pattern.MinIntegerDigits = 1
|
||||
}
|
||||
|
||||
// InitPercent initializes a Formatter using the default Pattern for the given
|
||||
// language.
|
||||
func (f *Formatter) InitPercent(t language.Tag) {
|
||||
f.init(t, tagToPercent)
|
||||
}
|
||||
|
||||
// InitPerMille initializes a Formatter using the default Pattern for the given
|
||||
// language.
|
||||
func (f *Formatter) InitPerMille(t language.Tag) {
|
||||
f.init(t, tagToPercent)
|
||||
f.Pattern.DigitShift = 3
|
||||
}
|
||||
|
||||
func (f *Formatter) Append(dst []byte, x interface{}) []byte {
|
||||
var d Decimal
|
||||
r := f.RoundingContext
|
||||
d.Convert(r, x)
|
||||
return f.Render(dst, FormatDigits(&d, r))
|
||||
}
|
||||
|
||||
func FormatDigits(d *Decimal, r RoundingContext) Digits {
|
||||
if r.isScientific() {
|
||||
return scientificVisibleDigits(r, d)
|
||||
}
|
||||
return decimalVisibleDigits(r, d)
|
||||
}
|
||||
|
||||
func (f *Formatter) Format(dst []byte, d *Decimal) []byte {
|
||||
return f.Render(dst, FormatDigits(d, f.RoundingContext))
|
||||
}
|
||||
|
||||
func (f *Formatter) Render(dst []byte, d Digits) []byte {
|
||||
var result []byte
|
||||
var postPrefix, preSuffix int
|
||||
if d.IsScientific {
|
||||
result, postPrefix, preSuffix = appendScientific(dst, f, &d)
|
||||
} else {
|
||||
result, postPrefix, preSuffix = appendDecimal(dst, f, &d)
|
||||
}
|
||||
if f.PadRune == 0 {
|
||||
return result
|
||||
}
|
||||
width := int(f.FormatWidth)
|
||||
if count := utf8.RuneCount(result); count < width {
|
||||
insertPos := 0
|
||||
switch f.Flags & PadMask {
|
||||
case PadAfterPrefix:
|
||||
insertPos = postPrefix
|
||||
case PadBeforeSuffix:
|
||||
insertPos = preSuffix
|
||||
case PadAfterSuffix:
|
||||
insertPos = len(result)
|
||||
}
|
||||
num := width - count
|
||||
pad := [utf8.UTFMax]byte{' '}
|
||||
sz := 1
|
||||
if r := f.PadRune; r != 0 {
|
||||
sz = utf8.EncodeRune(pad[:], r)
|
||||
}
|
||||
extra := sz * num
|
||||
if n := len(result) + extra; n < cap(result) {
|
||||
result = result[:n]
|
||||
copy(result[insertPos+extra:], result[insertPos:])
|
||||
} else {
|
||||
buf := make([]byte, n)
|
||||
copy(buf, result[:insertPos])
|
||||
copy(buf[insertPos+extra:], result[insertPos:])
|
||||
result = buf
|
||||
}
|
||||
for ; num > 0; num-- {
|
||||
insertPos += copy(result[insertPos:], pad[:sz])
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// decimalVisibleDigits converts d according to the RoundingContext. Note that
|
||||
// the exponent may change as a result of this operation.
|
||||
func decimalVisibleDigits(r RoundingContext, d *Decimal) Digits {
|
||||
if d.NaN || d.Inf {
|
||||
return Digits{digits: digits{Neg: d.Neg, NaN: d.NaN, Inf: d.Inf}}
|
||||
}
|
||||
n := Digits{digits: d.normalize().digits}
|
||||
|
||||
exp := n.Exp
|
||||
exp += int32(r.DigitShift)
|
||||
|
||||
// Cap integer digits. Remove *most-significant* digits.
|
||||
if r.MaxIntegerDigits > 0 {
|
||||
if p := int(exp) - int(r.MaxIntegerDigits); p > 0 {
|
||||
if p > len(n.Digits) {
|
||||
p = len(n.Digits)
|
||||
}
|
||||
if n.Digits = n.Digits[p:]; len(n.Digits) == 0 {
|
||||
exp = 0
|
||||
} else {
|
||||
exp -= int32(p)
|
||||
}
|
||||
// Strip leading zeros.
|
||||
for len(n.Digits) > 0 && n.Digits[0] == 0 {
|
||||
n.Digits = n.Digits[1:]
|
||||
exp--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rounding if not already done by Convert.
|
||||
p := len(n.Digits)
|
||||
if maxSig := int(r.MaxSignificantDigits); maxSig > 0 {
|
||||
p = maxSig
|
||||
}
|
||||
if maxFrac := int(r.MaxFractionDigits); maxFrac >= 0 {
|
||||
if cap := int(exp) + maxFrac; cap < p {
|
||||
p = int(exp) + maxFrac
|
||||
}
|
||||
if p < 0 {
|
||||
p = 0
|
||||
}
|
||||
}
|
||||
n.round(r.Mode, p)
|
||||
|
||||
// set End (trailing zeros)
|
||||
n.End = int32(len(n.Digits))
|
||||
if n.End == 0 {
|
||||
exp = 0
|
||||
if r.MinFractionDigits > 0 {
|
||||
n.End = int32(r.MinFractionDigits)
|
||||
}
|
||||
if p := int32(r.MinSignificantDigits) - 1; p > n.End {
|
||||
n.End = p
|
||||
}
|
||||
} else {
|
||||
if end := exp + int32(r.MinFractionDigits); end > n.End {
|
||||
n.End = end
|
||||
}
|
||||
if n.End < int32(r.MinSignificantDigits) {
|
||||
n.End = int32(r.MinSignificantDigits)
|
||||
}
|
||||
}
|
||||
n.Exp = exp
|
||||
return n
|
||||
}
|
||||
|
||||
// appendDecimal appends a formatted number to dst. It returns two possible
|
||||
// insertion points for padding.
|
||||
func appendDecimal(dst []byte, f *Formatter, n *Digits) (b []byte, postPre, preSuf int) {
|
||||
if dst, ok := f.renderSpecial(dst, n); ok {
|
||||
return dst, 0, len(dst)
|
||||
}
|
||||
digits := n.Digits
|
||||
exp := n.Exp
|
||||
|
||||
// Split in integer and fraction part.
|
||||
var intDigits, fracDigits []byte
|
||||
numInt := 0
|
||||
numFrac := int(n.End - n.Exp)
|
||||
if exp > 0 {
|
||||
numInt = int(exp)
|
||||
if int(exp) >= len(digits) { // ddddd | ddddd00
|
||||
intDigits = digits
|
||||
} else { // ddd.dd
|
||||
intDigits = digits[:exp]
|
||||
fracDigits = digits[exp:]
|
||||
}
|
||||
} else {
|
||||
fracDigits = digits
|
||||
}
|
||||
|
||||
neg := n.Neg
|
||||
affix, suffix := f.getAffixes(neg)
|
||||
dst = appendAffix(dst, f, affix, neg)
|
||||
savedLen := len(dst)
|
||||
|
||||
minInt := int(f.MinIntegerDigits)
|
||||
if minInt == 0 && f.MinSignificantDigits > 0 {
|
||||
minInt = 1
|
||||
}
|
||||
// add leading zeros
|
||||
for i := minInt; i > numInt; i-- {
|
||||
dst = f.AppendDigit(dst, 0)
|
||||
if f.needsSep(i) {
|
||||
dst = append(dst, f.Symbol(SymGroup)...)
|
||||
}
|
||||
}
|
||||
i := 0
|
||||
for ; i < len(intDigits); i++ {
|
||||
dst = f.AppendDigit(dst, intDigits[i])
|
||||
if f.needsSep(numInt - i) {
|
||||
dst = append(dst, f.Symbol(SymGroup)...)
|
||||
}
|
||||
}
|
||||
for ; i < numInt; i++ {
|
||||
dst = f.AppendDigit(dst, 0)
|
||||
if f.needsSep(numInt - i) {
|
||||
dst = append(dst, f.Symbol(SymGroup)...)
|
||||
}
|
||||
}
|
||||
|
||||
if numFrac > 0 || f.Flags&AlwaysDecimalSeparator != 0 {
|
||||
dst = append(dst, f.Symbol(SymDecimal)...)
|
||||
}
|
||||
// Add trailing zeros
|
||||
i = 0
|
||||
for n := -int(n.Exp); i < n; i++ {
|
||||
dst = f.AppendDigit(dst, 0)
|
||||
}
|
||||
for _, d := range fracDigits {
|
||||
i++
|
||||
dst = f.AppendDigit(dst, d)
|
||||
}
|
||||
for ; i < numFrac; i++ {
|
||||
dst = f.AppendDigit(dst, 0)
|
||||
}
|
||||
return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
|
||||
}
|
||||
|
||||
func scientificVisibleDigits(r RoundingContext, d *Decimal) Digits {
|
||||
if d.NaN || d.Inf {
|
||||
return Digits{digits: digits{Neg: d.Neg, NaN: d.NaN, Inf: d.Inf}}
|
||||
}
|
||||
n := Digits{digits: d.normalize().digits, IsScientific: true}
|
||||
|
||||
// Normalize to have at least one digit. This simplifies engineering
|
||||
// notation.
|
||||
if len(n.Digits) == 0 {
|
||||
n.Digits = append(n.Digits, 0)
|
||||
n.Exp = 1
|
||||
}
|
||||
|
||||
// Significant digits are transformed by the parser for scientific notation
|
||||
// and do not need to be handled here.
|
||||
maxInt, numInt := int(r.MaxIntegerDigits), int(r.MinIntegerDigits)
|
||||
if numInt == 0 {
|
||||
numInt = 1
|
||||
}
|
||||
|
||||
// If a maximum number of integers is specified, the minimum must be 1
|
||||
// and the exponent is grouped by this number (e.g. for engineering)
|
||||
if maxInt > numInt {
|
||||
// Correct the exponent to reflect a single integer digit.
|
||||
numInt = 1
|
||||
// engineering
|
||||
// 0.01234 ([12345]e-1) -> 1.2345e-2 12.345e-3
|
||||
// 12345 ([12345]e+5) -> 1.2345e4 12.345e3
|
||||
d := int(n.Exp-1) % maxInt
|
||||
if d < 0 {
|
||||
d += maxInt
|
||||
}
|
||||
numInt += d
|
||||
}
|
||||
|
||||
p := len(n.Digits)
|
||||
if maxSig := int(r.MaxSignificantDigits); maxSig > 0 {
|
||||
p = maxSig
|
||||
}
|
||||
if maxFrac := int(r.MaxFractionDigits); maxFrac >= 0 && numInt+maxFrac < p {
|
||||
p = numInt + maxFrac
|
||||
}
|
||||
n.round(r.Mode, p)
|
||||
|
||||
n.Comma = uint8(numInt)
|
||||
n.End = int32(len(n.Digits))
|
||||
if minSig := int32(r.MinFractionDigits) + int32(numInt); n.End < minSig {
|
||||
n.End = minSig
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// appendScientific appends a formatted number to dst. It returns two possible
|
||||
// insertion points for padding.
|
||||
func appendScientific(dst []byte, f *Formatter, n *Digits) (b []byte, postPre, preSuf int) {
|
||||
if dst, ok := f.renderSpecial(dst, n); ok {
|
||||
return dst, 0, 0
|
||||
}
|
||||
digits := n.Digits
|
||||
numInt := int(n.Comma)
|
||||
numFrac := int(n.End) - int(n.Comma)
|
||||
|
||||
var intDigits, fracDigits []byte
|
||||
if numInt <= len(digits) {
|
||||
intDigits = digits[:numInt]
|
||||
fracDigits = digits[numInt:]
|
||||
} else {
|
||||
intDigits = digits
|
||||
}
|
||||
neg := n.Neg
|
||||
affix, suffix := f.getAffixes(neg)
|
||||
dst = appendAffix(dst, f, affix, neg)
|
||||
savedLen := len(dst)
|
||||
|
||||
i := 0
|
||||
for ; i < len(intDigits); i++ {
|
||||
dst = f.AppendDigit(dst, intDigits[i])
|
||||
if f.needsSep(numInt - i) {
|
||||
dst = append(dst, f.Symbol(SymGroup)...)
|
||||
}
|
||||
}
|
||||
for ; i < numInt; i++ {
|
||||
dst = f.AppendDigit(dst, 0)
|
||||
if f.needsSep(numInt - i) {
|
||||
dst = append(dst, f.Symbol(SymGroup)...)
|
||||
}
|
||||
}
|
||||
|
||||
if numFrac > 0 || f.Flags&AlwaysDecimalSeparator != 0 {
|
||||
dst = append(dst, f.Symbol(SymDecimal)...)
|
||||
}
|
||||
i = 0
|
||||
for ; i < len(fracDigits); i++ {
|
||||
dst = f.AppendDigit(dst, fracDigits[i])
|
||||
}
|
||||
for ; i < numFrac; i++ {
|
||||
dst = f.AppendDigit(dst, 0)
|
||||
}
|
||||
|
||||
// exp
|
||||
buf := [12]byte{}
|
||||
// TODO: use exponential if superscripting is not available (no Latin
|
||||
// numbers or no tags) and use exponential in all other cases.
|
||||
exp := n.Exp - int32(n.Comma)
|
||||
exponential := f.Symbol(SymExponential)
|
||||
if exponential == "E" {
|
||||
dst = append(dst, "\u202f"...) // NARROW NO-BREAK SPACE
|
||||
dst = append(dst, f.Symbol(SymSuperscriptingExponent)...)
|
||||
dst = append(dst, "\u202f"...) // NARROW NO-BREAK SPACE
|
||||
dst = f.AppendDigit(dst, 1)
|
||||
dst = f.AppendDigit(dst, 0)
|
||||
switch {
|
||||
case exp < 0:
|
||||
dst = append(dst, superMinus...)
|
||||
exp = -exp
|
||||
case f.Flags&AlwaysExpSign != 0:
|
||||
dst = append(dst, superPlus...)
|
||||
}
|
||||
b = strconv.AppendUint(buf[:0], uint64(exp), 10)
|
||||
for i := len(b); i < int(f.MinExponentDigits); i++ {
|
||||
dst = append(dst, superDigits[0]...)
|
||||
}
|
||||
for _, c := range b {
|
||||
dst = append(dst, superDigits[c-'0']...)
|
||||
}
|
||||
} else {
|
||||
dst = append(dst, exponential...)
|
||||
switch {
|
||||
case exp < 0:
|
||||
dst = append(dst, f.Symbol(SymMinusSign)...)
|
||||
exp = -exp
|
||||
case f.Flags&AlwaysExpSign != 0:
|
||||
dst = append(dst, f.Symbol(SymPlusSign)...)
|
||||
}
|
||||
b = strconv.AppendUint(buf[:0], uint64(exp), 10)
|
||||
for i := len(b); i < int(f.MinExponentDigits); i++ {
|
||||
dst = f.AppendDigit(dst, 0)
|
||||
}
|
||||
for _, c := range b {
|
||||
dst = f.AppendDigit(dst, c-'0')
|
||||
}
|
||||
}
|
||||
return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
|
||||
}
|
||||
|
||||
const (
|
||||
superMinus = "\u207B" // SUPERSCRIPT HYPHEN-MINUS
|
||||
superPlus = "\u207A" // SUPERSCRIPT PLUS SIGN
|
||||
)
|
||||
|
||||
var (
|
||||
// Note: the digits are not sequential!!!
|
||||
superDigits = []string{
|
||||
"\u2070", // SUPERSCRIPT DIGIT ZERO
|
||||
"\u00B9", // SUPERSCRIPT DIGIT ONE
|
||||
"\u00B2", // SUPERSCRIPT DIGIT TWO
|
||||
"\u00B3", // SUPERSCRIPT DIGIT THREE
|
||||
"\u2074", // SUPERSCRIPT DIGIT FOUR
|
||||
"\u2075", // SUPERSCRIPT DIGIT FIVE
|
||||
"\u2076", // SUPERSCRIPT DIGIT SIX
|
||||
"\u2077", // SUPERSCRIPT DIGIT SEVEN
|
||||
"\u2078", // SUPERSCRIPT DIGIT EIGHT
|
||||
"\u2079", // SUPERSCRIPT DIGIT NINE
|
||||
}
|
||||
)
|
||||
|
||||
func (f *Formatter) getAffixes(neg bool) (affix, suffix string) {
|
||||
str := f.Affix
|
||||
if str != "" {
|
||||
if f.NegOffset > 0 {
|
||||
if neg {
|
||||
str = str[f.NegOffset:]
|
||||
} else {
|
||||
str = str[:f.NegOffset]
|
||||
}
|
||||
}
|
||||
sufStart := 1 + str[0]
|
||||
affix = str[1:sufStart]
|
||||
suffix = str[sufStart+1:]
|
||||
}
|
||||
// TODO: introduce a NeedNeg sign to indicate if the left pattern already
|
||||
// has a sign marked?
|
||||
if f.NegOffset == 0 && (neg || f.Flags&AlwaysSign != 0) {
|
||||
affix = "-" + affix
|
||||
}
|
||||
return affix, suffix
|
||||
}
|
||||
|
||||
func (f *Formatter) renderSpecial(dst []byte, d *Digits) (b []byte, ok bool) {
|
||||
if d.NaN {
|
||||
return fmtNaN(dst, f), true
|
||||
}
|
||||
if d.Inf {
|
||||
return fmtInfinite(dst, f, d), true
|
||||
}
|
||||
return dst, false
|
||||
}
|
||||
|
||||
func fmtNaN(dst []byte, f *Formatter) []byte {
|
||||
return append(dst, f.Symbol(SymNan)...)
|
||||
}
|
||||
|
||||
func fmtInfinite(dst []byte, f *Formatter, d *Digits) []byte {
|
||||
affix, suffix := f.getAffixes(d.Neg)
|
||||
dst = appendAffix(dst, f, affix, d.Neg)
|
||||
dst = append(dst, f.Symbol(SymInfinity)...)
|
||||
dst = appendAffix(dst, f, suffix, d.Neg)
|
||||
return dst
|
||||
}
|
||||
|
||||
func appendAffix(dst []byte, f *Formatter, affix string, neg bool) []byte {
|
||||
quoting := false
|
||||
escaping := false
|
||||
for _, r := range affix {
|
||||
switch {
|
||||
case escaping:
|
||||
// escaping occurs both inside and outside of quotes
|
||||
dst = append(dst, string(r)...)
|
||||
escaping = false
|
||||
case r == '\\':
|
||||
escaping = true
|
||||
case r == '\'':
|
||||
quoting = !quoting
|
||||
case quoting:
|
||||
dst = append(dst, string(r)...)
|
||||
case r == '%':
|
||||
if f.DigitShift == 3 {
|
||||
dst = append(dst, f.Symbol(SymPerMille)...)
|
||||
} else {
|
||||
dst = append(dst, f.Symbol(SymPercentSign)...)
|
||||
}
|
||||
case r == '-' || r == '+':
|
||||
if neg {
|
||||
dst = append(dst, f.Symbol(SymMinusSign)...)
|
||||
} else if f.Flags&ElideSign == 0 {
|
||||
dst = append(dst, f.Symbol(SymPlusSign)...)
|
||||
} else {
|
||||
dst = append(dst, ' ')
|
||||
}
|
||||
default:
|
||||
dst = append(dst, string(r)...)
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
152
vendor/golang.org/x/text/internal/number/number.go
generated
vendored
152
vendor/golang.org/x/text/internal/number/number.go
generated
vendored
@ -1,152 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run gen.go gen_common.go
|
||||
|
||||
// Package number contains tools and data for formatting numbers.
|
||||
package number
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/internal/language/compact"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// Info holds number formatting configuration data.
|
||||
type Info struct {
|
||||
system systemData // numbering system information
|
||||
symIndex symOffset // index to symbols
|
||||
}
|
||||
|
||||
// InfoFromLangID returns a Info for the given compact language identifier and
|
||||
// numbering system identifier. If system is the empty string, the default
|
||||
// numbering system will be taken for that language.
|
||||
func InfoFromLangID(compactIndex compact.ID, numberSystem string) Info {
|
||||
p := langToDefaults[compactIndex]
|
||||
// Lookup the entry for the language.
|
||||
pSymIndex := symOffset(0) // Default: Latin, default symbols
|
||||
system, ok := systemMap[numberSystem]
|
||||
if !ok {
|
||||
// Take the value for the default numbering system. This is by far the
|
||||
// most common case as an alternative numbering system is hardly used.
|
||||
if p&hasNonLatnMask == 0 { // Latn digits.
|
||||
pSymIndex = p
|
||||
} else { // Non-Latn or multiple numbering systems.
|
||||
// Take the first entry from the alternatives list.
|
||||
data := langToAlt[p&^hasNonLatnMask]
|
||||
pSymIndex = data.symIndex
|
||||
system = data.system
|
||||
}
|
||||
} else {
|
||||
langIndex := compactIndex
|
||||
ns := system
|
||||
outerLoop:
|
||||
for ; ; p = langToDefaults[langIndex] {
|
||||
if p&hasNonLatnMask == 0 {
|
||||
if ns == 0 {
|
||||
// The index directly points to the symbol data.
|
||||
pSymIndex = p
|
||||
break
|
||||
}
|
||||
// Move to the parent and retry.
|
||||
langIndex = langIndex.Parent()
|
||||
} else {
|
||||
// The index points to a list of symbol data indexes.
|
||||
for _, e := range langToAlt[p&^hasNonLatnMask:] {
|
||||
if e.compactTag != langIndex {
|
||||
if langIndex == 0 {
|
||||
// The CLDR root defines full symbol information for
|
||||
// all numbering systems (even though mostly by
|
||||
// means of aliases). Fall back to the default entry
|
||||
// for Latn if there is no data for the numbering
|
||||
// system of this language.
|
||||
if ns == 0 {
|
||||
break
|
||||
}
|
||||
// Fall back to Latin and start from the original
|
||||
// language. See
|
||||
// https://unicode.org/reports/tr35/#Locale_Inheritance.
|
||||
ns = numLatn
|
||||
langIndex = compactIndex
|
||||
continue outerLoop
|
||||
}
|
||||
// Fall back to parent.
|
||||
langIndex = langIndex.Parent()
|
||||
} else if e.system == ns {
|
||||
pSymIndex = e.symIndex
|
||||
break outerLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if int(system) >= len(numSysData) { // algorithmic
|
||||
// Will generate ASCII digits in case the user inadvertently calls
|
||||
// WriteDigit or Digit on it.
|
||||
d := numSysData[0]
|
||||
d.id = system
|
||||
return Info{
|
||||
system: d,
|
||||
symIndex: pSymIndex,
|
||||
}
|
||||
}
|
||||
return Info{
|
||||
system: numSysData[system],
|
||||
symIndex: pSymIndex,
|
||||
}
|
||||
}
|
||||
|
||||
// InfoFromTag returns a Info for the given language tag.
|
||||
func InfoFromTag(t language.Tag) Info {
|
||||
return InfoFromLangID(tagToID(t), t.TypeForKey("nu"))
|
||||
}
|
||||
|
||||
// IsDecimal reports if the numbering system can convert decimal to native
|
||||
// symbols one-to-one.
|
||||
func (n Info) IsDecimal() bool {
|
||||
return int(n.system.id) < len(numSysData)
|
||||
}
|
||||
|
||||
// WriteDigit writes the UTF-8 sequence for n corresponding to the given ASCII
|
||||
// digit to dst and reports the number of bytes written. dst must be large
|
||||
// enough to hold the rune (can be up to utf8.UTFMax bytes).
|
||||
func (n Info) WriteDigit(dst []byte, asciiDigit rune) int {
|
||||
copy(dst, n.system.zero[:n.system.digitSize])
|
||||
dst[n.system.digitSize-1] += byte(asciiDigit - '0')
|
||||
return int(n.system.digitSize)
|
||||
}
|
||||
|
||||
// AppendDigit appends the UTF-8 sequence for n corresponding to the given digit
|
||||
// to dst and reports the number of bytes written. dst must be large enough to
|
||||
// hold the rune (can be up to utf8.UTFMax bytes).
|
||||
func (n Info) AppendDigit(dst []byte, digit byte) []byte {
|
||||
dst = append(dst, n.system.zero[:n.system.digitSize]...)
|
||||
dst[len(dst)-1] += digit
|
||||
return dst
|
||||
}
|
||||
|
||||
// Digit returns the digit for the numbering system for the corresponding ASCII
|
||||
// value. For example, ni.Digit('3') could return '三'. Note that the argument
|
||||
// is the rune constant '3', which equals 51, not the integer constant 3.
|
||||
func (n Info) Digit(asciiDigit rune) rune {
|
||||
var x [utf8.UTFMax]byte
|
||||
n.WriteDigit(x[:], asciiDigit)
|
||||
r, _ := utf8.DecodeRune(x[:])
|
||||
return r
|
||||
}
|
||||
|
||||
// Symbol returns the string for the given symbol type.
|
||||
func (n Info) Symbol(t SymbolType) string {
|
||||
return symData.Elem(int(symIndex[n.symIndex][t]))
|
||||
}
|
||||
|
||||
func formatForLang(t language.Tag, index []byte) *Pattern {
|
||||
return &formats[index[tagToID(t)]]
|
||||
}
|
||||
|
||||
func tagToID(t language.Tag) compact.ID {
|
||||
id, _ := compact.RegionalID(compact.Tag(t))
|
||||
return id
|
||||
}
|
485
vendor/golang.org/x/text/internal/number/pattern.go
generated
vendored
485
vendor/golang.org/x/text/internal/number/pattern.go
generated
vendored
@ -1,485 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package number
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// This file contains a parser for the CLDR number patterns as described in
|
||||
// https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns.
|
||||
//
|
||||
// The following BNF is derived from this standard.
|
||||
//
|
||||
// pattern := subpattern (';' subpattern)?
|
||||
// subpattern := affix? number exponent? affix?
|
||||
// number := decimal | sigDigits
|
||||
// decimal := '#'* '0'* ('.' fraction)? | '#' | '0'
|
||||
// fraction := '0'* '#'*
|
||||
// sigDigits := '#'* '@' '@'* '#'*
|
||||
// exponent := 'E' '+'? '0'* '0'
|
||||
// padSpec := '*' \L
|
||||
//
|
||||
// Notes:
|
||||
// - An affix pattern may contain any runes, but runes with special meaning
|
||||
// should be escaped.
|
||||
// - Sequences of digits, '#', and '@' in decimal and sigDigits may have
|
||||
// interstitial commas.
|
||||
|
||||
// TODO: replace special characters in affixes (-, +, ¤) with control codes.
|
||||
|
||||
// Pattern holds information for formatting numbers. It is designed to hold
|
||||
// information from CLDR number patterns.
|
||||
//
|
||||
// This pattern is precompiled for all patterns for all languages. Even though
|
||||
// the number of patterns is not very large, we want to keep this small.
|
||||
//
|
||||
// This type is only intended for internal use.
|
||||
type Pattern struct {
|
||||
RoundingContext
|
||||
|
||||
Affix string // includes prefix and suffix. First byte is prefix length.
|
||||
Offset uint16 // Offset into Affix for prefix and suffix
|
||||
NegOffset uint16 // Offset into Affix for negative prefix and suffix or 0.
|
||||
PadRune rune
|
||||
FormatWidth uint16
|
||||
|
||||
GroupingSize [2]uint8
|
||||
Flags PatternFlag
|
||||
}
|
||||
|
||||
// A RoundingContext indicates how a number should be converted to digits.
|
||||
// It contains all information needed to determine the "visible digits" as
|
||||
// required by the pluralization rules.
|
||||
type RoundingContext struct {
|
||||
// TODO: unify these two fields so that there is a more unambiguous meaning
|
||||
// of how precision is handled.
|
||||
MaxSignificantDigits int16 // -1 is unlimited
|
||||
MaxFractionDigits int16 // -1 is unlimited
|
||||
|
||||
Increment uint32
|
||||
IncrementScale uint8 // May differ from printed scale.
|
||||
|
||||
Mode RoundingMode
|
||||
|
||||
DigitShift uint8 // Number of decimals to shift. Used for % and ‰.
|
||||
|
||||
// Number of digits.
|
||||
MinIntegerDigits uint8
|
||||
|
||||
MaxIntegerDigits uint8
|
||||
MinFractionDigits uint8
|
||||
MinSignificantDigits uint8
|
||||
|
||||
MinExponentDigits uint8
|
||||
}
|
||||
|
||||
// RoundSignificantDigits returns the number of significant digits an
|
||||
// implementation of Convert may round to or n < 0 if there is no maximum or
|
||||
// a maximum is not recommended.
|
||||
func (r *RoundingContext) RoundSignificantDigits() (n int) {
|
||||
if r.MaxFractionDigits == 0 && r.MaxSignificantDigits > 0 {
|
||||
return int(r.MaxSignificantDigits)
|
||||
} else if r.isScientific() && r.MaxIntegerDigits == 1 {
|
||||
if r.MaxSignificantDigits == 0 ||
|
||||
int(r.MaxFractionDigits+1) == int(r.MaxSignificantDigits) {
|
||||
// Note: don't add DigitShift: it is only used for decimals.
|
||||
return int(r.MaxFractionDigits) + 1
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// RoundFractionDigits returns the number of fraction digits an implementation
|
||||
// of Convert may round to or n < 0 if there is no maximum or a maximum is not
|
||||
// recommended.
|
||||
func (r *RoundingContext) RoundFractionDigits() (n int) {
|
||||
if r.MinExponentDigits == 0 &&
|
||||
r.MaxSignificantDigits == 0 &&
|
||||
r.MaxFractionDigits >= 0 {
|
||||
return int(r.MaxFractionDigits) + int(r.DigitShift)
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// SetScale fixes the RoundingContext to a fixed number of fraction digits.
|
||||
func (r *RoundingContext) SetScale(scale int) {
|
||||
r.MinFractionDigits = uint8(scale)
|
||||
r.MaxFractionDigits = int16(scale)
|
||||
}
|
||||
|
||||
func (r *RoundingContext) SetPrecision(prec int) {
|
||||
r.MaxSignificantDigits = int16(prec)
|
||||
}
|
||||
|
||||
func (r *RoundingContext) isScientific() bool {
|
||||
return r.MinExponentDigits > 0
|
||||
}
|
||||
|
||||
func (f *Pattern) needsSep(pos int) bool {
|
||||
p := pos - 1
|
||||
size := int(f.GroupingSize[0])
|
||||
if size == 0 || p == 0 {
|
||||
return false
|
||||
}
|
||||
if p == size {
|
||||
return true
|
||||
}
|
||||
if p -= size; p < 0 {
|
||||
return false
|
||||
}
|
||||
// TODO: make second groupingsize the same as first if 0 so that we can
|
||||
// avoid this check.
|
||||
if x := int(f.GroupingSize[1]); x != 0 {
|
||||
size = x
|
||||
}
|
||||
return p%size == 0
|
||||
}
|
||||
|
||||
// A PatternFlag is a bit mask for the flag field of a Pattern.
|
||||
type PatternFlag uint8
|
||||
|
||||
const (
|
||||
AlwaysSign PatternFlag = 1 << iota
|
||||
ElideSign // Use space instead of plus sign. AlwaysSign must be true.
|
||||
AlwaysExpSign
|
||||
AlwaysDecimalSeparator
|
||||
ParenthesisForNegative // Common pattern. Saves space.
|
||||
|
||||
PadAfterNumber
|
||||
PadAfterAffix
|
||||
|
||||
PadBeforePrefix = 0 // Default
|
||||
PadAfterPrefix = PadAfterAffix
|
||||
PadBeforeSuffix = PadAfterNumber
|
||||
PadAfterSuffix = PadAfterNumber | PadAfterAffix
|
||||
PadMask = PadAfterNumber | PadAfterAffix
|
||||
)
|
||||
|
||||
type parser struct {
|
||||
*Pattern
|
||||
|
||||
leadingSharps int
|
||||
|
||||
pos int
|
||||
err error
|
||||
doNotTerminate bool
|
||||
groupingCount uint
|
||||
hasGroup bool
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func (p *parser) setError(err error) {
|
||||
if p.err == nil {
|
||||
p.err = err
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parser) updateGrouping() {
|
||||
if p.hasGroup &&
|
||||
0 < p.groupingCount && p.groupingCount < 255 {
|
||||
p.GroupingSize[1] = p.GroupingSize[0]
|
||||
p.GroupingSize[0] = uint8(p.groupingCount)
|
||||
}
|
||||
p.groupingCount = 0
|
||||
p.hasGroup = true
|
||||
}
|
||||
|
||||
var (
|
||||
// TODO: more sensible and localizeable error messages.
|
||||
errMultiplePadSpecifiers = errors.New("format: pattern has multiple pad specifiers")
|
||||
errInvalidPadSpecifier = errors.New("format: invalid pad specifier")
|
||||
errInvalidQuote = errors.New("format: invalid quote")
|
||||
errAffixTooLarge = errors.New("format: prefix or suffix exceeds maximum UTF-8 length of 256 bytes")
|
||||
errDuplicatePercentSign = errors.New("format: duplicate percent sign")
|
||||
errDuplicatePermilleSign = errors.New("format: duplicate permille sign")
|
||||
errUnexpectedEnd = errors.New("format: unexpected end of pattern")
|
||||
)
|
||||
|
||||
// ParsePattern extracts formatting information from a CLDR number pattern.
|
||||
//
|
||||
// See https://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns.
|
||||
func ParsePattern(s string) (f *Pattern, err error) {
|
||||
p := parser{Pattern: &Pattern{}}
|
||||
|
||||
s = p.parseSubPattern(s)
|
||||
|
||||
if s != "" {
|
||||
// Parse negative sub pattern.
|
||||
if s[0] != ';' {
|
||||
p.setError(errors.New("format: error parsing first sub pattern"))
|
||||
return nil, p.err
|
||||
}
|
||||
neg := parser{Pattern: &Pattern{}} // just for extracting the affixes.
|
||||
s = neg.parseSubPattern(s[len(";"):])
|
||||
p.NegOffset = uint16(len(p.buf))
|
||||
p.buf = append(p.buf, neg.buf...)
|
||||
}
|
||||
if s != "" {
|
||||
p.setError(errors.New("format: spurious characters at end of pattern"))
|
||||
}
|
||||
if p.err != nil {
|
||||
return nil, p.err
|
||||
}
|
||||
if affix := string(p.buf); affix == "\x00\x00" || affix == "\x00\x00\x00\x00" {
|
||||
// No prefix or suffixes.
|
||||
p.NegOffset = 0
|
||||
} else {
|
||||
p.Affix = affix
|
||||
}
|
||||
if p.Increment == 0 {
|
||||
p.IncrementScale = 0
|
||||
}
|
||||
return p.Pattern, nil
|
||||
}
|
||||
|
||||
func (p *parser) parseSubPattern(s string) string {
|
||||
s = p.parsePad(s, PadBeforePrefix)
|
||||
s = p.parseAffix(s)
|
||||
s = p.parsePad(s, PadAfterPrefix)
|
||||
|
||||
s = p.parse(p.number, s)
|
||||
p.updateGrouping()
|
||||
|
||||
s = p.parsePad(s, PadBeforeSuffix)
|
||||
s = p.parseAffix(s)
|
||||
s = p.parsePad(s, PadAfterSuffix)
|
||||
return s
|
||||
}
|
||||
|
||||
func (p *parser) parsePad(s string, f PatternFlag) (tail string) {
|
||||
if len(s) >= 2 && s[0] == '*' {
|
||||
r, sz := utf8.DecodeRuneInString(s[1:])
|
||||
if p.PadRune != 0 {
|
||||
p.err = errMultiplePadSpecifiers
|
||||
} else {
|
||||
p.Flags |= f
|
||||
p.PadRune = r
|
||||
}
|
||||
return s[1+sz:]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (p *parser) parseAffix(s string) string {
|
||||
x := len(p.buf)
|
||||
p.buf = append(p.buf, 0) // placeholder for affix length
|
||||
|
||||
s = p.parse(p.affix, s)
|
||||
|
||||
n := len(p.buf) - x - 1
|
||||
if n > 0xFF {
|
||||
p.setError(errAffixTooLarge)
|
||||
}
|
||||
p.buf[x] = uint8(n)
|
||||
return s
|
||||
}
|
||||
|
||||
// state implements a state transition. It returns the new state. A state
|
||||
// function may set an error on the parser or may simply return on an incorrect
|
||||
// token and let the next phase fail.
|
||||
type state func(r rune) state
|
||||
|
||||
// parse repeatedly applies a state function on the given string until a
|
||||
// termination condition is reached.
|
||||
func (p *parser) parse(fn state, s string) (tail string) {
|
||||
for i, r := range s {
|
||||
p.doNotTerminate = false
|
||||
if fn = fn(r); fn == nil || p.err != nil {
|
||||
return s[i:]
|
||||
}
|
||||
p.FormatWidth++
|
||||
}
|
||||
if p.doNotTerminate {
|
||||
p.setError(errUnexpectedEnd)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p *parser) affix(r rune) state {
|
||||
switch r {
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'#', '@', '.', '*', ',', ';':
|
||||
return nil
|
||||
case '\'':
|
||||
p.FormatWidth--
|
||||
return p.escapeFirst
|
||||
case '%':
|
||||
if p.DigitShift != 0 {
|
||||
p.setError(errDuplicatePercentSign)
|
||||
}
|
||||
p.DigitShift = 2
|
||||
case '\u2030': // ‰ Per mille
|
||||
if p.DigitShift != 0 {
|
||||
p.setError(errDuplicatePermilleSign)
|
||||
}
|
||||
p.DigitShift = 3
|
||||
// TODO: handle currency somehow: ¤, ¤¤, ¤¤¤, ¤¤¤¤
|
||||
}
|
||||
p.buf = append(p.buf, string(r)...)
|
||||
return p.affix
|
||||
}
|
||||
|
||||
func (p *parser) escapeFirst(r rune) state {
|
||||
switch r {
|
||||
case '\'':
|
||||
p.buf = append(p.buf, "\\'"...)
|
||||
return p.affix
|
||||
default:
|
||||
p.buf = append(p.buf, '\'')
|
||||
p.buf = append(p.buf, string(r)...)
|
||||
}
|
||||
return p.escape
|
||||
}
|
||||
|
||||
func (p *parser) escape(r rune) state {
|
||||
switch r {
|
||||
case '\'':
|
||||
p.FormatWidth--
|
||||
p.buf = append(p.buf, '\'')
|
||||
return p.affix
|
||||
default:
|
||||
p.buf = append(p.buf, string(r)...)
|
||||
}
|
||||
return p.escape
|
||||
}
|
||||
|
||||
// number parses a number. The BNF says the integer part should always have
|
||||
// a '0', but that does not appear to be the case according to the rest of the
|
||||
// documentation. We will allow having only '#' numbers.
|
||||
func (p *parser) number(r rune) state {
|
||||
switch r {
|
||||
case '#':
|
||||
p.groupingCount++
|
||||
p.leadingSharps++
|
||||
case '@':
|
||||
p.groupingCount++
|
||||
p.leadingSharps = 0
|
||||
p.MaxFractionDigits = -1
|
||||
return p.sigDigits(r)
|
||||
case ',':
|
||||
if p.leadingSharps == 0 { // no leading commas
|
||||
return nil
|
||||
}
|
||||
p.updateGrouping()
|
||||
case 'E':
|
||||
p.MaxIntegerDigits = uint8(p.leadingSharps)
|
||||
return p.exponent
|
||||
case '.': // allow ".##" etc.
|
||||
p.updateGrouping()
|
||||
return p.fraction
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
return p.integer(r)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
return p.number
|
||||
}
|
||||
|
||||
func (p *parser) integer(r rune) state {
|
||||
if !('0' <= r && r <= '9') {
|
||||
var next state
|
||||
switch r {
|
||||
case 'E':
|
||||
if p.leadingSharps > 0 {
|
||||
p.MaxIntegerDigits = uint8(p.leadingSharps) + p.MinIntegerDigits
|
||||
}
|
||||
next = p.exponent
|
||||
case '.':
|
||||
next = p.fraction
|
||||
case ',':
|
||||
next = p.integer
|
||||
}
|
||||
p.updateGrouping()
|
||||
return next
|
||||
}
|
||||
p.Increment = p.Increment*10 + uint32(r-'0')
|
||||
p.groupingCount++
|
||||
p.MinIntegerDigits++
|
||||
return p.integer
|
||||
}
|
||||
|
||||
func (p *parser) sigDigits(r rune) state {
|
||||
switch r {
|
||||
case '@':
|
||||
p.groupingCount++
|
||||
p.MaxSignificantDigits++
|
||||
p.MinSignificantDigits++
|
||||
case '#':
|
||||
return p.sigDigitsFinal(r)
|
||||
case 'E':
|
||||
p.updateGrouping()
|
||||
return p.normalizeSigDigitsWithExponent()
|
||||
default:
|
||||
p.updateGrouping()
|
||||
return nil
|
||||
}
|
||||
return p.sigDigits
|
||||
}
|
||||
|
||||
func (p *parser) sigDigitsFinal(r rune) state {
|
||||
switch r {
|
||||
case '#':
|
||||
p.groupingCount++
|
||||
p.MaxSignificantDigits++
|
||||
case 'E':
|
||||
p.updateGrouping()
|
||||
return p.normalizeSigDigitsWithExponent()
|
||||
default:
|
||||
p.updateGrouping()
|
||||
return nil
|
||||
}
|
||||
return p.sigDigitsFinal
|
||||
}
|
||||
|
||||
func (p *parser) normalizeSigDigitsWithExponent() state {
|
||||
p.MinIntegerDigits, p.MaxIntegerDigits = 1, 1
|
||||
p.MinFractionDigits = p.MinSignificantDigits - 1
|
||||
p.MaxFractionDigits = p.MaxSignificantDigits - 1
|
||||
p.MinSignificantDigits, p.MaxSignificantDigits = 0, 0
|
||||
return p.exponent
|
||||
}
|
||||
|
||||
func (p *parser) fraction(r rune) state {
|
||||
switch r {
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
p.Increment = p.Increment*10 + uint32(r-'0')
|
||||
p.IncrementScale++
|
||||
p.MinFractionDigits++
|
||||
p.MaxFractionDigits++
|
||||
case '#':
|
||||
p.MaxFractionDigits++
|
||||
case 'E':
|
||||
if p.leadingSharps > 0 {
|
||||
p.MaxIntegerDigits = uint8(p.leadingSharps) + p.MinIntegerDigits
|
||||
}
|
||||
return p.exponent
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
return p.fraction
|
||||
}
|
||||
|
||||
func (p *parser) exponent(r rune) state {
|
||||
switch r {
|
||||
case '+':
|
||||
// Set mode and check it wasn't already set.
|
||||
if p.Flags&AlwaysExpSign != 0 || p.MinExponentDigits > 0 {
|
||||
break
|
||||
}
|
||||
p.Flags |= AlwaysExpSign
|
||||
p.doNotTerminate = true
|
||||
return p.exponent
|
||||
case '0':
|
||||
p.MinExponentDigits++
|
||||
return p.exponent
|
||||
}
|
||||
// termination condition
|
||||
if p.MinExponentDigits == 0 {
|
||||
p.setError(errors.New("format: need at least one digit"))
|
||||
}
|
||||
return nil
|
||||
}
|
30
vendor/golang.org/x/text/internal/number/roundingmode_string.go
generated
vendored
30
vendor/golang.org/x/text/internal/number/roundingmode_string.go
generated
vendored
@ -1,30 +0,0 @@
|
||||
// Code generated by "stringer -type RoundingMode"; DO NOT EDIT.
|
||||
|
||||
package number
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[ToNearestEven-0]
|
||||
_ = x[ToNearestZero-1]
|
||||
_ = x[ToNearestAway-2]
|
||||
_ = x[ToPositiveInf-3]
|
||||
_ = x[ToNegativeInf-4]
|
||||
_ = x[ToZero-5]
|
||||
_ = x[AwayFromZero-6]
|
||||
_ = x[numModes-7]
|
||||
}
|
||||
|
||||
const _RoundingMode_name = "ToNearestEvenToNearestZeroToNearestAwayToPositiveInfToNegativeInfToZeroAwayFromZeronumModes"
|
||||
|
||||
var _RoundingMode_index = [...]uint8{0, 13, 26, 39, 52, 65, 71, 83, 91}
|
||||
|
||||
func (i RoundingMode) String() string {
|
||||
if i >= RoundingMode(len(_RoundingMode_index)-1) {
|
||||
return "RoundingMode(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _RoundingMode_name[_RoundingMode_index[i]:_RoundingMode_index[i+1]]
|
||||
}
|
1219
vendor/golang.org/x/text/internal/number/tables.go
generated
vendored
1219
vendor/golang.org/x/text/internal/number/tables.go
generated
vendored
File diff suppressed because it is too large
Load Diff
86
vendor/golang.org/x/text/internal/stringset/set.go
generated
vendored
86
vendor/golang.org/x/text/internal/stringset/set.go
generated
vendored
@ -1,86 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package stringset provides a way to represent a collection of strings
|
||||
// compactly.
|
||||
package stringset
|
||||
|
||||
import "sort"
|
||||
|
||||
// A Set holds a collection of strings that can be looked up by an index number.
|
||||
type Set struct {
|
||||
// These fields are exported to allow for code generation.
|
||||
|
||||
Data string
|
||||
Index []uint16
|
||||
}
|
||||
|
||||
// Elem returns the string with index i. It panics if i is out of range.
|
||||
func (s *Set) Elem(i int) string {
|
||||
return s.Data[s.Index[i]:s.Index[i+1]]
|
||||
}
|
||||
|
||||
// Len returns the number of strings in the set.
|
||||
func (s *Set) Len() int {
|
||||
return len(s.Index) - 1
|
||||
}
|
||||
|
||||
// Search returns the index of the given string or -1 if it is not in the set.
|
||||
// The Set must have been created with strings in sorted order.
|
||||
func Search(s *Set, str string) int {
|
||||
// TODO: optimize this if it gets used a lot.
|
||||
n := len(s.Index) - 1
|
||||
p := sort.Search(n, func(i int) bool {
|
||||
return s.Elem(i) >= str
|
||||
})
|
||||
if p == n || str != s.Elem(p) {
|
||||
return -1
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// A Builder constructs Sets.
|
||||
type Builder struct {
|
||||
set Set
|
||||
index map[string]int
|
||||
}
|
||||
|
||||
// NewBuilder returns a new and initialized Builder.
|
||||
func NewBuilder() *Builder {
|
||||
return &Builder{
|
||||
set: Set{
|
||||
Index: []uint16{0},
|
||||
},
|
||||
index: map[string]int{},
|
||||
}
|
||||
}
|
||||
|
||||
// Set creates the set created so far.
|
||||
func (b *Builder) Set() Set {
|
||||
return b.set
|
||||
}
|
||||
|
||||
// Index returns the index for the given string, which must have been added
|
||||
// before.
|
||||
func (b *Builder) Index(s string) int {
|
||||
return b.index[s]
|
||||
}
|
||||
|
||||
// Add adds a string to the index. Strings that are added by a single Add will
|
||||
// be stored together, unless they match an existing string.
|
||||
func (b *Builder) Add(ss ...string) {
|
||||
// First check if the string already exists.
|
||||
for _, s := range ss {
|
||||
if _, ok := b.index[s]; ok {
|
||||
continue
|
||||
}
|
||||
b.index[s] = len(b.set.Index) - 1
|
||||
b.set.Data += s
|
||||
x := len(b.set.Data)
|
||||
if x > 0xFFFF {
|
||||
panic("Index too > 0xFFFF")
|
||||
}
|
||||
b.set.Index = append(b.set.Index, uint16(x))
|
||||
}
|
||||
}
|
87
vendor/golang.org/x/text/internal/utf8internal/utf8internal.go
generated
vendored
87
vendor/golang.org/x/text/internal/utf8internal/utf8internal.go
generated
vendored
@ -1,87 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package utf8internal contains low-level utf8-related constants, tables, etc.
|
||||
// that are used internally by the text package.
|
||||
package utf8internal
|
||||
|
||||
// The default lowest and highest continuation byte.
|
||||
const (
|
||||
LoCB = 0x80 // 1000 0000
|
||||
HiCB = 0xBF // 1011 1111
|
||||
)
|
||||
|
||||
// Constants related to getting information of first bytes of UTF-8 sequences.
|
||||
const (
|
||||
// ASCII identifies a UTF-8 byte as ASCII.
|
||||
ASCII = as
|
||||
|
||||
// FirstInvalid indicates a byte is invalid as a first byte of a UTF-8
|
||||
// sequence.
|
||||
FirstInvalid = xx
|
||||
|
||||
// SizeMask is a mask for the size bits. Use use x&SizeMask to get the size.
|
||||
SizeMask = 7
|
||||
|
||||
// AcceptShift is the right-shift count for the first byte info byte to get
|
||||
// the index into the AcceptRanges table. See AcceptRanges.
|
||||
AcceptShift = 4
|
||||
|
||||
// The names of these constants are chosen to give nice alignment in the
|
||||
// table below. The first nibble is an index into acceptRanges or F for
|
||||
// special one-byte cases. The second nibble is the Rune length or the
|
||||
// Status for the special one-byte case.
|
||||
xx = 0xF1 // invalid: size 1
|
||||
as = 0xF0 // ASCII: size 1
|
||||
s1 = 0x02 // accept 0, size 2
|
||||
s2 = 0x13 // accept 1, size 3
|
||||
s3 = 0x03 // accept 0, size 3
|
||||
s4 = 0x23 // accept 2, size 3
|
||||
s5 = 0x34 // accept 3, size 4
|
||||
s6 = 0x04 // accept 0, size 4
|
||||
s7 = 0x44 // accept 4, size 4
|
||||
)
|
||||
|
||||
// First is information about the first byte in a UTF-8 sequence.
|
||||
var First = [256]uint8{
|
||||
// 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x00-0x0F
|
||||
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x10-0x1F
|
||||
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x20-0x2F
|
||||
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x30-0x3F
|
||||
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x40-0x4F
|
||||
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x50-0x5F
|
||||
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x60-0x6F
|
||||
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x70-0x7F
|
||||
// 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x80-0x8F
|
||||
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x90-0x9F
|
||||
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xA0-0xAF
|
||||
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xB0-0xBF
|
||||
xx, xx, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xC0-0xCF
|
||||
s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xD0-0xDF
|
||||
s2, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s4, s3, s3, // 0xE0-0xEF
|
||||
s5, s6, s6, s6, s7, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xF0-0xFF
|
||||
}
|
||||
|
||||
// AcceptRange gives the range of valid values for the second byte in a UTF-8
|
||||
// sequence for any value for First that is not ASCII or FirstInvalid.
|
||||
type AcceptRange struct {
|
||||
Lo uint8 // lowest value for second byte.
|
||||
Hi uint8 // highest value for second byte.
|
||||
}
|
||||
|
||||
// AcceptRanges is a slice of AcceptRange values. For a given byte sequence b
|
||||
//
|
||||
// AcceptRanges[First[b[0]]>>AcceptShift]
|
||||
//
|
||||
// will give the value of AcceptRange for the multi-byte UTF-8 sequence starting
|
||||
// at b[0].
|
||||
var AcceptRanges = [...]AcceptRange{
|
||||
0: {LoCB, HiCB},
|
||||
1: {0xA0, HiCB},
|
||||
2: {LoCB, 0x9F},
|
||||
3: {0x90, HiCB},
|
||||
4: {LoCB, 0x8F},
|
||||
}
|
36
vendor/golang.org/x/text/message/catalog.go
generated
vendored
36
vendor/golang.org/x/text/message/catalog.go
generated
vendored
@ -1,36 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package message
|
||||
|
||||
// TODO: some types in this file will need to be made public at some time.
|
||||
// Documentation and method names will reflect this by using the exported name.
|
||||
|
||||
import (
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message/catalog"
|
||||
)
|
||||
|
||||
// MatchLanguage reports the matched tag obtained from language.MatchStrings for
|
||||
// the Matcher of the DefaultCatalog.
|
||||
func MatchLanguage(preferred ...string) language.Tag {
|
||||
c := DefaultCatalog
|
||||
tag, _ := language.MatchStrings(c.Matcher(), preferred...)
|
||||
return tag
|
||||
}
|
||||
|
||||
// DefaultCatalog is used by SetString.
|
||||
var DefaultCatalog catalog.Catalog = defaultCatalog
|
||||
|
||||
var defaultCatalog = catalog.NewBuilder()
|
||||
|
||||
// SetString calls SetString on the initial default Catalog.
|
||||
func SetString(tag language.Tag, key string, msg string) error {
|
||||
return defaultCatalog.SetString(tag, key, msg)
|
||||
}
|
||||
|
||||
// Set calls Set on the initial default Catalog.
|
||||
func Set(tag language.Tag, key string, msg ...catalog.Message) error {
|
||||
return defaultCatalog.Set(tag, key, msg...)
|
||||
}
|
365
vendor/golang.org/x/text/message/catalog/catalog.go
generated
vendored
365
vendor/golang.org/x/text/message/catalog/catalog.go
generated
vendored
@ -1,365 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package catalog defines collections of translated format strings.
|
||||
//
|
||||
// This package mostly defines types for populating catalogs with messages. The
|
||||
// catmsg package contains further definitions for creating custom message and
|
||||
// dictionary types as well as packages that use Catalogs.
|
||||
//
|
||||
// Package catalog defines various interfaces: Dictionary, Loader, and Message.
|
||||
// A Dictionary maintains a set of translations of format strings for a single
|
||||
// language. The Loader interface defines a source of dictionaries. A
|
||||
// translation of a format string is represented by a Message.
|
||||
//
|
||||
// # Catalogs
|
||||
//
|
||||
// A Catalog defines a programmatic interface for setting message translations.
|
||||
// It maintains a set of per-language dictionaries with translations for a set
|
||||
// of keys. For message translation to function properly, a translation should
|
||||
// be defined for each key for each supported language. A dictionary may be
|
||||
// underspecified, though, if there is a parent language that already defines
|
||||
// the key. For example, a Dictionary for "en-GB" could leave out entries that
|
||||
// are identical to those in a dictionary for "en".
|
||||
//
|
||||
// # Messages
|
||||
//
|
||||
// A Message is a format string which varies on the value of substitution
|
||||
// variables. For instance, to indicate the number of results one could want "no
|
||||
// results" if there are none, "1 result" if there is 1, and "%d results" for
|
||||
// any other number. Catalog is agnostic to the kind of format strings that are
|
||||
// used: for instance, messages can follow either the printf-style substitution
|
||||
// from package fmt or use templates.
|
||||
//
|
||||
// A Message does not substitute arguments in the format string. This job is
|
||||
// reserved for packages that render strings, such as message, that use Catalogs
|
||||
// to selected string. This separation of concerns allows Catalog to be used to
|
||||
// store any kind of formatting strings.
|
||||
//
|
||||
// # Selecting messages based on linguistic features of substitution arguments
|
||||
//
|
||||
// Messages may vary based on any linguistic features of the argument values.
|
||||
// The most common one is plural form, but others exist.
|
||||
//
|
||||
// Selection messages are provided in packages that provide support for a
|
||||
// specific linguistic feature. The following snippet uses plural.Selectf:
|
||||
//
|
||||
// catalog.Set(language.English, "You are %d minute(s) late.",
|
||||
// plural.Selectf(1, "",
|
||||
// plural.One, "You are 1 minute late.",
|
||||
// plural.Other, "You are %d minutes late."))
|
||||
//
|
||||
// In this example, a message is stored in the Catalog where one of two messages
|
||||
// is selected based on the first argument, a number. The first message is
|
||||
// selected if the argument is singular (identified by the selector "one") and
|
||||
// the second message is selected in all other cases. The selectors are defined
|
||||
// by the plural rules defined in CLDR. The selector "other" is special and will
|
||||
// always match. Each language always defines one of the linguistic categories
|
||||
// to be "other." For English, singular is "one" and plural is "other".
|
||||
//
|
||||
// Selects can be nested. This allows selecting sentences based on features of
|
||||
// multiple arguments or multiple linguistic properties of a single argument.
|
||||
//
|
||||
// # String interpolation
|
||||
//
|
||||
// There is often a lot of commonality between the possible variants of a
|
||||
// message. For instance, in the example above the word "minute" varies based on
|
||||
// the plural catogory of the argument, but the rest of the sentence is
|
||||
// identical. Using interpolation the above message can be rewritten as:
|
||||
//
|
||||
// catalog.Set(language.English, "You are %d minute(s) late.",
|
||||
// catalog.Var("minutes",
|
||||
// plural.Selectf(1, "", plural.One, "minute", plural.Other, "minutes")),
|
||||
// catalog.String("You are %[1]d ${minutes} late."))
|
||||
//
|
||||
// Var is defined to return the variable name if the message does not yield a
|
||||
// match. This allows us to further simplify this snippet to
|
||||
//
|
||||
// catalog.Set(language.English, "You are %d minute(s) late.",
|
||||
// catalog.Var("minutes", plural.Selectf(1, "", plural.One, "minute")),
|
||||
// catalog.String("You are %d ${minutes} late."))
|
||||
//
|
||||
// Overall this is still only a minor improvement, but things can get a lot more
|
||||
// unwieldy if more than one linguistic feature is used to determine a message
|
||||
// variant. Consider the following example:
|
||||
//
|
||||
// // argument 1: list of hosts, argument 2: list of guests
|
||||
// catalog.Set(language.English, "%[1]v invite(s) %[2]v to their party.",
|
||||
// catalog.Var("their",
|
||||
// plural.Selectf(1, ""
|
||||
// plural.One, gender.Select(1, "female", "her", "other", "his"))),
|
||||
// catalog.Var("invites", plural.Selectf(1, "", plural.One, "invite"))
|
||||
// catalog.String("%[1]v ${invites} %[2]v to ${their} party.")),
|
||||
//
|
||||
// Without variable substitution, this would have to be written as
|
||||
//
|
||||
// // argument 1: list of hosts, argument 2: list of guests
|
||||
// catalog.Set(language.English, "%[1]v invite(s) %[2]v to their party.",
|
||||
// plural.Selectf(1, "",
|
||||
// plural.One, gender.Select(1,
|
||||
// "female", "%[1]v invites %[2]v to her party."
|
||||
// "other", "%[1]v invites %[2]v to his party."),
|
||||
// plural.Other, "%[1]v invites %[2]v to their party."))
|
||||
//
|
||||
// Not necessarily shorter, but using variables there is less duplication and
|
||||
// the messages are more maintenance friendly. Moreover, languages may have up
|
||||
// to six plural forms. This makes the use of variables more welcome.
|
||||
//
|
||||
// Different messages using the same inflections can reuse variables by moving
|
||||
// them to macros. Using macros we can rewrite the message as:
|
||||
//
|
||||
// // argument 1: list of hosts, argument 2: list of guests
|
||||
// catalog.SetString(language.English, "%[1]v invite(s) %[2]v to their party.",
|
||||
// "%[1]v ${invites(1)} %[2]v to ${their(1)} party.")
|
||||
//
|
||||
// Where the following macros were defined separately.
|
||||
//
|
||||
// catalog.SetMacro(language.English, "invites", plural.Selectf(1, "",
|
||||
// plural.One, "invite"))
|
||||
// catalog.SetMacro(language.English, "their", plural.Selectf(1, "",
|
||||
// plural.One, gender.Select(1, "female", "her", "other", "his"))),
|
||||
//
|
||||
// Placeholders use parentheses and the arguments to invoke a macro.
|
||||
//
|
||||
// # Looking up messages
|
||||
//
|
||||
// Message lookup using Catalogs is typically only done by specialized packages
|
||||
// and is not something the user should be concerned with. For instance, to
|
||||
// express the tardiness of a user using the related message we defined earlier,
|
||||
// the user may use the package message like so:
|
||||
//
|
||||
// p := message.NewPrinter(language.English)
|
||||
// p.Printf("You are %d minute(s) late.", 5)
|
||||
//
|
||||
// Which would print:
|
||||
//
|
||||
// You are 5 minutes late.
|
||||
//
|
||||
// This package is UNDER CONSTRUCTION and its API may change.
|
||||
package catalog // import "golang.org/x/text/message/catalog"
|
||||
|
||||
// TODO:
|
||||
// Some way to freeze a catalog.
|
||||
// - Locking on each lockup turns out to be about 50% of the total running time
|
||||
// for some of the benchmarks in the message package.
|
||||
// Consider these:
|
||||
// - Sequence type to support sequences in user-defined messages.
|
||||
// - Garbage collection: Remove dictionaries that can no longer be reached
|
||||
// as other dictionaries have been added that cover all possible keys.
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/text/internal"
|
||||
|
||||
"golang.org/x/text/internal/catmsg"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// A Catalog allows lookup of translated messages.
|
||||
type Catalog interface {
|
||||
// Languages returns all languages for which the Catalog contains variants.
|
||||
Languages() []language.Tag
|
||||
|
||||
// Matcher returns a Matcher for languages from this Catalog.
|
||||
Matcher() language.Matcher
|
||||
|
||||
// A Context is used for evaluating Messages.
|
||||
Context(tag language.Tag, r catmsg.Renderer) *Context
|
||||
|
||||
// This method also makes Catalog a private interface.
|
||||
lookup(tag language.Tag, key string) (data string, ok bool)
|
||||
}
|
||||
|
||||
// NewFromMap creates a Catalog from the given map. If a Dictionary is
|
||||
// underspecified the entry is retrieved from a parent language.
|
||||
func NewFromMap(dictionaries map[string]Dictionary, opts ...Option) (Catalog, error) {
|
||||
options := options{}
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
c := &catalog{
|
||||
dicts: map[language.Tag]Dictionary{},
|
||||
}
|
||||
_, hasFallback := dictionaries[options.fallback.String()]
|
||||
if hasFallback {
|
||||
// TODO: Should it be okay to not have a fallback language?
|
||||
// Catalog generators could enforce there is always a fallback.
|
||||
c.langs = append(c.langs, options.fallback)
|
||||
}
|
||||
for lang, dict := range dictionaries {
|
||||
tag, err := language.Parse(lang)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("catalog: invalid language tag %q", lang)
|
||||
}
|
||||
if _, ok := c.dicts[tag]; ok {
|
||||
return nil, fmt.Errorf("catalog: duplicate entry for tag %q after normalization", tag)
|
||||
}
|
||||
c.dicts[tag] = dict
|
||||
if !hasFallback || tag != options.fallback {
|
||||
c.langs = append(c.langs, tag)
|
||||
}
|
||||
}
|
||||
if hasFallback {
|
||||
internal.SortTags(c.langs[1:])
|
||||
} else {
|
||||
internal.SortTags(c.langs)
|
||||
}
|
||||
c.matcher = language.NewMatcher(c.langs)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// A Dictionary is a source of translations for a single language.
|
||||
type Dictionary interface {
|
||||
// Lookup returns a message compiled with catmsg.Compile for the given key.
|
||||
// It returns false for ok if such a message could not be found.
|
||||
Lookup(key string) (data string, ok bool)
|
||||
}
|
||||
|
||||
type catalog struct {
|
||||
langs []language.Tag
|
||||
dicts map[language.Tag]Dictionary
|
||||
macros store
|
||||
matcher language.Matcher
|
||||
}
|
||||
|
||||
func (c *catalog) Languages() []language.Tag { return c.langs }
|
||||
func (c *catalog) Matcher() language.Matcher { return c.matcher }
|
||||
|
||||
func (c *catalog) lookup(tag language.Tag, key string) (data string, ok bool) {
|
||||
for ; ; tag = tag.Parent() {
|
||||
if dict, ok := c.dicts[tag]; ok {
|
||||
if data, ok := dict.Lookup(key); ok {
|
||||
return data, true
|
||||
}
|
||||
}
|
||||
if tag == language.Und {
|
||||
break
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// Context returns a Context for formatting messages.
|
||||
// Only one Message may be formatted per context at any given time.
|
||||
func (c *catalog) Context(tag language.Tag, r catmsg.Renderer) *Context {
|
||||
return &Context{
|
||||
cat: c,
|
||||
tag: tag,
|
||||
dec: catmsg.NewDecoder(tag, r, &dict{&c.macros, tag}),
|
||||
}
|
||||
}
|
||||
|
||||
// A Builder allows building a Catalog programmatically.
|
||||
type Builder struct {
|
||||
options
|
||||
matcher language.Matcher
|
||||
|
||||
index store
|
||||
macros store
|
||||
}
|
||||
|
||||
type options struct {
|
||||
fallback language.Tag
|
||||
}
|
||||
|
||||
// An Option configures Catalog behavior.
|
||||
type Option func(*options)
|
||||
|
||||
// Fallback specifies the default fallback language. The default is Und.
|
||||
func Fallback(tag language.Tag) Option {
|
||||
return func(o *options) { o.fallback = tag }
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// // Catalogs specifies one or more sources for a Catalog.
|
||||
// // Lookups are in order.
|
||||
// // This can be changed inserting a Catalog used for setting, which implements
|
||||
// // Loader, used for setting in the chain.
|
||||
// func Catalogs(d ...Loader) Option {
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// func Delims(start, end string) Option {}
|
||||
//
|
||||
// func Dict(tag language.Tag, d ...Dictionary) Option
|
||||
|
||||
// NewBuilder returns an empty mutable Catalog.
|
||||
func NewBuilder(opts ...Option) *Builder {
|
||||
c := &Builder{}
|
||||
for _, o := range opts {
|
||||
o(&c.options)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// SetString is shorthand for Set(tag, key, String(msg)).
|
||||
func (c *Builder) SetString(tag language.Tag, key string, msg string) error {
|
||||
return c.set(tag, key, &c.index, String(msg))
|
||||
}
|
||||
|
||||
// Set sets the translation for the given language and key.
|
||||
//
|
||||
// When evaluation this message, the first Message in the sequence to msgs to
|
||||
// evaluate to a string will be the message returned.
|
||||
func (c *Builder) Set(tag language.Tag, key string, msg ...Message) error {
|
||||
return c.set(tag, key, &c.index, msg...)
|
||||
}
|
||||
|
||||
// SetMacro defines a Message that may be substituted in another message.
|
||||
// The arguments to a macro Message are passed as arguments in the
|
||||
// placeholder the form "${foo(arg1, arg2)}".
|
||||
func (c *Builder) SetMacro(tag language.Tag, name string, msg ...Message) error {
|
||||
return c.set(tag, name, &c.macros, msg...)
|
||||
}
|
||||
|
||||
// ErrNotFound indicates there was no message for the given key.
|
||||
var ErrNotFound = errors.New("catalog: message not found")
|
||||
|
||||
// String specifies a plain message string. It can be used as fallback if no
|
||||
// other strings match or as a simple standalone message.
|
||||
//
|
||||
// It is an error to pass more than one String in a message sequence.
|
||||
func String(name string) Message {
|
||||
return catmsg.String(name)
|
||||
}
|
||||
|
||||
// Var sets a variable that may be substituted in formatting patterns using
|
||||
// named substitution of the form "${name}". The name argument is used as a
|
||||
// fallback if the statements do not produce a match. The statement sequence may
|
||||
// not contain any Var calls.
|
||||
//
|
||||
// The name passed to a Var must be unique within message sequence.
|
||||
func Var(name string, msg ...Message) Message {
|
||||
return &catmsg.Var{Name: name, Message: firstInSequence(msg)}
|
||||
}
|
||||
|
||||
// Context returns a Context for formatting messages.
|
||||
// Only one Message may be formatted per context at any given time.
|
||||
func (b *Builder) Context(tag language.Tag, r catmsg.Renderer) *Context {
|
||||
return &Context{
|
||||
cat: b,
|
||||
tag: tag,
|
||||
dec: catmsg.NewDecoder(tag, r, &dict{&b.macros, tag}),
|
||||
}
|
||||
}
|
||||
|
||||
// A Context is used for evaluating Messages.
|
||||
// Only one Message may be formatted per context at any given time.
|
||||
type Context struct {
|
||||
cat Catalog
|
||||
tag language.Tag // TODO: use compact index.
|
||||
dec *catmsg.Decoder
|
||||
}
|
||||
|
||||
// Execute looks up and executes the message with the given key.
|
||||
// It returns ErrNotFound if no message could be found in the index.
|
||||
func (c *Context) Execute(key string) error {
|
||||
data, ok := c.cat.lookup(c.tag, key)
|
||||
if !ok {
|
||||
return ErrNotFound
|
||||
}
|
||||
return c.dec.Execute(data)
|
||||
}
|
129
vendor/golang.org/x/text/message/catalog/dict.go
generated
vendored
129
vendor/golang.org/x/text/message/catalog/dict.go
generated
vendored
@ -1,129 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package catalog
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"golang.org/x/text/internal"
|
||||
"golang.org/x/text/internal/catmsg"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// TODO:
|
||||
// Dictionary returns a Dictionary that returns the first Message, using the
|
||||
// given language tag, that matches:
|
||||
// 1. the last one registered by one of the Set methods
|
||||
// 2. returned by one of the Loaders
|
||||
// 3. repeat from 1. using the parent language
|
||||
// This approach allows messages to be underspecified.
|
||||
// func (c *Catalog) Dictionary(tag language.Tag) (Dictionary, error) {
|
||||
// // TODO: verify dictionary exists.
|
||||
// return &dict{&c.index, tag}, nil
|
||||
// }
|
||||
|
||||
type dict struct {
|
||||
s *store
|
||||
tag language.Tag // TODO: make compact tag.
|
||||
}
|
||||
|
||||
func (d *dict) Lookup(key string) (data string, ok bool) {
|
||||
return d.s.lookup(d.tag, key)
|
||||
}
|
||||
|
||||
func (b *Builder) lookup(tag language.Tag, key string) (data string, ok bool) {
|
||||
return b.index.lookup(tag, key)
|
||||
}
|
||||
|
||||
func (c *Builder) set(tag language.Tag, key string, s *store, msg ...Message) error {
|
||||
data, err := catmsg.Compile(tag, &dict{&c.macros, tag}, firstInSequence(msg))
|
||||
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
m := s.index[tag]
|
||||
if m == nil {
|
||||
m = msgMap{}
|
||||
if s.index == nil {
|
||||
s.index = map[language.Tag]msgMap{}
|
||||
}
|
||||
c.matcher = nil
|
||||
s.index[tag] = m
|
||||
}
|
||||
|
||||
m[key] = data
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Builder) Matcher() language.Matcher {
|
||||
c.index.mutex.RLock()
|
||||
m := c.matcher
|
||||
c.index.mutex.RUnlock()
|
||||
if m != nil {
|
||||
return m
|
||||
}
|
||||
|
||||
c.index.mutex.Lock()
|
||||
if c.matcher == nil {
|
||||
c.matcher = language.NewMatcher(c.unlockedLanguages())
|
||||
}
|
||||
m = c.matcher
|
||||
c.index.mutex.Unlock()
|
||||
return m
|
||||
}
|
||||
|
||||
type store struct {
|
||||
mutex sync.RWMutex
|
||||
index map[language.Tag]msgMap
|
||||
}
|
||||
|
||||
type msgMap map[string]string
|
||||
|
||||
func (s *store) lookup(tag language.Tag, key string) (data string, ok bool) {
|
||||
s.mutex.RLock()
|
||||
defer s.mutex.RUnlock()
|
||||
|
||||
for ; ; tag = tag.Parent() {
|
||||
if msgs, ok := s.index[tag]; ok {
|
||||
if msg, ok := msgs[key]; ok {
|
||||
return msg, true
|
||||
}
|
||||
}
|
||||
if tag == language.Und {
|
||||
break
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// Languages returns all languages for which the Catalog contains variants.
|
||||
func (b *Builder) Languages() []language.Tag {
|
||||
s := &b.index
|
||||
s.mutex.RLock()
|
||||
defer s.mutex.RUnlock()
|
||||
|
||||
return b.unlockedLanguages()
|
||||
}
|
||||
|
||||
func (b *Builder) unlockedLanguages() []language.Tag {
|
||||
s := &b.index
|
||||
if len(s.index) == 0 {
|
||||
return nil
|
||||
}
|
||||
tags := make([]language.Tag, 0, len(s.index))
|
||||
_, hasFallback := s.index[b.options.fallback]
|
||||
offset := 0
|
||||
if hasFallback {
|
||||
tags = append(tags, b.options.fallback)
|
||||
offset = 1
|
||||
}
|
||||
for t := range s.index {
|
||||
if t != b.options.fallback {
|
||||
tags = append(tags, t)
|
||||
}
|
||||
}
|
||||
internal.SortTags(tags[offset:])
|
||||
return tags
|
||||
}
|
15
vendor/golang.org/x/text/message/catalog/go19.go
generated
vendored
15
vendor/golang.org/x/text/message/catalog/go19.go
generated
vendored
@ -1,15 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.9
|
||||
|
||||
package catalog
|
||||
|
||||
import "golang.org/x/text/internal/catmsg"
|
||||
|
||||
// A Message holds a collection of translations for the same phrase that may
|
||||
// vary based on the values of substitution arguments.
|
||||
type Message = catmsg.Message
|
||||
|
||||
type firstInSequence = catmsg.FirstOf
|
23
vendor/golang.org/x/text/message/catalog/gopre19.go
generated
vendored
23
vendor/golang.org/x/text/message/catalog/gopre19.go
generated
vendored
@ -1,23 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.9
|
||||
|
||||
package catalog
|
||||
|
||||
import "golang.org/x/text/internal/catmsg"
|
||||
|
||||
// A Message holds a collection of translations for the same phrase that may
|
||||
// vary based on the values of substitution arguments.
|
||||
type Message interface {
|
||||
catmsg.Message
|
||||
}
|
||||
|
||||
func firstInSequence(m []Message) catmsg.Message {
|
||||
a := []catmsg.Message{}
|
||||
for _, m := range m {
|
||||
a = append(a, m)
|
||||
}
|
||||
return catmsg.FirstOf(a)
|
||||
}
|
99
vendor/golang.org/x/text/message/doc.go
generated
vendored
99
vendor/golang.org/x/text/message/doc.go
generated
vendored
@ -1,99 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package message implements formatted I/O for localized strings with functions
|
||||
// analogous to the fmt's print functions. It is a drop-in replacement for fmt.
|
||||
//
|
||||
// # Localized Formatting
|
||||
//
|
||||
// A format string can be localized by replacing any of the print functions of
|
||||
// fmt with an equivalent call to a Printer.
|
||||
//
|
||||
// p := message.NewPrinter(message.MatchLanguage("en"))
|
||||
// p.Println(123456.78) // Prints 123,456.78
|
||||
//
|
||||
// p.Printf("%d ducks in a row", 4331) // Prints 4,331 ducks in a row
|
||||
//
|
||||
// p := message.NewPrinter(message.MatchLanguage("nl"))
|
||||
// p.Printf("Hoogte: %.1f meter", 1244.9) // Prints Hoogte: 1,244.9 meter
|
||||
//
|
||||
// p := message.NewPrinter(message.MatchLanguage("bn"))
|
||||
// p.Println(123456.78) // Prints ১,২৩,৪৫৬.৭৮
|
||||
//
|
||||
// Printer currently supports numbers and specialized types for which packages
|
||||
// exist in x/text. Other builtin types such as time.Time and slices are
|
||||
// planned.
|
||||
//
|
||||
// Format strings largely have the same meaning as with fmt with the following
|
||||
// notable exceptions:
|
||||
// - flag # always resorts to fmt for printing
|
||||
// - verb 'f', 'e', 'g', 'd' use localized formatting unless the '#' flag is
|
||||
// specified.
|
||||
// - verb 'm' inserts a translation of a string argument.
|
||||
//
|
||||
// See package fmt for more options.
|
||||
//
|
||||
// # Translation
|
||||
//
|
||||
// The format strings that are passed to Printf, Sprintf, Fprintf, or Errorf
|
||||
// are used as keys to look up translations for the specified languages.
|
||||
// More on how these need to be specified below.
|
||||
//
|
||||
// One can use arbitrary keys to distinguish between otherwise ambiguous
|
||||
// strings:
|
||||
//
|
||||
// p := message.NewPrinter(language.English)
|
||||
// p.Printf("archive(noun)") // Prints "archive"
|
||||
// p.Printf("archive(verb)") // Prints "archive"
|
||||
//
|
||||
// p := message.NewPrinter(language.German)
|
||||
// p.Printf("archive(noun)") // Prints "Archiv"
|
||||
// p.Printf("archive(verb)") // Prints "archivieren"
|
||||
//
|
||||
// To retain the fallback functionality, use Key:
|
||||
//
|
||||
// p.Printf(message.Key("archive(noun)", "archive"))
|
||||
// p.Printf(message.Key("archive(verb)", "archive"))
|
||||
//
|
||||
// # Translation Pipeline
|
||||
//
|
||||
// Format strings that contain text need to be translated to support different
|
||||
// locales. The first step is to extract strings that need to be translated.
|
||||
//
|
||||
// 1. Install gotext
|
||||
//
|
||||
// go get -u golang.org/x/text/cmd/gotext
|
||||
// gotext -help
|
||||
//
|
||||
// 2. Mark strings in your source to be translated by using message.Printer,
|
||||
// instead of the functions of the fmt package.
|
||||
//
|
||||
// 3. Extract the strings from your source
|
||||
//
|
||||
// gotext extract
|
||||
//
|
||||
// The output will be written to the textdata directory.
|
||||
//
|
||||
// 4. Send the files for translation
|
||||
//
|
||||
// It is planned to support multiple formats, but for now one will have to
|
||||
// rewrite the JSON output to the desired format.
|
||||
//
|
||||
// 5. Inject translations into program
|
||||
//
|
||||
// 6. Repeat from 2
|
||||
//
|
||||
// Right now this has to be done programmatically with calls to Set or
|
||||
// SetString. These functions as well as the methods defined in
|
||||
// see also package golang.org/x/text/message/catalog can be used to implement
|
||||
// either dynamic or static loading of messages.
|
||||
//
|
||||
// # Plural and Gender Forms
|
||||
//
|
||||
// Translated messages can vary based on the plural and gender forms of
|
||||
// substitution values. In general, it is up to the translators to provide
|
||||
// alternative translations for such forms. See the packages in
|
||||
// golang.org/x/text/feature and golang.org/x/text/message/catalog for more
|
||||
// information.
|
||||
package message
|
510
vendor/golang.org/x/text/message/format.go
generated
vendored
510
vendor/golang.org/x/text/message/format.go
generated
vendored
@ -1,510 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package message
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strconv"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/internal/format"
|
||||
)
|
||||
|
||||
const (
|
||||
ldigits = "0123456789abcdefx"
|
||||
udigits = "0123456789ABCDEFX"
|
||||
)
|
||||
|
||||
const (
|
||||
signed = true
|
||||
unsigned = false
|
||||
)
|
||||
|
||||
// A formatInfo is the raw formatter used by Printf etc.
|
||||
// It prints into a buffer that must be set up separately.
|
||||
type formatInfo struct {
|
||||
buf *bytes.Buffer
|
||||
|
||||
format.Parser
|
||||
|
||||
// intbuf is large enough to store %b of an int64 with a sign and
|
||||
// avoids padding at the end of the struct on 32 bit architectures.
|
||||
intbuf [68]byte
|
||||
}
|
||||
|
||||
func (f *formatInfo) init(buf *bytes.Buffer) {
|
||||
f.ClearFlags()
|
||||
f.buf = buf
|
||||
}
|
||||
|
||||
// writePadding generates n bytes of padding.
|
||||
func (f *formatInfo) writePadding(n int) {
|
||||
if n <= 0 { // No padding bytes needed.
|
||||
return
|
||||
}
|
||||
f.buf.Grow(n)
|
||||
// Decide which byte the padding should be filled with.
|
||||
padByte := byte(' ')
|
||||
if f.Zero {
|
||||
padByte = byte('0')
|
||||
}
|
||||
// Fill padding with padByte.
|
||||
for i := 0; i < n; i++ {
|
||||
f.buf.WriteByte(padByte) // TODO: make more efficient.
|
||||
}
|
||||
}
|
||||
|
||||
// pad appends b to f.buf, padded on left (!f.minus) or right (f.minus).
|
||||
func (f *formatInfo) pad(b []byte) {
|
||||
if !f.WidthPresent || f.Width == 0 {
|
||||
f.buf.Write(b)
|
||||
return
|
||||
}
|
||||
width := f.Width - utf8.RuneCount(b)
|
||||
if !f.Minus {
|
||||
// left padding
|
||||
f.writePadding(width)
|
||||
f.buf.Write(b)
|
||||
} else {
|
||||
// right padding
|
||||
f.buf.Write(b)
|
||||
f.writePadding(width)
|
||||
}
|
||||
}
|
||||
|
||||
// padString appends s to f.buf, padded on left (!f.minus) or right (f.minus).
|
||||
func (f *formatInfo) padString(s string) {
|
||||
if !f.WidthPresent || f.Width == 0 {
|
||||
f.buf.WriteString(s)
|
||||
return
|
||||
}
|
||||
width := f.Width - utf8.RuneCountInString(s)
|
||||
if !f.Minus {
|
||||
// left padding
|
||||
f.writePadding(width)
|
||||
f.buf.WriteString(s)
|
||||
} else {
|
||||
// right padding
|
||||
f.buf.WriteString(s)
|
||||
f.writePadding(width)
|
||||
}
|
||||
}
|
||||
|
||||
// fmt_boolean formats a boolean.
|
||||
func (f *formatInfo) fmt_boolean(v bool) {
|
||||
if v {
|
||||
f.padString("true")
|
||||
} else {
|
||||
f.padString("false")
|
||||
}
|
||||
}
|
||||
|
||||
// fmt_unicode formats a uint64 as "U+0078" or with f.sharp set as "U+0078 'x'".
|
||||
func (f *formatInfo) fmt_unicode(u uint64) {
|
||||
buf := f.intbuf[0:]
|
||||
|
||||
// With default precision set the maximum needed buf length is 18
|
||||
// for formatting -1 with %#U ("U+FFFFFFFFFFFFFFFF") which fits
|
||||
// into the already allocated intbuf with a capacity of 68 bytes.
|
||||
prec := 4
|
||||
if f.PrecPresent && f.Prec > 4 {
|
||||
prec = f.Prec
|
||||
// Compute space needed for "U+" , number, " '", character, "'".
|
||||
width := 2 + prec + 2 + utf8.UTFMax + 1
|
||||
if width > len(buf) {
|
||||
buf = make([]byte, width)
|
||||
}
|
||||
}
|
||||
|
||||
// Format into buf, ending at buf[i]. Formatting numbers is easier right-to-left.
|
||||
i := len(buf)
|
||||
|
||||
// For %#U we want to add a space and a quoted character at the end of the buffer.
|
||||
if f.Sharp && u <= utf8.MaxRune && strconv.IsPrint(rune(u)) {
|
||||
i--
|
||||
buf[i] = '\''
|
||||
i -= utf8.RuneLen(rune(u))
|
||||
utf8.EncodeRune(buf[i:], rune(u))
|
||||
i--
|
||||
buf[i] = '\''
|
||||
i--
|
||||
buf[i] = ' '
|
||||
}
|
||||
// Format the Unicode code point u as a hexadecimal number.
|
||||
for u >= 16 {
|
||||
i--
|
||||
buf[i] = udigits[u&0xF]
|
||||
prec--
|
||||
u >>= 4
|
||||
}
|
||||
i--
|
||||
buf[i] = udigits[u]
|
||||
prec--
|
||||
// Add zeros in front of the number until requested precision is reached.
|
||||
for prec > 0 {
|
||||
i--
|
||||
buf[i] = '0'
|
||||
prec--
|
||||
}
|
||||
// Add a leading "U+".
|
||||
i--
|
||||
buf[i] = '+'
|
||||
i--
|
||||
buf[i] = 'U'
|
||||
|
||||
oldZero := f.Zero
|
||||
f.Zero = false
|
||||
f.pad(buf[i:])
|
||||
f.Zero = oldZero
|
||||
}
|
||||
|
||||
// fmt_integer formats signed and unsigned integers.
|
||||
func (f *formatInfo) fmt_integer(u uint64, base int, isSigned bool, digits string) {
|
||||
negative := isSigned && int64(u) < 0
|
||||
if negative {
|
||||
u = -u
|
||||
}
|
||||
|
||||
buf := f.intbuf[0:]
|
||||
// The already allocated f.intbuf with a capacity of 68 bytes
|
||||
// is large enough for integer formatting when no precision or width is set.
|
||||
if f.WidthPresent || f.PrecPresent {
|
||||
// Account 3 extra bytes for possible addition of a sign and "0x".
|
||||
width := 3 + f.Width + f.Prec // wid and prec are always positive.
|
||||
if width > len(buf) {
|
||||
// We're going to need a bigger boat.
|
||||
buf = make([]byte, width)
|
||||
}
|
||||
}
|
||||
|
||||
// Two ways to ask for extra leading zero digits: %.3d or %03d.
|
||||
// If both are specified the f.zero flag is ignored and
|
||||
// padding with spaces is used instead.
|
||||
prec := 0
|
||||
if f.PrecPresent {
|
||||
prec = f.Prec
|
||||
// Precision of 0 and value of 0 means "print nothing" but padding.
|
||||
if prec == 0 && u == 0 {
|
||||
oldZero := f.Zero
|
||||
f.Zero = false
|
||||
f.writePadding(f.Width)
|
||||
f.Zero = oldZero
|
||||
return
|
||||
}
|
||||
} else if f.Zero && f.WidthPresent {
|
||||
prec = f.Width
|
||||
if negative || f.Plus || f.Space {
|
||||
prec-- // leave room for sign
|
||||
}
|
||||
}
|
||||
|
||||
// Because printing is easier right-to-left: format u into buf, ending at buf[i].
|
||||
// We could make things marginally faster by splitting the 32-bit case out
|
||||
// into a separate block but it's not worth the duplication, so u has 64 bits.
|
||||
i := len(buf)
|
||||
// Use constants for the division and modulo for more efficient code.
|
||||
// Switch cases ordered by popularity.
|
||||
switch base {
|
||||
case 10:
|
||||
for u >= 10 {
|
||||
i--
|
||||
next := u / 10
|
||||
buf[i] = byte('0' + u - next*10)
|
||||
u = next
|
||||
}
|
||||
case 16:
|
||||
for u >= 16 {
|
||||
i--
|
||||
buf[i] = digits[u&0xF]
|
||||
u >>= 4
|
||||
}
|
||||
case 8:
|
||||
for u >= 8 {
|
||||
i--
|
||||
buf[i] = byte('0' + u&7)
|
||||
u >>= 3
|
||||
}
|
||||
case 2:
|
||||
for u >= 2 {
|
||||
i--
|
||||
buf[i] = byte('0' + u&1)
|
||||
u >>= 1
|
||||
}
|
||||
default:
|
||||
panic("fmt: unknown base; can't happen")
|
||||
}
|
||||
i--
|
||||
buf[i] = digits[u]
|
||||
for i > 0 && prec > len(buf)-i {
|
||||
i--
|
||||
buf[i] = '0'
|
||||
}
|
||||
|
||||
// Various prefixes: 0x, -, etc.
|
||||
if f.Sharp {
|
||||
switch base {
|
||||
case 8:
|
||||
if buf[i] != '0' {
|
||||
i--
|
||||
buf[i] = '0'
|
||||
}
|
||||
case 16:
|
||||
// Add a leading 0x or 0X.
|
||||
i--
|
||||
buf[i] = digits[16]
|
||||
i--
|
||||
buf[i] = '0'
|
||||
}
|
||||
}
|
||||
|
||||
if negative {
|
||||
i--
|
||||
buf[i] = '-'
|
||||
} else if f.Plus {
|
||||
i--
|
||||
buf[i] = '+'
|
||||
} else if f.Space {
|
||||
i--
|
||||
buf[i] = ' '
|
||||
}
|
||||
|
||||
// Left padding with zeros has already been handled like precision earlier
|
||||
// or the f.zero flag is ignored due to an explicitly set precision.
|
||||
oldZero := f.Zero
|
||||
f.Zero = false
|
||||
f.pad(buf[i:])
|
||||
f.Zero = oldZero
|
||||
}
|
||||
|
||||
// truncate truncates the string to the specified precision, if present.
|
||||
func (f *formatInfo) truncate(s string) string {
|
||||
if f.PrecPresent {
|
||||
n := f.Prec
|
||||
for i := range s {
|
||||
n--
|
||||
if n < 0 {
|
||||
return s[:i]
|
||||
}
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// fmt_s formats a string.
|
||||
func (f *formatInfo) fmt_s(s string) {
|
||||
s = f.truncate(s)
|
||||
f.padString(s)
|
||||
}
|
||||
|
||||
// fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes.
|
||||
func (f *formatInfo) fmt_sbx(s string, b []byte, digits string) {
|
||||
length := len(b)
|
||||
if b == nil {
|
||||
// No byte slice present. Assume string s should be encoded.
|
||||
length = len(s)
|
||||
}
|
||||
// Set length to not process more bytes than the precision demands.
|
||||
if f.PrecPresent && f.Prec < length {
|
||||
length = f.Prec
|
||||
}
|
||||
// Compute width of the encoding taking into account the f.sharp and f.space flag.
|
||||
width := 2 * length
|
||||
if width > 0 {
|
||||
if f.Space {
|
||||
// Each element encoded by two hexadecimals will get a leading 0x or 0X.
|
||||
if f.Sharp {
|
||||
width *= 2
|
||||
}
|
||||
// Elements will be separated by a space.
|
||||
width += length - 1
|
||||
} else if f.Sharp {
|
||||
// Only a leading 0x or 0X will be added for the whole string.
|
||||
width += 2
|
||||
}
|
||||
} else { // The byte slice or string that should be encoded is empty.
|
||||
if f.WidthPresent {
|
||||
f.writePadding(f.Width)
|
||||
}
|
||||
return
|
||||
}
|
||||
// Handle padding to the left.
|
||||
if f.WidthPresent && f.Width > width && !f.Minus {
|
||||
f.writePadding(f.Width - width)
|
||||
}
|
||||
// Write the encoding directly into the output buffer.
|
||||
buf := f.buf
|
||||
if f.Sharp {
|
||||
// Add leading 0x or 0X.
|
||||
buf.WriteByte('0')
|
||||
buf.WriteByte(digits[16])
|
||||
}
|
||||
var c byte
|
||||
for i := 0; i < length; i++ {
|
||||
if f.Space && i > 0 {
|
||||
// Separate elements with a space.
|
||||
buf.WriteByte(' ')
|
||||
if f.Sharp {
|
||||
// Add leading 0x or 0X for each element.
|
||||
buf.WriteByte('0')
|
||||
buf.WriteByte(digits[16])
|
||||
}
|
||||
}
|
||||
if b != nil {
|
||||
c = b[i] // Take a byte from the input byte slice.
|
||||
} else {
|
||||
c = s[i] // Take a byte from the input string.
|
||||
}
|
||||
// Encode each byte as two hexadecimal digits.
|
||||
buf.WriteByte(digits[c>>4])
|
||||
buf.WriteByte(digits[c&0xF])
|
||||
}
|
||||
// Handle padding to the right.
|
||||
if f.WidthPresent && f.Width > width && f.Minus {
|
||||
f.writePadding(f.Width - width)
|
||||
}
|
||||
}
|
||||
|
||||
// fmt_sx formats a string as a hexadecimal encoding of its bytes.
|
||||
func (f *formatInfo) fmt_sx(s, digits string) {
|
||||
f.fmt_sbx(s, nil, digits)
|
||||
}
|
||||
|
||||
// fmt_bx formats a byte slice as a hexadecimal encoding of its bytes.
|
||||
func (f *formatInfo) fmt_bx(b []byte, digits string) {
|
||||
f.fmt_sbx("", b, digits)
|
||||
}
|
||||
|
||||
// fmt_q formats a string as a double-quoted, escaped Go string constant.
|
||||
// If f.sharp is set a raw (backquoted) string may be returned instead
|
||||
// if the string does not contain any control characters other than tab.
|
||||
func (f *formatInfo) fmt_q(s string) {
|
||||
s = f.truncate(s)
|
||||
if f.Sharp && strconv.CanBackquote(s) {
|
||||
f.padString("`" + s + "`")
|
||||
return
|
||||
}
|
||||
buf := f.intbuf[:0]
|
||||
if f.Plus {
|
||||
f.pad(strconv.AppendQuoteToASCII(buf, s))
|
||||
} else {
|
||||
f.pad(strconv.AppendQuote(buf, s))
|
||||
}
|
||||
}
|
||||
|
||||
// fmt_c formats an integer as a Unicode character.
|
||||
// If the character is not valid Unicode, it will print '\ufffd'.
|
||||
func (f *formatInfo) fmt_c(c uint64) {
|
||||
r := rune(c)
|
||||
if c > utf8.MaxRune {
|
||||
r = utf8.RuneError
|
||||
}
|
||||
buf := f.intbuf[:0]
|
||||
w := utf8.EncodeRune(buf[:utf8.UTFMax], r)
|
||||
f.pad(buf[:w])
|
||||
}
|
||||
|
||||
// fmt_qc formats an integer as a single-quoted, escaped Go character constant.
|
||||
// If the character is not valid Unicode, it will print '\ufffd'.
|
||||
func (f *formatInfo) fmt_qc(c uint64) {
|
||||
r := rune(c)
|
||||
if c > utf8.MaxRune {
|
||||
r = utf8.RuneError
|
||||
}
|
||||
buf := f.intbuf[:0]
|
||||
if f.Plus {
|
||||
f.pad(strconv.AppendQuoteRuneToASCII(buf, r))
|
||||
} else {
|
||||
f.pad(strconv.AppendQuoteRune(buf, r))
|
||||
}
|
||||
}
|
||||
|
||||
// fmt_float formats a float64. It assumes that verb is a valid format specifier
|
||||
// for strconv.AppendFloat and therefore fits into a byte.
|
||||
func (f *formatInfo) fmt_float(v float64, size int, verb rune, prec int) {
|
||||
// Explicit precision in format specifier overrules default precision.
|
||||
if f.PrecPresent {
|
||||
prec = f.Prec
|
||||
}
|
||||
// Format number, reserving space for leading + sign if needed.
|
||||
num := strconv.AppendFloat(f.intbuf[:1], v, byte(verb), prec, size)
|
||||
if num[1] == '-' || num[1] == '+' {
|
||||
num = num[1:]
|
||||
} else {
|
||||
num[0] = '+'
|
||||
}
|
||||
// f.space means to add a leading space instead of a "+" sign unless
|
||||
// the sign is explicitly asked for by f.plus.
|
||||
if f.Space && num[0] == '+' && !f.Plus {
|
||||
num[0] = ' '
|
||||
}
|
||||
// Special handling for infinities and NaN,
|
||||
// which don't look like a number so shouldn't be padded with zeros.
|
||||
if num[1] == 'I' || num[1] == 'N' {
|
||||
oldZero := f.Zero
|
||||
f.Zero = false
|
||||
// Remove sign before NaN if not asked for.
|
||||
if num[1] == 'N' && !f.Space && !f.Plus {
|
||||
num = num[1:]
|
||||
}
|
||||
f.pad(num)
|
||||
f.Zero = oldZero
|
||||
return
|
||||
}
|
||||
// The sharp flag forces printing a decimal point for non-binary formats
|
||||
// and retains trailing zeros, which we may need to restore.
|
||||
if f.Sharp && verb != 'b' {
|
||||
digits := 0
|
||||
switch verb {
|
||||
case 'v', 'g', 'G':
|
||||
digits = prec
|
||||
// If no precision is set explicitly use a precision of 6.
|
||||
if digits == -1 {
|
||||
digits = 6
|
||||
}
|
||||
}
|
||||
|
||||
// Buffer pre-allocated with enough room for
|
||||
// exponent notations of the form "e+123".
|
||||
var tailBuf [5]byte
|
||||
tail := tailBuf[:0]
|
||||
|
||||
hasDecimalPoint := false
|
||||
// Starting from i = 1 to skip sign at num[0].
|
||||
for i := 1; i < len(num); i++ {
|
||||
switch num[i] {
|
||||
case '.':
|
||||
hasDecimalPoint = true
|
||||
case 'e', 'E':
|
||||
tail = append(tail, num[i:]...)
|
||||
num = num[:i]
|
||||
default:
|
||||
digits--
|
||||
}
|
||||
}
|
||||
if !hasDecimalPoint {
|
||||
num = append(num, '.')
|
||||
}
|
||||
for digits > 0 {
|
||||
num = append(num, '0')
|
||||
digits--
|
||||
}
|
||||
num = append(num, tail...)
|
||||
}
|
||||
// We want a sign if asked for and if the sign is not positive.
|
||||
if f.Plus || num[0] != '+' {
|
||||
// If we're zero padding to the left we want the sign before the leading zeros.
|
||||
// Achieve this by writing the sign out and then padding the unsigned number.
|
||||
if f.Zero && f.WidthPresent && f.Width > len(num) {
|
||||
f.buf.WriteByte(num[0])
|
||||
f.writePadding(f.Width - len(num))
|
||||
f.buf.Write(num[1:])
|
||||
return
|
||||
}
|
||||
f.pad(num)
|
||||
return
|
||||
}
|
||||
// No sign to show and the number is positive; just print the unsigned number.
|
||||
f.pad(num[1:])
|
||||
}
|
192
vendor/golang.org/x/text/message/message.go
generated
vendored
192
vendor/golang.org/x/text/message/message.go
generated
vendored
@ -1,192 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package message // import "golang.org/x/text/message"
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
// Include features to facilitate generated catalogs.
|
||||
_ "golang.org/x/text/feature/plural"
|
||||
|
||||
"golang.org/x/text/internal/number"
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message/catalog"
|
||||
)
|
||||
|
||||
// A Printer implements language-specific formatted I/O analogous to the fmt
|
||||
// package.
|
||||
type Printer struct {
|
||||
// the language
|
||||
tag language.Tag
|
||||
|
||||
toDecimal number.Formatter
|
||||
toScientific number.Formatter
|
||||
|
||||
cat catalog.Catalog
|
||||
}
|
||||
|
||||
type options struct {
|
||||
cat catalog.Catalog
|
||||
// TODO:
|
||||
// - allow %s to print integers in written form (tables are likely too large
|
||||
// to enable this by default).
|
||||
// - list behavior
|
||||
//
|
||||
}
|
||||
|
||||
// An Option defines an option of a Printer.
|
||||
type Option func(o *options)
|
||||
|
||||
// Catalog defines the catalog to be used.
|
||||
func Catalog(c catalog.Catalog) Option {
|
||||
return func(o *options) { o.cat = c }
|
||||
}
|
||||
|
||||
// NewPrinter returns a Printer that formats messages tailored to language t.
|
||||
func NewPrinter(t language.Tag, opts ...Option) *Printer {
|
||||
options := &options{
|
||||
cat: DefaultCatalog,
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(options)
|
||||
}
|
||||
p := &Printer{
|
||||
tag: t,
|
||||
cat: options.cat,
|
||||
}
|
||||
p.toDecimal.InitDecimal(t)
|
||||
p.toScientific.InitScientific(t)
|
||||
return p
|
||||
}
|
||||
|
||||
// Sprint is like fmt.Sprint, but using language-specific formatting.
|
||||
func (p *Printer) Sprint(a ...interface{}) string {
|
||||
pp := newPrinter(p)
|
||||
pp.doPrint(a)
|
||||
s := pp.String()
|
||||
pp.free()
|
||||
return s
|
||||
}
|
||||
|
||||
// Fprint is like fmt.Fprint, but using language-specific formatting.
|
||||
func (p *Printer) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
|
||||
pp := newPrinter(p)
|
||||
pp.doPrint(a)
|
||||
n64, err := io.Copy(w, &pp.Buffer)
|
||||
pp.free()
|
||||
return int(n64), err
|
||||
}
|
||||
|
||||
// Print is like fmt.Print, but using language-specific formatting.
|
||||
func (p *Printer) Print(a ...interface{}) (n int, err error) {
|
||||
return p.Fprint(os.Stdout, a...)
|
||||
}
|
||||
|
||||
// Sprintln is like fmt.Sprintln, but using language-specific formatting.
|
||||
func (p *Printer) Sprintln(a ...interface{}) string {
|
||||
pp := newPrinter(p)
|
||||
pp.doPrintln(a)
|
||||
s := pp.String()
|
||||
pp.free()
|
||||
return s
|
||||
}
|
||||
|
||||
// Fprintln is like fmt.Fprintln, but using language-specific formatting.
|
||||
func (p *Printer) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
|
||||
pp := newPrinter(p)
|
||||
pp.doPrintln(a)
|
||||
n64, err := io.Copy(w, &pp.Buffer)
|
||||
pp.free()
|
||||
return int(n64), err
|
||||
}
|
||||
|
||||
// Println is like fmt.Println, but using language-specific formatting.
|
||||
func (p *Printer) Println(a ...interface{}) (n int, err error) {
|
||||
return p.Fprintln(os.Stdout, a...)
|
||||
}
|
||||
|
||||
// Sprintf is like fmt.Sprintf, but using language-specific formatting.
|
||||
func (p *Printer) Sprintf(key Reference, a ...interface{}) string {
|
||||
pp := newPrinter(p)
|
||||
lookupAndFormat(pp, key, a)
|
||||
s := pp.String()
|
||||
pp.free()
|
||||
return s
|
||||
}
|
||||
|
||||
// Fprintf is like fmt.Fprintf, but using language-specific formatting.
|
||||
func (p *Printer) Fprintf(w io.Writer, key Reference, a ...interface{}) (n int, err error) {
|
||||
pp := newPrinter(p)
|
||||
lookupAndFormat(pp, key, a)
|
||||
n, err = w.Write(pp.Bytes())
|
||||
pp.free()
|
||||
return n, err
|
||||
|
||||
}
|
||||
|
||||
// Printf is like fmt.Printf, but using language-specific formatting.
|
||||
func (p *Printer) Printf(key Reference, a ...interface{}) (n int, err error) {
|
||||
pp := newPrinter(p)
|
||||
lookupAndFormat(pp, key, a)
|
||||
n, err = os.Stdout.Write(pp.Bytes())
|
||||
pp.free()
|
||||
return n, err
|
||||
}
|
||||
|
||||
func lookupAndFormat(p *printer, r Reference, a []interface{}) {
|
||||
p.fmt.Reset(a)
|
||||
switch v := r.(type) {
|
||||
case string:
|
||||
if p.catContext.Execute(v) == catalog.ErrNotFound {
|
||||
p.Render(v)
|
||||
return
|
||||
}
|
||||
case key:
|
||||
if p.catContext.Execute(v.id) == catalog.ErrNotFound &&
|
||||
p.catContext.Execute(v.fallback) == catalog.ErrNotFound {
|
||||
p.Render(v.fallback)
|
||||
return
|
||||
}
|
||||
default:
|
||||
panic("key argument is not a Reference")
|
||||
}
|
||||
}
|
||||
|
||||
type rawPrinter struct {
|
||||
p *printer
|
||||
}
|
||||
|
||||
func (p rawPrinter) Render(msg string) { p.p.WriteString(msg) }
|
||||
func (p rawPrinter) Arg(i int) interface{} { return nil }
|
||||
|
||||
// Arg implements catmsg.Renderer.
|
||||
func (p *printer) Arg(i int) interface{} { // TODO, also return "ok" bool
|
||||
i--
|
||||
if uint(i) < uint(len(p.fmt.Args)) {
|
||||
return p.fmt.Args[i]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Render implements catmsg.Renderer.
|
||||
func (p *printer) Render(msg string) {
|
||||
p.doPrintf(msg)
|
||||
}
|
||||
|
||||
// A Reference is a string or a message reference.
|
||||
type Reference interface {
|
||||
// TODO: also allow []string
|
||||
}
|
||||
|
||||
// Key creates a message Reference for a message where the given id is used for
|
||||
// message lookup and the fallback is returned when no matches are found.
|
||||
func Key(id string, fallback string) Reference {
|
||||
return key{id, fallback}
|
||||
}
|
||||
|
||||
type key struct {
|
||||
id, fallback string
|
||||
}
|
984
vendor/golang.org/x/text/message/print.go
generated
vendored
984
vendor/golang.org/x/text/message/print.go
generated
vendored
@ -1,984 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package message
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt" // TODO: consider copying interfaces from package fmt to avoid dependency.
|
||||
"math"
|
||||
"reflect"
|
||||
"sync"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/internal/format"
|
||||
"golang.org/x/text/internal/number"
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message/catalog"
|
||||
)
|
||||
|
||||
// Strings for use with buffer.WriteString.
|
||||
// This is less overhead than using buffer.Write with byte arrays.
|
||||
const (
|
||||
commaSpaceString = ", "
|
||||
nilAngleString = "<nil>"
|
||||
nilParenString = "(nil)"
|
||||
nilString = "nil"
|
||||
mapString = "map["
|
||||
percentBangString = "%!"
|
||||
missingString = "(MISSING)"
|
||||
badIndexString = "(BADINDEX)"
|
||||
panicString = "(PANIC="
|
||||
extraString = "%!(EXTRA "
|
||||
badWidthString = "%!(BADWIDTH)"
|
||||
badPrecString = "%!(BADPREC)"
|
||||
noVerbString = "%!(NOVERB)"
|
||||
|
||||
invReflectString = "<invalid reflect.Value>"
|
||||
)
|
||||
|
||||
var printerPool = sync.Pool{
|
||||
New: func() interface{} { return new(printer) },
|
||||
}
|
||||
|
||||
// newPrinter allocates a new printer struct or grabs a cached one.
|
||||
func newPrinter(pp *Printer) *printer {
|
||||
p := printerPool.Get().(*printer)
|
||||
p.Printer = *pp
|
||||
// TODO: cache most of the following call.
|
||||
p.catContext = pp.cat.Context(pp.tag, p)
|
||||
|
||||
p.panicking = false
|
||||
p.erroring = false
|
||||
p.fmt.init(&p.Buffer)
|
||||
return p
|
||||
}
|
||||
|
||||
// free saves used printer structs in printerFree; avoids an allocation per invocation.
|
||||
func (p *printer) free() {
|
||||
p.Buffer.Reset()
|
||||
p.arg = nil
|
||||
p.value = reflect.Value{}
|
||||
printerPool.Put(p)
|
||||
}
|
||||
|
||||
// printer is used to store a printer's state.
|
||||
// It implements "golang.org/x/text/internal/format".State.
|
||||
type printer struct {
|
||||
Printer
|
||||
|
||||
// the context for looking up message translations
|
||||
catContext *catalog.Context
|
||||
|
||||
// buffer for accumulating output.
|
||||
bytes.Buffer
|
||||
|
||||
// arg holds the current item, as an interface{}.
|
||||
arg interface{}
|
||||
// value is used instead of arg for reflect values.
|
||||
value reflect.Value
|
||||
|
||||
// fmt is used to format basic items such as integers or strings.
|
||||
fmt formatInfo
|
||||
|
||||
// panicking is set by catchPanic to avoid infinite panic, recover, panic, ... recursion.
|
||||
panicking bool
|
||||
// erroring is set when printing an error string to guard against calling handleMethods.
|
||||
erroring bool
|
||||
}
|
||||
|
||||
// Language implements "golang.org/x/text/internal/format".State.
|
||||
func (p *printer) Language() language.Tag { return p.tag }
|
||||
|
||||
func (p *printer) Width() (wid int, ok bool) { return p.fmt.Width, p.fmt.WidthPresent }
|
||||
|
||||
func (p *printer) Precision() (prec int, ok bool) { return p.fmt.Prec, p.fmt.PrecPresent }
|
||||
|
||||
func (p *printer) Flag(b int) bool {
|
||||
switch b {
|
||||
case '-':
|
||||
return p.fmt.Minus
|
||||
case '+':
|
||||
return p.fmt.Plus || p.fmt.PlusV
|
||||
case '#':
|
||||
return p.fmt.Sharp || p.fmt.SharpV
|
||||
case ' ':
|
||||
return p.fmt.Space
|
||||
case '0':
|
||||
return p.fmt.Zero
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// getField gets the i'th field of the struct value.
|
||||
// If the field is itself is an interface, return a value for
|
||||
// the thing inside the interface, not the interface itself.
|
||||
func getField(v reflect.Value, i int) reflect.Value {
|
||||
val := v.Field(i)
|
||||
if val.Kind() == reflect.Interface && !val.IsNil() {
|
||||
val = val.Elem()
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func (p *printer) unknownType(v reflect.Value) {
|
||||
if !v.IsValid() {
|
||||
p.WriteString(nilAngleString)
|
||||
return
|
||||
}
|
||||
p.WriteByte('?')
|
||||
p.WriteString(v.Type().String())
|
||||
p.WriteByte('?')
|
||||
}
|
||||
|
||||
func (p *printer) badVerb(verb rune) {
|
||||
p.erroring = true
|
||||
p.WriteString(percentBangString)
|
||||
p.WriteRune(verb)
|
||||
p.WriteByte('(')
|
||||
switch {
|
||||
case p.arg != nil:
|
||||
p.WriteString(reflect.TypeOf(p.arg).String())
|
||||
p.WriteByte('=')
|
||||
p.printArg(p.arg, 'v')
|
||||
case p.value.IsValid():
|
||||
p.WriteString(p.value.Type().String())
|
||||
p.WriteByte('=')
|
||||
p.printValue(p.value, 'v', 0)
|
||||
default:
|
||||
p.WriteString(nilAngleString)
|
||||
}
|
||||
p.WriteByte(')')
|
||||
p.erroring = false
|
||||
}
|
||||
|
||||
func (p *printer) fmtBool(v bool, verb rune) {
|
||||
switch verb {
|
||||
case 't', 'v':
|
||||
p.fmt.fmt_boolean(v)
|
||||
default:
|
||||
p.badVerb(verb)
|
||||
}
|
||||
}
|
||||
|
||||
// fmt0x64 formats a uint64 in hexadecimal and prefixes it with 0x or
|
||||
// not, as requested, by temporarily setting the sharp flag.
|
||||
func (p *printer) fmt0x64(v uint64, leading0x bool) {
|
||||
sharp := p.fmt.Sharp
|
||||
p.fmt.Sharp = leading0x
|
||||
p.fmt.fmt_integer(v, 16, unsigned, ldigits)
|
||||
p.fmt.Sharp = sharp
|
||||
}
|
||||
|
||||
// fmtInteger formats a signed or unsigned integer.
|
||||
func (p *printer) fmtInteger(v uint64, isSigned bool, verb rune) {
|
||||
switch verb {
|
||||
case 'v':
|
||||
if p.fmt.SharpV && !isSigned {
|
||||
p.fmt0x64(v, true)
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
case 'd':
|
||||
if p.fmt.Sharp || p.fmt.SharpV {
|
||||
p.fmt.fmt_integer(v, 10, isSigned, ldigits)
|
||||
} else {
|
||||
p.fmtDecimalInt(v, isSigned)
|
||||
}
|
||||
case 'b':
|
||||
p.fmt.fmt_integer(v, 2, isSigned, ldigits)
|
||||
case 'o':
|
||||
p.fmt.fmt_integer(v, 8, isSigned, ldigits)
|
||||
case 'x':
|
||||
p.fmt.fmt_integer(v, 16, isSigned, ldigits)
|
||||
case 'X':
|
||||
p.fmt.fmt_integer(v, 16, isSigned, udigits)
|
||||
case 'c':
|
||||
p.fmt.fmt_c(v)
|
||||
case 'q':
|
||||
if v <= utf8.MaxRune {
|
||||
p.fmt.fmt_qc(v)
|
||||
} else {
|
||||
p.badVerb(verb)
|
||||
}
|
||||
case 'U':
|
||||
p.fmt.fmt_unicode(v)
|
||||
default:
|
||||
p.badVerb(verb)
|
||||
}
|
||||
}
|
||||
|
||||
// fmtFloat formats a float. The default precision for each verb
|
||||
// is specified as last argument in the call to fmt_float.
|
||||
func (p *printer) fmtFloat(v float64, size int, verb rune) {
|
||||
switch verb {
|
||||
case 'b':
|
||||
p.fmt.fmt_float(v, size, verb, -1)
|
||||
case 'v':
|
||||
verb = 'g'
|
||||
fallthrough
|
||||
case 'g', 'G':
|
||||
if p.fmt.Sharp || p.fmt.SharpV {
|
||||
p.fmt.fmt_float(v, size, verb, -1)
|
||||
} else {
|
||||
p.fmtVariableFloat(v, size)
|
||||
}
|
||||
case 'e', 'E':
|
||||
if p.fmt.Sharp || p.fmt.SharpV {
|
||||
p.fmt.fmt_float(v, size, verb, 6)
|
||||
} else {
|
||||
p.fmtScientific(v, size, 6)
|
||||
}
|
||||
case 'f', 'F':
|
||||
if p.fmt.Sharp || p.fmt.SharpV {
|
||||
p.fmt.fmt_float(v, size, verb, 6)
|
||||
} else {
|
||||
p.fmtDecimalFloat(v, size, 6)
|
||||
}
|
||||
default:
|
||||
p.badVerb(verb)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *printer) setFlags(f *number.Formatter) {
|
||||
f.Flags &^= number.ElideSign
|
||||
if p.fmt.Plus || p.fmt.Space {
|
||||
f.Flags |= number.AlwaysSign
|
||||
if !p.fmt.Plus {
|
||||
f.Flags |= number.ElideSign
|
||||
}
|
||||
} else {
|
||||
f.Flags &^= number.AlwaysSign
|
||||
}
|
||||
}
|
||||
|
||||
func (p *printer) updatePadding(f *number.Formatter) {
|
||||
f.Flags &^= number.PadMask
|
||||
if p.fmt.Minus {
|
||||
f.Flags |= number.PadAfterSuffix
|
||||
} else {
|
||||
f.Flags |= number.PadBeforePrefix
|
||||
}
|
||||
f.PadRune = ' '
|
||||
f.FormatWidth = uint16(p.fmt.Width)
|
||||
}
|
||||
|
||||
func (p *printer) initDecimal(minFrac, maxFrac int) {
|
||||
f := &p.toDecimal
|
||||
f.MinIntegerDigits = 1
|
||||
f.MaxIntegerDigits = 0
|
||||
f.MinFractionDigits = uint8(minFrac)
|
||||
f.MaxFractionDigits = int16(maxFrac)
|
||||
p.setFlags(f)
|
||||
f.PadRune = 0
|
||||
if p.fmt.WidthPresent {
|
||||
if p.fmt.Zero {
|
||||
wid := p.fmt.Width
|
||||
// Use significant integers for this.
|
||||
// TODO: this is not the same as width, but so be it.
|
||||
if f.MinFractionDigits > 0 {
|
||||
wid -= 1 + int(f.MinFractionDigits)
|
||||
}
|
||||
if p.fmt.Plus || p.fmt.Space {
|
||||
wid--
|
||||
}
|
||||
if wid > 0 && wid > int(f.MinIntegerDigits) {
|
||||
f.MinIntegerDigits = uint8(wid)
|
||||
}
|
||||
}
|
||||
p.updatePadding(f)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *printer) initScientific(minFrac, maxFrac int) {
|
||||
f := &p.toScientific
|
||||
if maxFrac < 0 {
|
||||
f.SetPrecision(maxFrac)
|
||||
} else {
|
||||
f.SetPrecision(maxFrac + 1)
|
||||
f.MinFractionDigits = uint8(minFrac)
|
||||
f.MaxFractionDigits = int16(maxFrac)
|
||||
}
|
||||
f.MinExponentDigits = 2
|
||||
p.setFlags(f)
|
||||
f.PadRune = 0
|
||||
if p.fmt.WidthPresent {
|
||||
f.Flags &^= number.PadMask
|
||||
if p.fmt.Zero {
|
||||
f.PadRune = f.Digit(0)
|
||||
f.Flags |= number.PadAfterPrefix
|
||||
} else {
|
||||
f.PadRune = ' '
|
||||
f.Flags |= number.PadBeforePrefix
|
||||
}
|
||||
p.updatePadding(f)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *printer) fmtDecimalInt(v uint64, isSigned bool) {
|
||||
var d number.Decimal
|
||||
|
||||
f := &p.toDecimal
|
||||
if p.fmt.PrecPresent {
|
||||
p.setFlags(f)
|
||||
f.MinIntegerDigits = uint8(p.fmt.Prec)
|
||||
f.MaxIntegerDigits = 0
|
||||
f.MinFractionDigits = 0
|
||||
f.MaxFractionDigits = 0
|
||||
if p.fmt.WidthPresent {
|
||||
p.updatePadding(f)
|
||||
}
|
||||
} else {
|
||||
p.initDecimal(0, 0)
|
||||
}
|
||||
d.ConvertInt(p.toDecimal.RoundingContext, isSigned, v)
|
||||
|
||||
out := p.toDecimal.Format([]byte(nil), &d)
|
||||
p.Buffer.Write(out)
|
||||
}
|
||||
|
||||
func (p *printer) fmtDecimalFloat(v float64, size, prec int) {
|
||||
var d number.Decimal
|
||||
if p.fmt.PrecPresent {
|
||||
prec = p.fmt.Prec
|
||||
}
|
||||
p.initDecimal(prec, prec)
|
||||
d.ConvertFloat(p.toDecimal.RoundingContext, v, size)
|
||||
|
||||
out := p.toDecimal.Format([]byte(nil), &d)
|
||||
p.Buffer.Write(out)
|
||||
}
|
||||
|
||||
func (p *printer) fmtVariableFloat(v float64, size int) {
|
||||
prec := -1
|
||||
if p.fmt.PrecPresent {
|
||||
prec = p.fmt.Prec
|
||||
}
|
||||
var d number.Decimal
|
||||
p.initScientific(0, prec)
|
||||
d.ConvertFloat(p.toScientific.RoundingContext, v, size)
|
||||
|
||||
// Copy logic of 'g' formatting from strconv. It is simplified a bit as
|
||||
// we don't have to mind having prec > len(d.Digits).
|
||||
shortest := prec < 0
|
||||
ePrec := prec
|
||||
if shortest {
|
||||
prec = len(d.Digits)
|
||||
ePrec = 6
|
||||
} else if prec == 0 {
|
||||
prec = 1
|
||||
ePrec = 1
|
||||
}
|
||||
exp := int(d.Exp) - 1
|
||||
if exp < -4 || exp >= ePrec {
|
||||
p.initScientific(0, prec)
|
||||
|
||||
out := p.toScientific.Format([]byte(nil), &d)
|
||||
p.Buffer.Write(out)
|
||||
} else {
|
||||
if prec > int(d.Exp) {
|
||||
prec = len(d.Digits)
|
||||
}
|
||||
if prec -= int(d.Exp); prec < 0 {
|
||||
prec = 0
|
||||
}
|
||||
p.initDecimal(0, prec)
|
||||
|
||||
out := p.toDecimal.Format([]byte(nil), &d)
|
||||
p.Buffer.Write(out)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *printer) fmtScientific(v float64, size, prec int) {
|
||||
var d number.Decimal
|
||||
if p.fmt.PrecPresent {
|
||||
prec = p.fmt.Prec
|
||||
}
|
||||
p.initScientific(prec, prec)
|
||||
rc := p.toScientific.RoundingContext
|
||||
d.ConvertFloat(rc, v, size)
|
||||
|
||||
out := p.toScientific.Format([]byte(nil), &d)
|
||||
p.Buffer.Write(out)
|
||||
|
||||
}
|
||||
|
||||
// fmtComplex formats a complex number v with
|
||||
// r = real(v) and j = imag(v) as (r+ji) using
|
||||
// fmtFloat for r and j formatting.
|
||||
func (p *printer) fmtComplex(v complex128, size int, verb rune) {
|
||||
// Make sure any unsupported verbs are found before the
|
||||
// calls to fmtFloat to not generate an incorrect error string.
|
||||
switch verb {
|
||||
case 'v', 'b', 'g', 'G', 'f', 'F', 'e', 'E':
|
||||
p.WriteByte('(')
|
||||
p.fmtFloat(real(v), size/2, verb)
|
||||
// Imaginary part always has a sign.
|
||||
if math.IsNaN(imag(v)) {
|
||||
// By CLDR's rules, NaNs do not use patterns or signs. As this code
|
||||
// relies on AlwaysSign working for imaginary parts, we need to
|
||||
// manually handle NaNs.
|
||||
f := &p.toScientific
|
||||
p.setFlags(f)
|
||||
p.updatePadding(f)
|
||||
p.setFlags(f)
|
||||
nan := f.Symbol(number.SymNan)
|
||||
extra := 0
|
||||
if w, ok := p.Width(); ok {
|
||||
extra = w - utf8.RuneCountInString(nan) - 1
|
||||
}
|
||||
if f.Flags&number.PadAfterNumber == 0 {
|
||||
for ; extra > 0; extra-- {
|
||||
p.WriteRune(f.PadRune)
|
||||
}
|
||||
}
|
||||
p.WriteString(f.Symbol(number.SymPlusSign))
|
||||
p.WriteString(nan)
|
||||
for ; extra > 0; extra-- {
|
||||
p.WriteRune(f.PadRune)
|
||||
}
|
||||
p.WriteString("i)")
|
||||
return
|
||||
}
|
||||
oldPlus := p.fmt.Plus
|
||||
p.fmt.Plus = true
|
||||
p.fmtFloat(imag(v), size/2, verb)
|
||||
p.WriteString("i)") // TODO: use symbol?
|
||||
p.fmt.Plus = oldPlus
|
||||
default:
|
||||
p.badVerb(verb)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *printer) fmtString(v string, verb rune) {
|
||||
switch verb {
|
||||
case 'v':
|
||||
if p.fmt.SharpV {
|
||||
p.fmt.fmt_q(v)
|
||||
} else {
|
||||
p.fmt.fmt_s(v)
|
||||
}
|
||||
case 's':
|
||||
p.fmt.fmt_s(v)
|
||||
case 'x':
|
||||
p.fmt.fmt_sx(v, ldigits)
|
||||
case 'X':
|
||||
p.fmt.fmt_sx(v, udigits)
|
||||
case 'q':
|
||||
p.fmt.fmt_q(v)
|
||||
case 'm':
|
||||
ctx := p.cat.Context(p.tag, rawPrinter{p})
|
||||
if ctx.Execute(v) == catalog.ErrNotFound {
|
||||
p.WriteString(v)
|
||||
}
|
||||
default:
|
||||
p.badVerb(verb)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *printer) fmtBytes(v []byte, verb rune, typeString string) {
|
||||
switch verb {
|
||||
case 'v', 'd':
|
||||
if p.fmt.SharpV {
|
||||
p.WriteString(typeString)
|
||||
if v == nil {
|
||||
p.WriteString(nilParenString)
|
||||
return
|
||||
}
|
||||
p.WriteByte('{')
|
||||
for i, c := range v {
|
||||
if i > 0 {
|
||||
p.WriteString(commaSpaceString)
|
||||
}
|
||||
p.fmt0x64(uint64(c), true)
|
||||
}
|
||||
p.WriteByte('}')
|
||||
} else {
|
||||
p.WriteByte('[')
|
||||
for i, c := range v {
|
||||
if i > 0 {
|
||||
p.WriteByte(' ')
|
||||
}
|
||||
p.fmt.fmt_integer(uint64(c), 10, unsigned, ldigits)
|
||||
}
|
||||
p.WriteByte(']')
|
||||
}
|
||||
case 's':
|
||||
p.fmt.fmt_s(string(v))
|
||||
case 'x':
|
||||
p.fmt.fmt_bx(v, ldigits)
|
||||
case 'X':
|
||||
p.fmt.fmt_bx(v, udigits)
|
||||
case 'q':
|
||||
p.fmt.fmt_q(string(v))
|
||||
default:
|
||||
p.printValue(reflect.ValueOf(v), verb, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *printer) fmtPointer(value reflect.Value, verb rune) {
|
||||
var u uintptr
|
||||
switch value.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
|
||||
u = value.Pointer()
|
||||
default:
|
||||
p.badVerb(verb)
|
||||
return
|
||||
}
|
||||
|
||||
switch verb {
|
||||
case 'v':
|
||||
if p.fmt.SharpV {
|
||||
p.WriteByte('(')
|
||||
p.WriteString(value.Type().String())
|
||||
p.WriteString(")(")
|
||||
if u == 0 {
|
||||
p.WriteString(nilString)
|
||||
} else {
|
||||
p.fmt0x64(uint64(u), true)
|
||||
}
|
||||
p.WriteByte(')')
|
||||
} else {
|
||||
if u == 0 {
|
||||
p.fmt.padString(nilAngleString)
|
||||
} else {
|
||||
p.fmt0x64(uint64(u), !p.fmt.Sharp)
|
||||
}
|
||||
}
|
||||
case 'p':
|
||||
p.fmt0x64(uint64(u), !p.fmt.Sharp)
|
||||
case 'b', 'o', 'd', 'x', 'X':
|
||||
if verb == 'd' {
|
||||
p.fmt.Sharp = true // Print as standard go. TODO: does this make sense?
|
||||
}
|
||||
p.fmtInteger(uint64(u), unsigned, verb)
|
||||
default:
|
||||
p.badVerb(verb)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *printer) catchPanic(arg interface{}, verb rune) {
|
||||
if err := recover(); err != nil {
|
||||
// If it's a nil pointer, just say "<nil>". The likeliest causes are a
|
||||
// Stringer that fails to guard against nil or a nil pointer for a
|
||||
// value receiver, and in either case, "<nil>" is a nice result.
|
||||
if v := reflect.ValueOf(arg); v.Kind() == reflect.Ptr && v.IsNil() {
|
||||
p.WriteString(nilAngleString)
|
||||
return
|
||||
}
|
||||
// Otherwise print a concise panic message. Most of the time the panic
|
||||
// value will print itself nicely.
|
||||
if p.panicking {
|
||||
// Nested panics; the recursion in printArg cannot succeed.
|
||||
panic(err)
|
||||
}
|
||||
|
||||
oldFlags := p.fmt.Parser
|
||||
// For this output we want default behavior.
|
||||
p.fmt.ClearFlags()
|
||||
|
||||
p.WriteString(percentBangString)
|
||||
p.WriteRune(verb)
|
||||
p.WriteString(panicString)
|
||||
p.panicking = true
|
||||
p.printArg(err, 'v')
|
||||
p.panicking = false
|
||||
p.WriteByte(')')
|
||||
|
||||
p.fmt.Parser = oldFlags
|
||||
}
|
||||
}
|
||||
|
||||
func (p *printer) handleMethods(verb rune) (handled bool) {
|
||||
if p.erroring {
|
||||
return
|
||||
}
|
||||
// Is it a Formatter?
|
||||
if formatter, ok := p.arg.(format.Formatter); ok {
|
||||
handled = true
|
||||
defer p.catchPanic(p.arg, verb)
|
||||
formatter.Format(p, verb)
|
||||
return
|
||||
}
|
||||
if formatter, ok := p.arg.(fmt.Formatter); ok {
|
||||
handled = true
|
||||
defer p.catchPanic(p.arg, verb)
|
||||
formatter.Format(p, verb)
|
||||
return
|
||||
}
|
||||
|
||||
// If we're doing Go syntax and the argument knows how to supply it, take care of it now.
|
||||
if p.fmt.SharpV {
|
||||
if stringer, ok := p.arg.(fmt.GoStringer); ok {
|
||||
handled = true
|
||||
defer p.catchPanic(p.arg, verb)
|
||||
// Print the result of GoString unadorned.
|
||||
p.fmt.fmt_s(stringer.GoString())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// If a string is acceptable according to the format, see if
|
||||
// the value satisfies one of the string-valued interfaces.
|
||||
// Println etc. set verb to %v, which is "stringable".
|
||||
switch verb {
|
||||
case 'v', 's', 'x', 'X', 'q':
|
||||
// Is it an error or Stringer?
|
||||
// The duplication in the bodies is necessary:
|
||||
// setting handled and deferring catchPanic
|
||||
// must happen before calling the method.
|
||||
switch v := p.arg.(type) {
|
||||
case error:
|
||||
handled = true
|
||||
defer p.catchPanic(p.arg, verb)
|
||||
p.fmtString(v.Error(), verb)
|
||||
return
|
||||
|
||||
case fmt.Stringer:
|
||||
handled = true
|
||||
defer p.catchPanic(p.arg, verb)
|
||||
p.fmtString(v.String(), verb)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *printer) printArg(arg interface{}, verb rune) {
|
||||
p.arg = arg
|
||||
p.value = reflect.Value{}
|
||||
|
||||
if arg == nil {
|
||||
switch verb {
|
||||
case 'T', 'v':
|
||||
p.fmt.padString(nilAngleString)
|
||||
default:
|
||||
p.badVerb(verb)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Special processing considerations.
|
||||
// %T (the value's type) and %p (its address) are special; we always do them first.
|
||||
switch verb {
|
||||
case 'T':
|
||||
p.fmt.fmt_s(reflect.TypeOf(arg).String())
|
||||
return
|
||||
case 'p':
|
||||
p.fmtPointer(reflect.ValueOf(arg), 'p')
|
||||
return
|
||||
}
|
||||
|
||||
// Some types can be done without reflection.
|
||||
switch f := arg.(type) {
|
||||
case bool:
|
||||
p.fmtBool(f, verb)
|
||||
case float32:
|
||||
p.fmtFloat(float64(f), 32, verb)
|
||||
case float64:
|
||||
p.fmtFloat(f, 64, verb)
|
||||
case complex64:
|
||||
p.fmtComplex(complex128(f), 64, verb)
|
||||
case complex128:
|
||||
p.fmtComplex(f, 128, verb)
|
||||
case int:
|
||||
p.fmtInteger(uint64(f), signed, verb)
|
||||
case int8:
|
||||
p.fmtInteger(uint64(f), signed, verb)
|
||||
case int16:
|
||||
p.fmtInteger(uint64(f), signed, verb)
|
||||
case int32:
|
||||
p.fmtInteger(uint64(f), signed, verb)
|
||||
case int64:
|
||||
p.fmtInteger(uint64(f), signed, verb)
|
||||
case uint:
|
||||
p.fmtInteger(uint64(f), unsigned, verb)
|
||||
case uint8:
|
||||
p.fmtInteger(uint64(f), unsigned, verb)
|
||||
case uint16:
|
||||
p.fmtInteger(uint64(f), unsigned, verb)
|
||||
case uint32:
|
||||
p.fmtInteger(uint64(f), unsigned, verb)
|
||||
case uint64:
|
||||
p.fmtInteger(f, unsigned, verb)
|
||||
case uintptr:
|
||||
p.fmtInteger(uint64(f), unsigned, verb)
|
||||
case string:
|
||||
p.fmtString(f, verb)
|
||||
case []byte:
|
||||
p.fmtBytes(f, verb, "[]byte")
|
||||
case reflect.Value:
|
||||
// Handle extractable values with special methods
|
||||
// since printValue does not handle them at depth 0.
|
||||
if f.IsValid() && f.CanInterface() {
|
||||
p.arg = f.Interface()
|
||||
if p.handleMethods(verb) {
|
||||
return
|
||||
}
|
||||
}
|
||||
p.printValue(f, verb, 0)
|
||||
default:
|
||||
// If the type is not simple, it might have methods.
|
||||
if !p.handleMethods(verb) {
|
||||
// Need to use reflection, since the type had no
|
||||
// interface methods that could be used for formatting.
|
||||
p.printValue(reflect.ValueOf(f), verb, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// printValue is similar to printArg but starts with a reflect value, not an interface{} value.
|
||||
// It does not handle 'p' and 'T' verbs because these should have been already handled by printArg.
|
||||
func (p *printer) printValue(value reflect.Value, verb rune, depth int) {
|
||||
// Handle values with special methods if not already handled by printArg (depth == 0).
|
||||
if depth > 0 && value.IsValid() && value.CanInterface() {
|
||||
p.arg = value.Interface()
|
||||
if p.handleMethods(verb) {
|
||||
return
|
||||
}
|
||||
}
|
||||
p.arg = nil
|
||||
p.value = value
|
||||
|
||||
switch f := value; value.Kind() {
|
||||
case reflect.Invalid:
|
||||
if depth == 0 {
|
||||
p.WriteString(invReflectString)
|
||||
} else {
|
||||
switch verb {
|
||||
case 'v':
|
||||
p.WriteString(nilAngleString)
|
||||
default:
|
||||
p.badVerb(verb)
|
||||
}
|
||||
}
|
||||
case reflect.Bool:
|
||||
p.fmtBool(f.Bool(), verb)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
p.fmtInteger(uint64(f.Int()), signed, verb)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
p.fmtInteger(f.Uint(), unsigned, verb)
|
||||
case reflect.Float32:
|
||||
p.fmtFloat(f.Float(), 32, verb)
|
||||
case reflect.Float64:
|
||||
p.fmtFloat(f.Float(), 64, verb)
|
||||
case reflect.Complex64:
|
||||
p.fmtComplex(f.Complex(), 64, verb)
|
||||
case reflect.Complex128:
|
||||
p.fmtComplex(f.Complex(), 128, verb)
|
||||
case reflect.String:
|
||||
p.fmtString(f.String(), verb)
|
||||
case reflect.Map:
|
||||
if p.fmt.SharpV {
|
||||
p.WriteString(f.Type().String())
|
||||
if f.IsNil() {
|
||||
p.WriteString(nilParenString)
|
||||
return
|
||||
}
|
||||
p.WriteByte('{')
|
||||
} else {
|
||||
p.WriteString(mapString)
|
||||
}
|
||||
keys := f.MapKeys()
|
||||
for i, key := range keys {
|
||||
if i > 0 {
|
||||
if p.fmt.SharpV {
|
||||
p.WriteString(commaSpaceString)
|
||||
} else {
|
||||
p.WriteByte(' ')
|
||||
}
|
||||
}
|
||||
p.printValue(key, verb, depth+1)
|
||||
p.WriteByte(':')
|
||||
p.printValue(f.MapIndex(key), verb, depth+1)
|
||||
}
|
||||
if p.fmt.SharpV {
|
||||
p.WriteByte('}')
|
||||
} else {
|
||||
p.WriteByte(']')
|
||||
}
|
||||
case reflect.Struct:
|
||||
if p.fmt.SharpV {
|
||||
p.WriteString(f.Type().String())
|
||||
}
|
||||
p.WriteByte('{')
|
||||
for i := 0; i < f.NumField(); i++ {
|
||||
if i > 0 {
|
||||
if p.fmt.SharpV {
|
||||
p.WriteString(commaSpaceString)
|
||||
} else {
|
||||
p.WriteByte(' ')
|
||||
}
|
||||
}
|
||||
if p.fmt.PlusV || p.fmt.SharpV {
|
||||
if name := f.Type().Field(i).Name; name != "" {
|
||||
p.WriteString(name)
|
||||
p.WriteByte(':')
|
||||
}
|
||||
}
|
||||
p.printValue(getField(f, i), verb, depth+1)
|
||||
}
|
||||
p.WriteByte('}')
|
||||
case reflect.Interface:
|
||||
value := f.Elem()
|
||||
if !value.IsValid() {
|
||||
if p.fmt.SharpV {
|
||||
p.WriteString(f.Type().String())
|
||||
p.WriteString(nilParenString)
|
||||
} else {
|
||||
p.WriteString(nilAngleString)
|
||||
}
|
||||
} else {
|
||||
p.printValue(value, verb, depth+1)
|
||||
}
|
||||
case reflect.Array, reflect.Slice:
|
||||
switch verb {
|
||||
case 's', 'q', 'x', 'X':
|
||||
// Handle byte and uint8 slices and arrays special for the above verbs.
|
||||
t := f.Type()
|
||||
if t.Elem().Kind() == reflect.Uint8 {
|
||||
var bytes []byte
|
||||
if f.Kind() == reflect.Slice {
|
||||
bytes = f.Bytes()
|
||||
} else if f.CanAddr() {
|
||||
bytes = f.Slice(0, f.Len()).Bytes()
|
||||
} else {
|
||||
// We have an array, but we cannot Slice() a non-addressable array,
|
||||
// so we build a slice by hand. This is a rare case but it would be nice
|
||||
// if reflection could help a little more.
|
||||
bytes = make([]byte, f.Len())
|
||||
for i := range bytes {
|
||||
bytes[i] = byte(f.Index(i).Uint())
|
||||
}
|
||||
}
|
||||
p.fmtBytes(bytes, verb, t.String())
|
||||
return
|
||||
}
|
||||
}
|
||||
if p.fmt.SharpV {
|
||||
p.WriteString(f.Type().String())
|
||||
if f.Kind() == reflect.Slice && f.IsNil() {
|
||||
p.WriteString(nilParenString)
|
||||
return
|
||||
}
|
||||
p.WriteByte('{')
|
||||
for i := 0; i < f.Len(); i++ {
|
||||
if i > 0 {
|
||||
p.WriteString(commaSpaceString)
|
||||
}
|
||||
p.printValue(f.Index(i), verb, depth+1)
|
||||
}
|
||||
p.WriteByte('}')
|
||||
} else {
|
||||
p.WriteByte('[')
|
||||
for i := 0; i < f.Len(); i++ {
|
||||
if i > 0 {
|
||||
p.WriteByte(' ')
|
||||
}
|
||||
p.printValue(f.Index(i), verb, depth+1)
|
||||
}
|
||||
p.WriteByte(']')
|
||||
}
|
||||
case reflect.Ptr:
|
||||
// pointer to array or slice or struct? ok at top level
|
||||
// but not embedded (avoid loops)
|
||||
if depth == 0 && f.Pointer() != 0 {
|
||||
switch a := f.Elem(); a.Kind() {
|
||||
case reflect.Array, reflect.Slice, reflect.Struct, reflect.Map:
|
||||
p.WriteByte('&')
|
||||
p.printValue(a, verb, depth+1)
|
||||
return
|
||||
}
|
||||
}
|
||||
fallthrough
|
||||
case reflect.Chan, reflect.Func, reflect.UnsafePointer:
|
||||
p.fmtPointer(f, verb)
|
||||
default:
|
||||
p.unknownType(f)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *printer) badArgNum(verb rune) {
|
||||
p.WriteString(percentBangString)
|
||||
p.WriteRune(verb)
|
||||
p.WriteString(badIndexString)
|
||||
}
|
||||
|
||||
func (p *printer) missingArg(verb rune) {
|
||||
p.WriteString(percentBangString)
|
||||
p.WriteRune(verb)
|
||||
p.WriteString(missingString)
|
||||
}
|
||||
|
||||
func (p *printer) doPrintf(fmt string) {
|
||||
for p.fmt.Parser.SetFormat(fmt); p.fmt.Scan(); {
|
||||
switch p.fmt.Status {
|
||||
case format.StatusText:
|
||||
p.WriteString(p.fmt.Text())
|
||||
case format.StatusSubstitution:
|
||||
p.printArg(p.Arg(p.fmt.ArgNum), p.fmt.Verb)
|
||||
case format.StatusBadWidthSubstitution:
|
||||
p.WriteString(badWidthString)
|
||||
p.printArg(p.Arg(p.fmt.ArgNum), p.fmt.Verb)
|
||||
case format.StatusBadPrecSubstitution:
|
||||
p.WriteString(badPrecString)
|
||||
p.printArg(p.Arg(p.fmt.ArgNum), p.fmt.Verb)
|
||||
case format.StatusNoVerb:
|
||||
p.WriteString(noVerbString)
|
||||
case format.StatusBadArgNum:
|
||||
p.badArgNum(p.fmt.Verb)
|
||||
case format.StatusMissingArg:
|
||||
p.missingArg(p.fmt.Verb)
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
// Check for extra arguments, but only if there was at least one ordered
|
||||
// argument. Note that this behavior is necessarily different from fmt:
|
||||
// different variants of messages may opt to drop some or all of the
|
||||
// arguments.
|
||||
if !p.fmt.Reordered && p.fmt.ArgNum < len(p.fmt.Args) && p.fmt.ArgNum != 0 {
|
||||
p.fmt.ClearFlags()
|
||||
p.WriteString(extraString)
|
||||
for i, arg := range p.fmt.Args[p.fmt.ArgNum:] {
|
||||
if i > 0 {
|
||||
p.WriteString(commaSpaceString)
|
||||
}
|
||||
if arg == nil {
|
||||
p.WriteString(nilAngleString)
|
||||
} else {
|
||||
p.WriteString(reflect.TypeOf(arg).String())
|
||||
p.WriteString("=")
|
||||
p.printArg(arg, 'v')
|
||||
}
|
||||
}
|
||||
p.WriteByte(')')
|
||||
}
|
||||
}
|
||||
|
||||
func (p *printer) doPrint(a []interface{}) {
|
||||
prevString := false
|
||||
for argNum, arg := range a {
|
||||
isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String
|
||||
// Add a space between two non-string arguments.
|
||||
if argNum > 0 && !isString && !prevString {
|
||||
p.WriteByte(' ')
|
||||
}
|
||||
p.printArg(arg, 'v')
|
||||
prevString = isString
|
||||
}
|
||||
}
|
||||
|
||||
// doPrintln is like doPrint but always adds a space between arguments
|
||||
// and a newline after the last argument.
|
||||
func (p *printer) doPrintln(a []interface{}) {
|
||||
for argNum, arg := range a {
|
||||
if argNum > 0 {
|
||||
p.WriteByte(' ')
|
||||
}
|
||||
p.printArg(arg, 'v')
|
||||
}
|
||||
p.WriteByte('\n')
|
||||
}
|
187
vendor/golang.org/x/text/runes/cond.go
generated
vendored
187
vendor/golang.org/x/text/runes/cond.go
generated
vendored
@ -1,187 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package runes
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// Note: below we pass invalid UTF-8 to the tIn and tNotIn transformers as is.
|
||||
// This is done for various reasons:
|
||||
// - To retain the semantics of the Nop transformer: if input is passed to a Nop
|
||||
// one would expect it to be unchanged.
|
||||
// - It would be very expensive to pass a converted RuneError to a transformer:
|
||||
// a transformer might need more source bytes after RuneError, meaning that
|
||||
// the only way to pass it safely is to create a new buffer and manage the
|
||||
// intermingling of RuneErrors and normal input.
|
||||
// - Many transformers leave ill-formed UTF-8 as is, so this is not
|
||||
// inconsistent. Generally ill-formed UTF-8 is only replaced if it is a
|
||||
// logical consequence of the operation (as for Map) or if it otherwise would
|
||||
// pose security concerns (as for Remove).
|
||||
// - An alternative would be to return an error on ill-formed UTF-8, but this
|
||||
// would be inconsistent with other operations.
|
||||
|
||||
// If returns a transformer that applies tIn to consecutive runes for which
|
||||
// s.Contains(r) and tNotIn to consecutive runes for which !s.Contains(r). Reset
|
||||
// is called on tIn and tNotIn at the start of each run. A Nop transformer will
|
||||
// substitute a nil value passed to tIn or tNotIn. Invalid UTF-8 is translated
|
||||
// to RuneError to determine which transformer to apply, but is passed as is to
|
||||
// the respective transformer.
|
||||
func If(s Set, tIn, tNotIn transform.Transformer) Transformer {
|
||||
if tIn == nil && tNotIn == nil {
|
||||
return Transformer{transform.Nop}
|
||||
}
|
||||
if tIn == nil {
|
||||
tIn = transform.Nop
|
||||
}
|
||||
if tNotIn == nil {
|
||||
tNotIn = transform.Nop
|
||||
}
|
||||
sIn, ok := tIn.(transform.SpanningTransformer)
|
||||
if !ok {
|
||||
sIn = dummySpan{tIn}
|
||||
}
|
||||
sNotIn, ok := tNotIn.(transform.SpanningTransformer)
|
||||
if !ok {
|
||||
sNotIn = dummySpan{tNotIn}
|
||||
}
|
||||
|
||||
a := &cond{
|
||||
tIn: sIn,
|
||||
tNotIn: sNotIn,
|
||||
f: s.Contains,
|
||||
}
|
||||
a.Reset()
|
||||
return Transformer{a}
|
||||
}
|
||||
|
||||
type dummySpan struct{ transform.Transformer }
|
||||
|
||||
func (d dummySpan) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
return 0, transform.ErrEndOfSpan
|
||||
}
|
||||
|
||||
type cond struct {
|
||||
tIn, tNotIn transform.SpanningTransformer
|
||||
f func(rune) bool
|
||||
check func(rune) bool // current check to perform
|
||||
t transform.SpanningTransformer // current transformer to use
|
||||
}
|
||||
|
||||
// Reset implements transform.Transformer.
|
||||
func (t *cond) Reset() {
|
||||
t.check = t.is
|
||||
t.t = t.tIn
|
||||
t.t.Reset() // notIn will be reset on first usage.
|
||||
}
|
||||
|
||||
func (t *cond) is(r rune) bool {
|
||||
if t.f(r) {
|
||||
return true
|
||||
}
|
||||
t.check = t.isNot
|
||||
t.t = t.tNotIn
|
||||
t.tNotIn.Reset()
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *cond) isNot(r rune) bool {
|
||||
if !t.f(r) {
|
||||
return true
|
||||
}
|
||||
t.check = t.is
|
||||
t.t = t.tIn
|
||||
t.tIn.Reset()
|
||||
return false
|
||||
}
|
||||
|
||||
// This implementation of Span doesn't help all too much, but it needs to be
|
||||
// there to satisfy this package's Transformer interface.
|
||||
// TODO: there are certainly room for improvements, though. For example, if
|
||||
// t.t == transform.Nop (which will a common occurrence) it will save a bundle
|
||||
// to special-case that loop.
|
||||
func (t *cond) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
p := 0
|
||||
for n < len(src) && err == nil {
|
||||
// Don't process too much at a time as the Spanner that will be
|
||||
// called on this block may terminate early.
|
||||
const maxChunk = 4096
|
||||
max := len(src)
|
||||
if v := n + maxChunk; v < max {
|
||||
max = v
|
||||
}
|
||||
atEnd := false
|
||||
size := 0
|
||||
current := t.t
|
||||
for ; p < max; p += size {
|
||||
r := rune(src[p])
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
} else if r, size = utf8.DecodeRune(src[p:]); size == 1 {
|
||||
if !atEOF && !utf8.FullRune(src[p:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
if !t.check(r) {
|
||||
// The next rune will be the start of a new run.
|
||||
atEnd = true
|
||||
break
|
||||
}
|
||||
}
|
||||
n2, err2 := current.Span(src[n:p], atEnd || (atEOF && p == len(src)))
|
||||
n += n2
|
||||
if err2 != nil {
|
||||
return n, err2
|
||||
}
|
||||
// At this point either err != nil or t.check will pass for the rune at p.
|
||||
p = n + size
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (t *cond) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
p := 0
|
||||
for nSrc < len(src) && err == nil {
|
||||
// Don't process too much at a time, as the work might be wasted if the
|
||||
// destination buffer isn't large enough to hold the result or a
|
||||
// transform returns an error early.
|
||||
const maxChunk = 4096
|
||||
max := len(src)
|
||||
if n := nSrc + maxChunk; n < len(src) {
|
||||
max = n
|
||||
}
|
||||
atEnd := false
|
||||
size := 0
|
||||
current := t.t
|
||||
for ; p < max; p += size {
|
||||
r := rune(src[p])
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
} else if r, size = utf8.DecodeRune(src[p:]); size == 1 {
|
||||
if !atEOF && !utf8.FullRune(src[p:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
if !t.check(r) {
|
||||
// The next rune will be the start of a new run.
|
||||
atEnd = true
|
||||
break
|
||||
}
|
||||
}
|
||||
nDst2, nSrc2, err2 := current.Transform(dst[nDst:], src[nSrc:p], atEnd || (atEOF && p == len(src)))
|
||||
nDst += nDst2
|
||||
nSrc += nSrc2
|
||||
if err2 != nil {
|
||||
return nDst, nSrc, err2
|
||||
}
|
||||
// At this point either err != nil or t.check will pass for the rune at p.
|
||||
p = nSrc + size
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
355
vendor/golang.org/x/text/runes/runes.go
generated
vendored
355
vendor/golang.org/x/text/runes/runes.go
generated
vendored
@ -1,355 +0,0 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package runes provide transforms for UTF-8 encoded text.
|
||||
package runes // import "golang.org/x/text/runes"
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// A Set is a collection of runes.
|
||||
type Set interface {
|
||||
// Contains returns true if r is contained in the set.
|
||||
Contains(r rune) bool
|
||||
}
|
||||
|
||||
type setFunc func(rune) bool
|
||||
|
||||
func (s setFunc) Contains(r rune) bool {
|
||||
return s(r)
|
||||
}
|
||||
|
||||
// Note: using funcs here instead of wrapping types result in cleaner
|
||||
// documentation and a smaller API.
|
||||
|
||||
// In creates a Set with a Contains method that returns true for all runes in
|
||||
// the given RangeTable.
|
||||
func In(rt *unicode.RangeTable) Set {
|
||||
return setFunc(func(r rune) bool { return unicode.Is(rt, r) })
|
||||
}
|
||||
|
||||
// NotIn creates a Set with a Contains method that returns true for all runes not
|
||||
// in the given RangeTable.
|
||||
func NotIn(rt *unicode.RangeTable) Set {
|
||||
return setFunc(func(r rune) bool { return !unicode.Is(rt, r) })
|
||||
}
|
||||
|
||||
// Predicate creates a Set with a Contains method that returns f(r).
|
||||
func Predicate(f func(rune) bool) Set {
|
||||
return setFunc(f)
|
||||
}
|
||||
|
||||
// Transformer implements the transform.Transformer interface.
|
||||
type Transformer struct {
|
||||
t transform.SpanningTransformer
|
||||
}
|
||||
|
||||
func (t Transformer) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
return t.t.Transform(dst, src, atEOF)
|
||||
}
|
||||
|
||||
func (t Transformer) Span(b []byte, atEOF bool) (n int, err error) {
|
||||
return t.t.Span(b, atEOF)
|
||||
}
|
||||
|
||||
func (t Transformer) Reset() { t.t.Reset() }
|
||||
|
||||
// Bytes returns a new byte slice with the result of converting b using t. It
|
||||
// calls Reset on t. It returns nil if any error was found. This can only happen
|
||||
// if an error-producing Transformer is passed to If.
|
||||
func (t Transformer) Bytes(b []byte) []byte {
|
||||
b, _, err := transform.Bytes(t, b)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// String returns a string with the result of converting s using t. It calls
|
||||
// Reset on t. It returns the empty string if any error was found. This can only
|
||||
// happen if an error-producing Transformer is passed to If.
|
||||
func (t Transformer) String(s string) string {
|
||||
s, _, err := transform.String(t, s)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// - Copy: copying strings and bytes in whole-rune units.
|
||||
// - Validation (maybe)
|
||||
// - Well-formed-ness (maybe)
|
||||
|
||||
const runeErrorString = string(utf8.RuneError)
|
||||
|
||||
// Remove returns a Transformer that removes runes r for which s.Contains(r).
|
||||
// Illegal input bytes are replaced by RuneError before being passed to f.
|
||||
func Remove(s Set) Transformer {
|
||||
if f, ok := s.(setFunc); ok {
|
||||
// This little trick cuts the running time of BenchmarkRemove for sets
|
||||
// created by Predicate roughly in half.
|
||||
// TODO: special-case RangeTables as well.
|
||||
return Transformer{remove(f)}
|
||||
}
|
||||
return Transformer{remove(s.Contains)}
|
||||
}
|
||||
|
||||
// TODO: remove transform.RemoveFunc.
|
||||
|
||||
type remove func(r rune) bool
|
||||
|
||||
func (remove) Reset() {}
|
||||
|
||||
// Span implements transform.Spanner.
|
||||
func (t remove) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
for r, size := rune(0), 0; n < len(src); {
|
||||
if r = rune(src[n]); r < utf8.RuneSelf {
|
||||
size = 1
|
||||
} else if r, size = utf8.DecodeRune(src[n:]); size == 1 {
|
||||
// Invalid rune.
|
||||
if !atEOF && !utf8.FullRune(src[n:]) {
|
||||
err = transform.ErrShortSrc
|
||||
} else {
|
||||
err = transform.ErrEndOfSpan
|
||||
}
|
||||
break
|
||||
}
|
||||
if t(r) {
|
||||
err = transform.ErrEndOfSpan
|
||||
break
|
||||
}
|
||||
n += size
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Transform implements transform.Transformer.
|
||||
func (t remove) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
for r, size := rune(0), 0; nSrc < len(src); {
|
||||
if r = rune(src[nSrc]); r < utf8.RuneSelf {
|
||||
size = 1
|
||||
} else if r, size = utf8.DecodeRune(src[nSrc:]); size == 1 {
|
||||
// Invalid rune.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
// We replace illegal bytes with RuneError. Not doing so might
|
||||
// otherwise turn a sequence of invalid UTF-8 into valid UTF-8.
|
||||
// The resulting byte sequence may subsequently contain runes
|
||||
// for which t(r) is true that were passed unnoticed.
|
||||
if !t(utf8.RuneError) {
|
||||
if nDst+3 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = runeErrorString[0]
|
||||
dst[nDst+1] = runeErrorString[1]
|
||||
dst[nDst+2] = runeErrorString[2]
|
||||
nDst += 3
|
||||
}
|
||||
nSrc++
|
||||
continue
|
||||
}
|
||||
if t(r) {
|
||||
nSrc += size
|
||||
continue
|
||||
}
|
||||
if nDst+size > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
for i := 0; i < size; i++ {
|
||||
dst[nDst] = src[nSrc]
|
||||
nDst++
|
||||
nSrc++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Map returns a Transformer that maps the runes in the input using the given
|
||||
// mapping. Illegal bytes in the input are converted to utf8.RuneError before
|
||||
// being passed to the mapping func.
|
||||
func Map(mapping func(rune) rune) Transformer {
|
||||
return Transformer{mapper(mapping)}
|
||||
}
|
||||
|
||||
type mapper func(rune) rune
|
||||
|
||||
func (mapper) Reset() {}
|
||||
|
||||
// Span implements transform.Spanner.
|
||||
func (t mapper) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
for r, size := rune(0), 0; n < len(src); n += size {
|
||||
if r = rune(src[n]); r < utf8.RuneSelf {
|
||||
size = 1
|
||||
} else if r, size = utf8.DecodeRune(src[n:]); size == 1 {
|
||||
// Invalid rune.
|
||||
if !atEOF && !utf8.FullRune(src[n:]) {
|
||||
err = transform.ErrShortSrc
|
||||
} else {
|
||||
err = transform.ErrEndOfSpan
|
||||
}
|
||||
break
|
||||
}
|
||||
if t(r) != r {
|
||||
err = transform.ErrEndOfSpan
|
||||
break
|
||||
}
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Transform implements transform.Transformer.
|
||||
func (t mapper) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
var replacement rune
|
||||
var b [utf8.UTFMax]byte
|
||||
|
||||
for r, size := rune(0), 0; nSrc < len(src); {
|
||||
if r = rune(src[nSrc]); r < utf8.RuneSelf {
|
||||
if replacement = t(r); replacement < utf8.RuneSelf {
|
||||
if nDst == len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = byte(replacement)
|
||||
nDst++
|
||||
nSrc++
|
||||
continue
|
||||
}
|
||||
size = 1
|
||||
} else if r, size = utf8.DecodeRune(src[nSrc:]); size == 1 {
|
||||
// Invalid rune.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
|
||||
if replacement = t(utf8.RuneError); replacement == utf8.RuneError {
|
||||
if nDst+3 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = runeErrorString[0]
|
||||
dst[nDst+1] = runeErrorString[1]
|
||||
dst[nDst+2] = runeErrorString[2]
|
||||
nDst += 3
|
||||
nSrc++
|
||||
continue
|
||||
}
|
||||
} else if replacement = t(r); replacement == r {
|
||||
if nDst+size > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
for i := 0; i < size; i++ {
|
||||
dst[nDst] = src[nSrc]
|
||||
nDst++
|
||||
nSrc++
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
n := utf8.EncodeRune(b[:], replacement)
|
||||
|
||||
if nDst+n > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
dst[nDst] = b[i]
|
||||
nDst++
|
||||
}
|
||||
nSrc += size
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ReplaceIllFormed returns a transformer that replaces all input bytes that are
|
||||
// not part of a well-formed UTF-8 code sequence with utf8.RuneError.
|
||||
func ReplaceIllFormed() Transformer {
|
||||
return Transformer{&replaceIllFormed{}}
|
||||
}
|
||||
|
||||
type replaceIllFormed struct{ transform.NopResetter }
|
||||
|
||||
func (t replaceIllFormed) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
for n < len(src) {
|
||||
// ASCII fast path.
|
||||
if src[n] < utf8.RuneSelf {
|
||||
n++
|
||||
continue
|
||||
}
|
||||
|
||||
r, size := utf8.DecodeRune(src[n:])
|
||||
|
||||
// Look for a valid non-ASCII rune.
|
||||
if r != utf8.RuneError || size != 1 {
|
||||
n += size
|
||||
continue
|
||||
}
|
||||
|
||||
// Look for short source data.
|
||||
if !atEOF && !utf8.FullRune(src[n:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
|
||||
// We have an invalid rune.
|
||||
err = transform.ErrEndOfSpan
|
||||
break
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (t replaceIllFormed) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
for nSrc < len(src) {
|
||||
// ASCII fast path.
|
||||
if r := src[nSrc]; r < utf8.RuneSelf {
|
||||
if nDst == len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = r
|
||||
nDst++
|
||||
nSrc++
|
||||
continue
|
||||
}
|
||||
|
||||
// Look for a valid non-ASCII rune.
|
||||
if _, size := utf8.DecodeRune(src[nSrc:]); size != 1 {
|
||||
if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
nDst += size
|
||||
nSrc += size
|
||||
continue
|
||||
}
|
||||
|
||||
// Look for short source data.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
|
||||
// We have an invalid rune.
|
||||
if nDst+3 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = runeErrorString[0]
|
||||
dst[nDst+1] = runeErrorString[1]
|
||||
dst[nDst+2] = runeErrorString[2]
|
||||
nDst += 3
|
||||
nSrc++
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
Reference in New Issue
Block a user