vendor: update all dependencies

This commit is contained in:
Nick Craig-Wood
2017-07-23 08:51:42 +01:00
parent 0b6fba34a3
commit eb87cf6f12
2008 changed files with 352617 additions and 1004734 deletions
+366
View File
@@ -0,0 +1,366 @@
// 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
// First is used as a Handle to EncodeMessageType, followed by a series of calls
// to EncodeMessage, to implement selecting the first matching Message.
//
// TODO: this can be removed once we either can use type aliases or if the
// internals of this package are merged with the catalog package.
var First Handle = msgFirst
// 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
numFixed
)
const prefix = "golang.org/x/text/internal/catmsg."
var (
mutex sync.Mutex
names = map[string]Handle{
prefix + "Vars": msgVars,
prefix + "First": msgFirst,
prefix + "Raw": msgRaw,
prefix + "String": msgString,
}
handlers = make([]Handler, numFixed)
)
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
}
}
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
}
// 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(1)
// 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
}
+294
View File
@@ -0,0 +1,294 @@
// 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"
"strings"
"testing"
"golang.org/x/text/language"
)
type renderer struct {
args []int
result string
}
func (r *renderer) Arg(i int) interface{} {
if i >= len(r.args) {
return nil
}
return r.args[i]
}
func (r *renderer) Render(s string) {
if r.result != "" {
r.result += "|"
}
r.result += s
}
func TestCodec(t *testing.T) {
type test struct {
args []int
out string
decErr string
}
single := func(out, err string) []test { return []test{{out: out, decErr: err}} }
testCases := []struct {
desc string
m Message
enc string
encErr string
tests []test
}{{
desc: "unused variable",
m: &Var{"name", String("foo")},
encErr: errIsVar.Error(),
tests: single("", ""),
}, {
desc: "empty",
m: empty{},
tests: single("", ""),
}, {
desc: "sequence with empty",
m: seq{empty{}},
tests: single("", ""),
}, {
desc: "raw string",
m: Raw("foo"),
tests: single("foo", ""),
}, {
desc: "raw string no sub",
m: Raw("${foo}"),
enc: "\x02${foo}",
tests: single("${foo}", ""),
}, {
desc: "simple string",
m: String("foo"),
tests: single("foo", ""),
}, {
desc: "missing var",
m: String("foo${bar}"),
enc: "\x03\x03foo\x02\x03bar",
encErr: `unknown var "bar"`,
tests: single("foo|bar", ""),
}, {
desc: "empty var",
m: seq{
&Var{"bar", seq{}},
String("foo${bar}"),
},
enc: "\x00\x05\x04\x02bar\x03\x03foo\x00\x00",
// TODO: recognize that it is cheaper to substitute bar.
tests: single("foo|bar", ""),
}, {
desc: "var after value",
m: seq{
String("foo${bar}"),
&Var{"bar", String("baz")},
},
encErr: errIsVar.Error(),
tests: single("foo|bar", ""),
}, {
desc: "substitution",
m: seq{
&Var{"bar", String("baz")},
String("foo${bar}"),
},
tests: single("foo|baz", ""),
}, {
desc: "shadowed variable",
m: seq{
&Var{"bar", String("baz")},
seq{
&Var{"bar", String("BAZ")},
String("foo${bar}"),
},
},
tests: single("foo|BAZ", ""),
}, {
desc: "not shadowed variable",
m: seq{
&Var{"bar", String("baz")},
seq{
String("foo${bar}"),
&Var{"bar", String("BAZ")},
},
},
encErr: errIsVar.Error(),
tests: single("foo|baz", ""),
}, {
desc: "duplicate variable",
m: seq{
&Var{"bar", String("baz")},
&Var{"bar", String("BAZ")},
String("${bar}"),
},
encErr: "catmsg: duplicate variable \"bar\"",
tests: single("baz", ""),
}, {
desc: "complete incomplete variable",
m: seq{
&Var{"bar", incomplete{}},
String("${bar}"),
},
enc: "\x00\t\b\x01\x01\x04\x04\x02bar\x03\x00\x00\x00",
// TODO: recognize that it is cheaper to substitute bar.
tests: single("bar", ""),
}, {
desc: "incomplete sequence",
m: seq{
incomplete{},
incomplete{},
},
encErr: ErrIncomplete.Error(),
tests: single("", ErrNoMatch.Error()),
}, {
desc: "compile error variable",
m: seq{
&Var{"bar", errorCompileMsg{}},
String("${bar}"),
},
encErr: errCompileTest.Error(),
tests: single("bar", ""),
}, {
desc: "compile error message",
m: errorCompileMsg{},
encErr: errCompileTest.Error(),
tests: single("", ""),
}, {
desc: "compile error sequence",
m: seq{
errorCompileMsg{},
errorCompileMsg{},
},
encErr: errCompileTest.Error(),
tests: single("", ""),
}, {
desc: "macro",
m: String("${exists(1)}"),
tests: single("you betya!", ""),
}, {
desc: "macro incomplete",
m: String("${incomplete(1)}"),
enc: "\x03\x00\x01\nincomplete\x01",
tests: single("incomplete", ""),
}, {
desc: "macro undefined at end",
m: String("${undefined(1)}"),
enc: "\x03\x00\x01\tundefined\x01",
tests: single("undefined", "catmsg: undefined macro \"undefined\""),
}, {
desc: "macro undefined with more text following",
m: String("${undefined(1)}."),
enc: "\x03\x00\x01\tundefined\x01\x01.",
tests: single("undefined|.", "catmsg: undefined macro \"undefined\""),
}, {
desc: "macro missing paren",
m: String("${missing(1}"),
encErr: "catmsg: missing ')'",
tests: single("$!(MISSINGPAREN)", ""),
}, {
desc: "macro bad num",
m: String("aa${bad(a)}"),
encErr: "catmsg: invalid number \"a\"",
tests: single("aa$!(BADNUM)", ""),
}, {
desc: "var missing brace",
m: String("a${missing"),
encErr: "catmsg: missing '}'",
tests: single("a$!(MISSINGBRACE)", ""),
}}
r := &renderer{}
dec := NewDecoder(language.Und, r, macros)
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
data, err := Compile(language.Und, macros, tc.m)
if failErr(err, tc.encErr) {
t.Errorf("encoding error: got %+q; want %+q", err, tc.encErr)
}
if tc.enc != "" && data != tc.enc {
t.Errorf("encoding: got %+q; want %+q", data, tc.enc)
}
for _, st := range tc.tests {
t.Run("", func(t *testing.T) {
*r = renderer{args: st.args}
if err = dec.Execute(data); failErr(err, st.decErr) {
t.Errorf("decoding error: got %+q; want %+q", err, st.decErr)
}
if r.result != st.out {
t.Errorf("decode: got %+q; want %+q", r.result, st.out)
}
})
}
})
}
}
func failErr(got error, want string) bool {
if got == nil {
return want != ""
}
return want == "" || !strings.Contains(got.Error(), want)
}
type seq []Message
func (s seq) Compile(e *Encoder) (err error) {
err = ErrIncomplete
e.EncodeMessageType(First)
for _, m := range s {
// Pass only the last error, but allow erroneous or complete messages
// here to allow testing different scenarios.
err = e.EncodeMessage(m)
}
return err
}
type empty struct{}
func (empty) Compile(e *Encoder) (err error) { return nil }
var msgIncomplete = Register(
"golang.org/x/text/internal/catmsg.incomplete",
func(d *Decoder) bool { return false })
type incomplete struct{}
func (incomplete) Compile(e *Encoder) (err error) {
e.EncodeMessageType(msgIncomplete)
return ErrIncomplete
}
type errorCompileMsg struct{}
var errCompileTest = errors.New("catmsg: compile error test")
func (errorCompileMsg) Compile(e *Encoder) (err error) {
return errCompileTest
}
type dictionary struct{}
var (
macros = dictionary{}
dictMessages = map[string]string{
"exists": compile(String("you betya!")),
"incomplete": compile(incomplete{}),
}
)
func (d dictionary) Lookup(key string) (data string, ok bool) {
data, ok = dictMessages[key]
return
}
func compile(m Message) (data string) {
data, _ = Compile(language.Und, macros, m)
return data
}
+407
View File
@@ -0,0 +1,407 @@
// 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}
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(First)
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")
}
}
+33 -18
View File
@@ -67,6 +67,15 @@ func VerifyDNSLength(verify bool) Option {
return func(o *options) { o.verifyDNSLength = verify }
}
// RemoveLeadingDots removes leading label separators. Leading runes that map to
// dots, such as U+3002 IDEOGRAPHIC FULL STOP, are removed as well.
//
// This is the behavior suggested by the UTS #46 and is adopted by some
// browsers.
func RemoveLeadingDots(remove bool) Option {
return func(o *options) { o.removeLeadingDots = remove }
}
// ValidateLabels sets whether to check the mandatory label validation criteria
// as defined in Section 5.4 of RFC 5891. This includes testing for correct use
// of hyphens ('-'), normalization, validity of runes, and the context rules.
@@ -133,14 +142,16 @@ func MapForLookup() Option {
o.mapping = validateAndMap
StrictDomainName(true)(o)
ValidateLabels(true)(o)
RemoveLeadingDots(true)(o)
}
}
type options struct {
transitional bool
useSTD3Rules bool
validateLabels bool
verifyDNSLength bool
transitional bool
useSTD3Rules bool
validateLabels bool
verifyDNSLength bool
removeLeadingDots bool
trie *idnaTrie
@@ -240,21 +251,23 @@ var (
punycode = &Profile{}
lookup = &Profile{options{
transitional: true,
useSTD3Rules: true,
validateLabels: true,
trie: trie,
fromPuny: validateFromPunycode,
mapping: validateAndMap,
bidirule: bidirule.ValidString,
transitional: true,
useSTD3Rules: true,
validateLabels: true,
removeLeadingDots: true,
trie: trie,
fromPuny: validateFromPunycode,
mapping: validateAndMap,
bidirule: bidirule.ValidString,
}}
display = &Profile{options{
useSTD3Rules: true,
validateLabels: true,
trie: trie,
fromPuny: validateFromPunycode,
mapping: validateAndMap,
bidirule: bidirule.ValidString,
useSTD3Rules: true,
validateLabels: true,
removeLeadingDots: true,
trie: trie,
fromPuny: validateFromPunycode,
mapping: validateAndMap,
bidirule: bidirule.ValidString,
}}
registration = &Profile{options{
useSTD3Rules: true,
@@ -293,7 +306,9 @@ func (p *Profile) process(s string, toASCII bool) (string, error) {
s, err = p.mapping(p, s)
}
// Remove leading empty labels.
for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
if p.removeLeadingDots {
for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
}
}
// It seems like we should only create this error on ToASCII, but the
// UTS 46 conformance tests suggests we should always check this.
+16 -7
View File
@@ -117,7 +117,7 @@ func TestLabelErrors(t *testing.T) {
f func(string) (string, error)
}
punyA := kind{"PunycodeA", punycode.ToASCII}
resolve := kind{"ToASCII", Lookup.ToASCII}
resolve := kind{"ResolveA", Lookup.ToASCII}
display := kind{"ToUnicode", Display.ToUnicode}
p := New(VerifyDNSLength(true), MapForLookup(), BidiRule())
lengthU := kind{"CheckLengthU", p.ToUnicode}
@@ -145,16 +145,25 @@ func TestLabelErrors(t *testing.T) {
{display, "foo.xn--.bar", "foo..bar", ""},
{lengthA, "a..b", "a..b", "A4"},
// Stripping leading empty labels here but not for "empty" punycode
// above seems inconsistent, but seems to be applied by both the
// conformance test and Chrome. Different interpretations would be
// possible, though.
{punyA, ".b", ".b", ""},
// For backwards compatibility, the Punycode profile does not map runes.
{punyA, "\u3002b", "xn--b-83t", ""},
{punyA, "..b", "..b", ""},
// Only strip leading empty labels for certain profiles. Stripping
// leading empty labels here but not for "empty" punycode above seems
// inconsistent, but seems to be applied by both the conformance test
// and Chrome. So we turn it off by default, support it as an option,
// and enable it in profiles where it seems commonplace.
{lengthA, ".b", "b", ""},
{lengthA, "\u3002b", "b", ""},
{lengthA, "..b", "b", ""},
{lengthA, "b..", "b..", ""}, // TODO: remove trailing dots?
{lengthA, "b..", "b..", ""},
{resolve, "a..b", "a..b", ""},
{resolve, ".b", "b", ""},
{resolve, "\u3002b", "b", ""},
{resolve, "..b", "b", ""},
{resolve, "b..", "b..", ""}, // TODO: remove trailing dots?
{resolve, "b..", "b..", ""},
// Raw punycode
{punyA, "", "", ""},
+433
View File
@@ -0,0 +1,433 @@
// 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
)
// A RoundingContext indicates how a number should be converted to digits.
type RoundingContext struct {
Mode RoundingMode
Increment int32 // if > 0, round to Increment * 10^-Scale
Precision int32 // maximum number of significant digits.
Scale int32 // maximum number of decimals after the dot.
}
const maxIntDigits = 20
// A Decimal represents floating point number represented in digits of the base
// in which a number is to be displayed. 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
// 0.00123 Digits: [1, 2, 3], Exp: -2
type Decimal 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.
buf [maxIntDigits]byte
}
// normalize retuns 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 *Decimal) 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 *Decimal) 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 *Decimal) 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 *Decimal) {
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)
// 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
}
abs := x
if x < 0 {
d.Neg = true
abs = -x
}
if math.IsInf(abs, 1) {
d.Inf = true
return
}
// Simple case: decimal notation
if r.Scale > 0 || r.Increment > 0 || r.Precision == 0 {
if int(r.Scale) > len(scales) {
x *= math.Pow(10, float64(r.Scale))
} else {
x *= scales[r.Scale]
}
if r.Increment > 0 {
inc := float64(r.Increment)
x /= float64(inc)
x = r.Mode.roundFloat(x)
x *= inc
} else {
x = r.Mode.roundFloat(x)
}
d.fillIntDigits(uint64(math.Abs(x)))
d.Exp = int32(len(d.Digits)) - r.Scale
return
}
// Nasty case (for non-decimal notation).
// Asides from being inefficient, this result is also wrong as it will
// apply ToNearestEven rounding regardless of the user setting.
// TODO: expose functionality in strconv so we can avoid this hack.
// Something like this would work:
// AppendDigits(dst []byte, x float64, base, size, prec int) (digits []byte, exp, accuracy int)
// TODO: This only supports the nearest even rounding mode.
prec := int(r.Precision)
if prec > 0 {
prec--
}
b := strconv.AppendFloat(d.Digits, abs, 'e', prec, size)
i := 0
k := 0
// No need to check i < len(b) as we always have an 'e'.
for {
if c := b[i]; '0' <= c && c <= '9' {
b[k] = c - '0'
k++
} else if c != '.' {
break
}
i++
}
d.Digits = b[:k]
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
}
}
+291
View File
@@ -0,0 +1,291 @@
// 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 (
"fmt"
"math"
"strconv"
"strings"
"testing"
)
func mkfloat(num string) float64 {
u, _ := strconv.ParseUint(num, 10, 32)
return float64(u)
}
// mkdec creates a decimal from a string. All ASCII digits are converted to
// digits in the decimal. The dot is used to indicate the scale by which the
// digits are shifted. Numbers may have an additional exponent or be the special
// value NaN, Inf, or -Inf.
func mkdec(num string) (d Decimal) {
if num[0] == '-' {
d.Neg = true
num = num[1:]
}
switch num {
case "NaN":
d.NaN = true
return
case "Inf":
d.Inf = true
return
}
if p := strings.IndexAny(num, "eE"); p != -1 {
i64, err := strconv.ParseInt(num[p+1:], 10, 32)
if err != nil {
panic(err)
}
d.Exp = int32(i64)
num = num[:p]
}
if p := strings.IndexByte(num, '.'); p != -1 {
d.Exp += int32(p)
num = num[:p] + num[p+1:]
} else {
d.Exp += int32(len(num))
}
d.Digits = []byte(num)
for i := range d.Digits {
d.Digits[i] -= '0'
}
return d.normalize()
}
func byteNum(s string) []byte {
b := make([]byte, len(s))
for i := 0; i < len(s); i++ {
if c := s[i]; '0' <= c && c <= '9' {
b[i] = s[i] - '0'
} else {
b[i] = s[i] - 'a' + 10
}
}
return b
}
func strNum(s string) string {
return string(byteNum(s))
}
func TestDecimalString(t *testing.T) {
for _, test := range []struct {
x Decimal
want string
}{
{want: "0"},
{Decimal{Digits: nil, Exp: 1000}, "0"}, // exponent of 1000 is ignored
{Decimal{Digits: byteNum("12345"), Exp: 0}, "0.12345"},
{Decimal{Digits: byteNum("12345"), Exp: -3}, "0.00012345"},
{Decimal{Digits: byteNum("12345"), Exp: +3}, "123.45"},
{Decimal{Digits: byteNum("12345"), Exp: +10}, "1234500000"},
} {
if got := test.x.String(); got != test.want {
t.Errorf("%v == %q; want %q", test.x, got, test.want)
}
}
}
func TestRounding(t *testing.T) {
testCases := []struct {
x string
n int
// modes is the result for modes. Signs are left out of the result.
// The results are stored in the following order:
// zero, negInf
// nearZero, nearEven, nearAway
// away, posInf
modes [numModes]string
}{
{"0", 1, [numModes]string{
"0", "0",
"0", "0", "0",
"0", "0"}},
{"1", 1, [numModes]string{
"1", "1",
"1", "1", "1",
"1", "1"}},
{"5", 1, [numModes]string{
"5", "5",
"5", "5", "5",
"5", "5"}},
{"15", 1, [numModes]string{
"10", "10",
"10", "20", "20",
"20", "20"}},
{"45", 1, [numModes]string{
"40", "40",
"40", "40", "50",
"50", "50"}},
{"95", 1, [numModes]string{
"90", "90",
"90", "100", "100",
"100", "100"}},
{"12344999", 4, [numModes]string{
"12340000", "12340000",
"12340000", "12340000", "12340000",
"12350000", "12350000"}},
{"12345000", 4, [numModes]string{
"12340000", "12340000",
"12340000", "12340000", "12350000",
"12350000", "12350000"}},
{"12345001", 4, [numModes]string{
"12340000", "12340000",
"12350000", "12350000", "12350000",
"12350000", "12350000"}},
{"12345100", 4, [numModes]string{
"12340000", "12340000",
"12350000", "12350000", "12350000",
"12350000", "12350000"}},
{"23454999", 4, [numModes]string{
"23450000", "23450000",
"23450000", "23450000", "23450000",
"23460000", "23460000"}},
{"23455000", 4, [numModes]string{
"23450000", "23450000",
"23450000", "23460000", "23460000",
"23460000", "23460000"}},
{"23455001", 4, [numModes]string{
"23450000", "23450000",
"23460000", "23460000", "23460000",
"23460000", "23460000"}},
{"23455100", 4, [numModes]string{
"23450000", "23450000",
"23460000", "23460000", "23460000",
"23460000", "23460000"}},
{"99994999", 4, [numModes]string{
"99990000", "99990000",
"99990000", "99990000", "99990000",
"100000000", "100000000"}},
{"99995000", 4, [numModes]string{
"99990000", "99990000",
"99990000", "100000000", "100000000",
"100000000", "100000000"}},
{"99999999", 4, [numModes]string{
"99990000", "99990000",
"100000000", "100000000", "100000000",
"100000000", "100000000"}},
{"12994999", 4, [numModes]string{
"12990000", "12990000",
"12990000", "12990000", "12990000",
"13000000", "13000000"}},
{"12995000", 4, [numModes]string{
"12990000", "12990000",
"12990000", "13000000", "13000000",
"13000000", "13000000"}},
{"12999999", 4, [numModes]string{
"12990000", "12990000",
"13000000", "13000000", "13000000",
"13000000", "13000000"}},
}
modes := []RoundingMode{
ToZero, ToNegativeInf,
ToNearestZero, ToNearestEven, ToNearestAway,
AwayFromZero, ToPositiveInf,
}
for _, tc := range testCases {
// Create negative counterpart tests: the sign is reversed and
// ToPositiveInf and ToNegativeInf swapped.
negModes := tc.modes
negModes[1], negModes[6] = negModes[6], negModes[1]
for i, res := range negModes {
negModes[i] = "-" + res
}
for i, m := range modes {
t.Run(fmt.Sprintf("x:%s/n:%d/%s", tc.x, tc.n, m), func(t *testing.T) {
d := mkdec(tc.x)
d.round(m, tc.n)
if got := d.String(); got != tc.modes[i] {
t.Errorf("pos decimal: got %q; want %q", d.String(), tc.modes[i])
}
mult := math.Pow(10, float64(len(tc.x)-tc.n))
f := mkfloat(tc.x)
f = m.roundFloat(f/mult) * mult
if got := fmt.Sprintf("%.0f", f); got != tc.modes[i] {
t.Errorf("pos float: got %q; want %q", got, tc.modes[i])
}
// Test the negative case. This is the same as the positive
// case, but with ToPositiveInf and ToNegativeInf swapped.
d = mkdec(tc.x)
d.Neg = true
d.round(m, tc.n)
if got, want := d.String(), negModes[i]; got != want {
t.Errorf("neg decimal: got %q; want %q", d.String(), want)
}
f = -mkfloat(tc.x)
f = m.roundFloat(f/mult) * mult
if got := fmt.Sprintf("%.0f", f); got != negModes[i] {
t.Errorf("neg float: got %q; want %q", got, negModes[i])
}
})
}
}
}
func TestConvert(t *testing.T) {
scale2 := &RoundingContext{Scale: 2}
scale2away := &RoundingContext{Scale: 2, Mode: AwayFromZero}
inc0_05 := &RoundingContext{Increment: 5, Scale: 2}
inc50 := &RoundingContext{Increment: 50}
prec3 := &RoundingContext{Precision: 3}
testCases := []struct {
x interface{}
rc *RoundingContext
out string
}{
{int8(-34), scale2, "-34"},
{int16(-234), scale2, "-234"},
{int32(-234), scale2, "-234"},
{int64(-234), scale2, "-234"},
{int(-234), scale2, "-234"},
{uint8(234), scale2, "234"},
{uint16(234), scale2, "234"},
{uint32(234), scale2, "234"},
{uint64(234), scale2, "234"},
{uint(234), scale2, "234"},
{-0.001, scale2, "-0"},
{-1e9, scale2, "-1000000000.00"},
{0.234, scale2, "0.23"},
{0.234, scale2away, "0.24"},
{0.1234, prec3, "0.123"},
{1234.0, prec3, "1230"},
{1.2345e10, prec3, "12300000000"},
{0.03, inc0_05, "0.05"},
{0.025, inc0_05, "0"},
{0.075, inc0_05, "0.10"},
{325, inc50, "300"},
{375, inc50, "400"},
{converter(3), scale2, "100"},
{math.Inf(1), inc50, "Inf"},
{math.Inf(-1), inc50, "-Inf"},
{math.NaN(), inc50, "NaN"},
}
for _, tc := range testCases {
var d Decimal
t.Run(fmt.Sprintf("%T:%v-%v", tc.x, tc.x, tc.rc), func(t *testing.T) {
d.Convert(tc.rc, tc.x)
if got := d.String(); got != tc.out {
t.Errorf("got %q; want %q", got, tc.out)
}
})
}
}
type converter int
func (c converter) Convert(d *Decimal, r *RoundingContext) {
d.Digits = append(d.Digits, 1, 0, 0)
d.Exp = 3
}
+467
View File
@@ -0,0 +1,467 @@
// 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 &nbsp;
// 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
RoundingContext
}
func (f *Formatter) init(t language.Tag, index []uint8) {
f.Info = InfoFromTag(t)
for ; ; t = t.Parent() {
if ci, ok := language.CompactIndex(t); ok {
f.Pattern = formats[index[ci]]
break
}
}
}
// 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)
}
// 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.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
d.Convert(&f.RoundingContext, x)
return f.Format(dst, &d)
}
func (f *Formatter) Format(dst []byte, d *Decimal) []byte {
var result []byte
var postPrefix, preSuffix int
if f.MinExponentDigits > 0 {
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
}
// appendDecimal appends a formatted number to dst. It returns two possible
// insertion points for padding.
func appendDecimal(dst []byte, f *Formatter, d *Decimal) (b []byte, postPre, preSuf int) {
if dst, ok := f.renderSpecial(dst, d); ok {
return dst, 0, len(dst)
}
n := d.normalize()
if maxSig := int(f.MaxSignificantDigits); maxSig > 0 {
n.round(ToZero, maxSig)
}
digits := n.Digits
exp := n.Exp
exp += int32(f.Pattern.DigitShift)
// Split in integer and fraction part.
var intDigits, fracDigits []byte
var numInt, numFrac int
if exp > 0 {
numInt = int(exp)
if int(exp) >= len(digits) { // ddddd | ddddd00
intDigits = digits
} else { // ddd.dd
intDigits = digits[:exp]
fracDigits = digits[exp:]
numFrac = len(fracDigits)
}
} else {
fracDigits = digits
numFrac = -int(exp) + len(digits)
}
// Cap integer digits. Remove *most-significant* digits.
if f.MaxIntegerDigits > 0 && numInt > int(f.MaxIntegerDigits) {
offset := numInt - int(f.MaxIntegerDigits)
if offset > len(intDigits) {
numInt = 0
intDigits = nil
} else {
numInt = int(f.MaxIntegerDigits)
intDigits = intDigits[offset:]
// for keeping track of significant digits
digits = digits[offset:]
}
// Strip leading zeros. Resulting number of digits is significant digits.
for len(intDigits) > 0 && intDigits[0] == 0 {
intDigits = intDigits[1:]
digits = digits[1:]
numInt--
}
}
if f.MaxSignificantDigits == 0 && int(f.MaxFractionDigits) < numFrac {
if extra := numFrac - int(f.MaxFractionDigits); extra > len(fracDigits) {
numFrac = 0
fracDigits = nil
} else {
numFrac = int(f.MaxFractionDigits)
fracDigits = fracDigits[:len(fracDigits)-extra]
}
}
neg := d.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)...)
}
}
trailZero := int(f.MinFractionDigits) - numFrac
if d := int(f.MinSignificantDigits) - len(digits); d > 0 && d > trailZero {
trailZero = d
}
if numFrac > 0 || trailZero > 0 || f.Flags&AlwaysDecimalSeparator != 0 {
dst = append(dst, f.Symbol(SymDecimal)...)
}
// Add leading zeros
for i := numFrac - len(fracDigits); i > 0; i-- {
dst = f.AppendDigit(dst, 0)
}
i = 0
for ; i < len(fracDigits); i++ {
dst = f.AppendDigit(dst, fracDigits[i])
}
for ; trailZero > 0; trailZero-- {
dst = f.AppendDigit(dst, 0)
}
return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
}
// appendScientific appends a formatted number to dst. It returns two possible
// insertion points for padding.
func appendScientific(dst []byte, f *Formatter, d *Decimal) (b []byte, postPre, preSuf int) {
if dst, ok := f.renderSpecial(dst, d); ok {
return dst, 0, 0
}
// Significant digits are transformed by parser for scientific notation and
// do not need to be handled here.
maxInt, numInt := int(f.MaxIntegerDigits), int(f.MinIntegerDigits)
if numInt == 0 {
numInt = 1
}
maxSig := int(f.MaxFractionDigits) + numInt
minSig := int(f.MinFractionDigits) + numInt
n := d.normalize()
if maxSig > 0 {
n.round(ToZero, maxSig)
}
digits := n.Digits
exp := n.Exp
// 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 len(digits) == 0 {
exp = 0
} else if maxInt > numInt {
// Correct the exponent to reflect a single integer digit.
exp--
numInt = 1
// engineering
// 0.01234 ([12345]e-1) -> 1.2345e-2 12.345e-3
// 12345 ([12345]e+5) -> 1.2345e4 12.345e3
d := int(exp) % maxInt
if d < 0 {
d += maxInt
}
exp -= int32(d)
numInt += d
} else {
exp -= int32(numInt)
}
var intDigits, fracDigits []byte
if numInt <= len(digits) {
intDigits = digits[:numInt]
fracDigits = digits[numInt:]
} else {
intDigits = digits
}
neg := d.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)...)
}
}
trailZero := minSig - numInt - len(fracDigits)
if len(fracDigits) > 0 || trailZero > 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 ; trailZero > 0; trailZero-- {
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.
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 *Decimal) (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 *Decimal) []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
}
+508
View File
@@ -0,0 +1,508 @@
// 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 (
"fmt"
"log"
"testing"
"golang.org/x/text/language"
)
func TestAppendDecimal(t *testing.T) {
type pairs map[string]string // alternates with decimal input and result
testCases := []struct {
pattern string
// We want to be able to test some forms of patterns that cannot be
// represented as a string.
pat *Pattern
test pairs
}{{
pattern: "0",
test: pairs{
"0": "0",
"1": "1",
"-1": "-1",
".00": "0",
"10.": "10",
"12": "12",
"1.2": "1",
"NaN": "NaN",
"-Inf": "-∞",
},
}, {
pattern: "+0;+0",
test: pairs{
"0": "+0",
"1": "+1",
"-1": "-1",
".00": "+0",
"10.": "+10",
"12": "+12",
"1.2": "+1",
"NaN": "NaN",
"-Inf": "-∞",
"Inf": "+∞",
},
}, {
pattern: "0 +;0 +",
test: pairs{
"0": "0 +",
"1": "1 +",
"-1": "1 -",
".00": "0 +",
},
}, {
pattern: "0;0-",
test: pairs{
"-1": "1-",
"NaN": "NaN",
"-Inf": "∞-",
"Inf": "∞",
},
}, {
pattern: "0000",
test: pairs{
"0": "0000",
"1": "0001",
"12": "0012",
"12345": "12345",
},
}, {
pattern: ".0",
test: pairs{
"0": ".0",
"1": "1.0",
"1.2": "1.2",
"1.2345": "1.2",
},
}, {
pattern: "#.0",
test: pairs{
"0": ".0",
},
}, {
pattern: "#.0#",
test: pairs{
"0": ".0",
"1": "1.0",
},
}, {
pattern: "0.0#",
test: pairs{
"0": "0.0",
},
}, {
pattern: "#0.###",
test: pairs{
"0": "0",
"1": "1",
"1.2": "1.2",
"1.2345": "1.234", // rounding should have been done earlier
"1234.5": "1234.5",
"1234.567": "1234.567",
},
}, {
pattern: "#0.######",
test: pairs{
"0": "0",
"1234.5678": "1234.5678",
"0.123456789": "0.123456",
"NaN": "NaN",
"Inf": "∞",
},
// Test separators.
}, {
pattern: "#,#.00",
test: pairs{
"100": "1,0,0.00",
},
}, {
pattern: "#,0.##",
test: pairs{
"10": "1,0",
},
}, {
pattern: "#,0",
test: pairs{
"10": "1,0",
},
}, {
pattern: "#,##,#.00",
test: pairs{
"1000": "1,00,0.00",
},
}, {
pattern: "#,##0.###",
test: pairs{
"0": "0",
"1234.5678": "1,234.567",
"0.123456789": "0.123",
},
}, {
pattern: "#,##,##0.###",
test: pairs{
"0": "0",
"123456789012": "1,23,45,67,89,012",
"0.123456789": "0.123",
},
}, {
pattern: "0,00,000.###",
test: pairs{
"0": "0,00,000",
"123456789012": "1,23,45,67,89,012",
"12.3456789": "0,00,012.345",
"0.123456789": "0,00,000.123",
},
// Support for ill-formed patterns.
}, {
pattern: "#",
test: pairs{
".00": "", // This is the behavior of fmt.
"0": "", // This is the behavior of fmt.
"1": "1",
"10.": "10",
},
}, {
pattern: ".#",
test: pairs{
"0": "", // This is the behavior of fmt.
"1": "1",
"1.2": "1.2",
"1.2345": "1.2",
},
}, {
pattern: "#,#.##",
test: pairs{
"10": "1,0",
},
}, {
pattern: "#,#",
test: pairs{
"10": "1,0",
},
// Special patterns
}, {
pattern: "#,max_int=2",
pat: &Pattern{
MaxIntegerDigits: 2,
},
test: pairs{
"2017": "17",
},
}, {
pattern: "0,max_int=2",
pat: &Pattern{
MaxIntegerDigits: 2,
MinIntegerDigits: 1,
},
test: pairs{
"2000": "0",
"2001": "1",
"2017": "17",
},
}, {
pattern: "00,max_int=2",
pat: &Pattern{
MaxIntegerDigits: 2,
MinIntegerDigits: 2,
},
test: pairs{
"2000": "00",
"2001": "01",
"2017": "17",
},
}, {
pattern: "@@@@,max_int=2",
pat: &Pattern{
MaxIntegerDigits: 2,
MinSignificantDigits: 4,
},
test: pairs{
"2017": "17.00",
"2000": "0.000",
"2001": "1.000",
},
// Significant digits
}, {
pattern: "@@##",
test: pairs{
"1": "1.0",
"0.1": "0.10",
"123": "123",
"1234": "1234",
"12345": "12340",
},
}, {
pattern: "@@@@",
test: pairs{
"1": "1.000",
".1": "0.1000",
".001": "0.001000",
"123": "123.0",
"1234": "1234",
"12345": "12340", // rounding down
"NaN": "NaN",
"-Inf": "-∞",
},
// TODO: rounding
// {"@@@@": "23456": "23460"}, // rounding up
// TODO: padding
// Scientific and Engineering notation
}, {
pattern: "#E0",
test: pairs{
"0": "0\u202f×\u202f10⁰",
"1": "1\u202f×\u202f10⁰",
"123.456": "1\u202f×\u202f10²",
},
}, {
pattern: "#E+0",
test: pairs{
"0": "0\u202f×\u202f10⁺⁰",
"1000": "1\u202f×\u202f10⁺³",
"1E100": "1\u202f×\u202f10⁺¹⁰⁰",
"1E-100": "1\u202f×\u202f10⁻¹⁰⁰",
"NaN": "NaN",
"-Inf": "-∞",
},
}, {
pattern: "##0E00",
test: pairs{
"100": "100\u202f×\u202f10⁰⁰",
"12345": "10\u202f×\u202f10⁰³",
"123.456": "100\u202f×\u202f10⁰⁰",
},
}, {
pattern: "##0.###E00",
test: pairs{
"100": "100\u202f×\u202f10⁰⁰",
"12345": "12.34\u202f×\u202f10⁰³",
"123.456": "123.4\u202f×\u202f10⁰⁰",
},
}, {
pattern: "##0.000E00",
test: pairs{
"100": "100.0\u202f×\u202f10⁰⁰",
"12345": "12.34\u202f×\u202f10⁰³",
"123.456": "123.4\u202f×\u202f10⁰⁰",
},
}, {
pattern: "@@E0",
test: pairs{
"0": "0.0\u202f×\u202f10⁰",
"99": "9.9\u202f×\u202f10¹",
"0.99": "9.9\u202f×\u202f10⁻¹",
},
}, {
pattern: "@###E00",
test: pairs{
"0": "0\u202f×\u202f10⁰⁰",
"1": "1\u202f×\u202f10⁰⁰",
"11": "1.1\u202f×\u202f10⁰¹",
"111": "1.11\u202f×\u202f10⁰²",
"1111": "1.111\u202f×\u202f10⁰³",
"11111": "1.111\u202f×\u202f10⁰⁴",
"0.1": "1\u202f×\u202f10⁻⁰¹",
"0.11": "1.1\u202f×\u202f10⁻⁰¹",
"0.001": "1\u202f×\u202f10⁻⁰³",
},
}, {
pattern: "*x##0",
test: pairs{
"0": "xx0",
"10": "x10",
"100": "100",
"1000": "1000",
},
}, {
pattern: "##0*x",
test: pairs{
"0": "0xx",
"10": "10x",
"100": "100",
"1000": "1000",
},
}, {
pattern: "* ###0.000",
test: pairs{
"0": " 0.000",
"123": " 123.000",
"123.456": " 123.456",
"1234.567": "1234.567",
},
}, {
pattern: "**0.0#######E00",
test: pairs{
"0": "***0.0\u202f×\u202f10⁰⁰",
"10": "***1.0\u202f×\u202f10⁰¹",
"11": "***1.1\u202f×\u202f10⁰¹",
"111": "**1.11\u202f×\u202f10⁰²",
"1111": "*1.111\u202f×\u202f10⁰³",
"11111": "1.1111\u202f×\u202f10⁰⁴",
"11110": "*1.111\u202f×\u202f10⁰⁴",
"11100": "**1.11\u202f×\u202f10⁰⁴",
"11000": "***1.1\u202f×\u202f10⁰⁴",
"10000": "***1.0\u202f×\u202f10⁰⁴",
},
}, {
pattern: "*xpre0suf",
test: pairs{
"0": "pre0suf",
"10": "pre10suf",
},
}, {
pattern: "*∞ pre ###0 suf",
test: pairs{
"0": "∞∞∞ pre 0 suf",
"10": "∞∞ pre 10 suf",
"100": "∞ pre 100 suf",
"1000": " pre 1000 suf",
},
}, {
pattern: "pre *∞###0 suf",
test: pairs{
"0": "pre ∞∞∞0 suf",
"10": "pre ∞∞10 suf",
"100": "pre ∞100 suf",
"1000": "pre 1000 suf",
},
}, {
pattern: "pre ###0*∞ suf",
test: pairs{
"0": "pre 0∞∞∞ suf",
"10": "pre 10∞∞ suf",
"100": "pre 100∞ suf",
"1000": "pre 1000 suf",
},
}, {
pattern: "pre ###0 suf *∞",
test: pairs{
"0": "pre 0 suf ∞∞∞",
"10": "pre 10 suf ∞∞",
"100": "pre 100 suf ∞",
"1000": "pre 1000 suf ",
},
}, {
// Take width of positive pattern.
pattern: "**###0;**-#####0x",
test: pairs{
"0": "***0",
"-1": "*-1x",
},
}, {
pattern: "0.00%",
test: pairs{
"0.1": "10.00%",
},
}, {
pattern: "0.##%",
test: pairs{
"0.1": "10%",
"0.11": "11%",
"0.111": "11.1%",
"0.1111": "11.11%",
"0.11111": "11.11%",
},
}, {
pattern: "‰ 0.0#",
test: pairs{
"0.1": "‰ 100.0",
"0.11": "‰ 110.0",
"0.111": "‰ 111.0",
"0.1111": "‰ 111.1",
"0.11111": "‰ 111.11",
"0.111111": "‰ 111.11",
},
}}
// TODO:
// "#,##0.00¤",
// "#,##0.00 ¤;(#,##0.00 ¤)",
for _, tc := range testCases {
pat := tc.pat
if pat == nil {
var err error
if pat, err = ParsePattern(tc.pattern); err != nil {
log.Fatal(err)
}
}
var f Formatter
f.InitPattern(language.English, pat)
for dec, want := range tc.test {
buf := make([]byte, 100)
t.Run(tc.pattern+"/"+dec, func(t *testing.T) {
dec := mkdec(dec)
buf = f.Format(buf[:0], &dec)
if got := string(buf); got != want {
t.Errorf("\n got %[1]q (%[1]s)\nwant %[2]q (%[2]s)", got, want)
}
})
}
}
}
func TestLocales(t *testing.T) {
testCases := []struct {
tag language.Tag
num string
want string
}{
{language.Make("en"), "123456.78", "123,456.78"},
{language.Make("de"), "123456.78", "123.456,78"},
{language.Make("de-CH"), "123456.78", "123’456.78"},
{language.Make("fr"), "123456.78", "123 456,78"},
{language.Make("bn"), "123456.78", "১,২৩,৪৫৬.৭৮"},
}
for _, tc := range testCases {
t.Run(fmt.Sprint(tc.tag, "/", tc.num), func(t *testing.T) {
var f Formatter
f.InitDecimal(tc.tag)
d := mkdec(tc.num)
b := f.Format(nil, &d)
if got := string(b); got != tc.want {
t.Errorf("got %[1]q (%[1]s); want %[2]q (%[2]s)", got, tc.want)
}
})
}
}
func TestFormatters(t *testing.T) {
var f Formatter
testCases := []struct {
init func(t language.Tag)
num string
want string
}{
{f.InitDecimal, "123456.78", "123,456.78"},
{f.InitScientific, "123456.78", "1.23\u202f×\u202f10⁵"},
{f.InitEngineering, "123456.78", "123\u202f×\u202f10³"},
{f.InitPercent, "0.1234", "12.34%"},
{f.InitPerMille, "0.1234", "123.40‰"},
}
for i, tc := range testCases {
t.Run(fmt.Sprint(i, "/", tc.num), func(t *testing.T) {
tc.init(language.English)
f.Pattern.MinFractionDigits = 2
f.Pattern.MaxFractionDigits = 2
d := mkdec(tc.num)
b := f.Format(nil, &d)
if got := string(b); got != tc.want {
t.Errorf("got %[1]q (%[1]s); want %[2]q (%[2]s)", got, tc.want)
}
})
}
}
+9
View File
@@ -121,6 +121,15 @@ func (n Info) WriteDigit(dst []byte, asciiDigit rune) int {
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.
+20 -10
View File
@@ -5,6 +5,7 @@
package number
import (
"fmt"
"testing"
"golang.org/x/text/internal/testtext"
@@ -26,9 +27,9 @@ func TestInfo(t *testing.T) {
// U+096F DEVANAGARI DIGIT NINE ('९')
{"de-BE-u-nu-deva", SymGroup, ".", '\u096f'}, // miss -> latn -> de
{"de-Cyrl-BE", SymGroup, ",", '9'}, // inherits from root
{"de-CH", SymGroup, "'", '9'}, // overrides values in de
{"de-CH-oxendict", SymGroup, "'", '9'}, // inherits from de-CH (no compact index)
{"de-CH-u-nu-deva", SymGroup, "'", '\u096f'}, // miss -> latn -> de-CH
{"de-CH", SymGroup, "’", '9'}, // overrides values in de
{"de-CH-oxendict", SymGroup, "’", '9'}, // inherits from de-CH (no compact index)
{"de-CH-u-nu-deva", SymGroup, "’", '\u096f'}, // miss -> latn -> de-CH
{"pa", SymExponential, "E", '9'},
@@ -51,13 +52,22 @@ func TestInfo(t *testing.T) {
{"en-u-nu-roman", SymPlusSign, "+", '9'},
}
for _, tc := range testCases {
info := InfoFromTag(language.MustParse(tc.lang))
if got := info.Symbol(tc.sym); got != tc.wantSym {
t.Errorf("%s:%v:sym: got %q; want %q", tc.lang, tc.sym, got, tc.wantSym)
}
if got := info.Digit('9'); got != tc.wantNine {
t.Errorf("%s:%v:nine: got %q; want %q", tc.lang, tc.sym, got, tc.wantNine)
}
t.Run(fmt.Sprintf("%s:%v", tc.lang, tc.sym), func(t *testing.T) {
info := InfoFromTag(language.MustParse(tc.lang))
if got := info.Symbol(tc.sym); got != tc.wantSym {
t.Errorf("sym: got %q; want %q", got, tc.wantSym)
}
if got := info.Digit('9'); got != tc.wantNine {
t.Errorf("Digit(9): got %+q; want %+q", got, tc.wantNine)
}
var buf [4]byte
if got := string(buf[:info.WriteDigit(buf[:], '9')]); got != string(tc.wantNine) {
t.Errorf("WriteDigit(9): got %+q; want %+q", got, tc.wantNine)
}
if got := string(info.AppendDigit([]byte{}, 9)); got != string(tc.wantNine) {
t.Errorf("AppendDigit(9): got %+q; want %+q", got, tc.wantNine)
}
})
}
}
+51 -10
View File
@@ -46,16 +46,17 @@ type Pattern struct {
Offset uint16 // Offset into Affix for prefix and suffix
NegOffset uint16 // Offset into Affix for negative prefix and suffix or 0.
Multiplier uint32
FormatWidth uint16
RoundIncrement uint32 // Use Min*Digits to determine scale
PadRune rune
FormatWidth uint16
DigitShift uint8 // Number of decimals to shift. Used for % and ‰.
GroupingSize [2]uint8
Flags PatternFlag
// Number of digits.
// TODO: consider using uint32
MinIntegerDigits uint8
MaxIntegerDigits uint8
MinFractionDigits uint8
@@ -65,11 +66,32 @@ type Pattern struct {
MinExponentDigits uint8
}
// A PatternFlag is a bit mask for the flag field of a Format.
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.
@@ -104,7 +126,8 @@ func (p *parser) setError(err error) {
}
func (p *parser) updateGrouping() {
if p.hasGroup && p.groupingCount < 255 {
if p.hasGroup &&
0 < p.groupingCount && p.groupingCount < 255 {
p.GroupingSize[1] = p.GroupingSize[0]
p.GroupingSize[0] = uint8(p.groupingCount)
}
@@ -163,6 +186,7 @@ func (p *parser) parseSubPattern(s string) string {
s = p.parsePad(s, PadAfterPrefix)
s = p.parse(p.number, s)
p.updateGrouping()
s = p.parsePad(s, PadBeforeSuffix)
s = p.parseAffix(s)
@@ -225,26 +249,41 @@ func (p *parser) affix(r rune) state {
'#', '@', '.', '*', ',', ';':
return nil
case '\'':
return p.escape
p.FormatWidth--
return p.escapeFirst
case '%':
if p.Multiplier != 0 {
if p.DigitShift != 0 {
p.setError(errDuplicatePercentSign)
}
p.Multiplier = 100
p.DigitShift = 2
case '\u2030': // ‰ Per mille
if p.Multiplier != 0 {
if p.DigitShift != 0 {
p.setError(errDuplicatePermilleSign)
}
p.Multiplier = 1000
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)...)
@@ -294,6 +333,8 @@ func (p *parser) integer(r rune) state {
next = p.exponent
case '.':
next = p.fraction
case ',':
next = p.integer
}
p.updateGrouping()
return next
+73 -12
View File
@@ -25,6 +25,20 @@ var testCases = []struct {
FormatWidth: 1,
MinIntegerDigits: 1,
},
}, {
"+0",
&Pattern{
Affix: "\x01+\x00",
FormatWidth: 2,
MinIntegerDigits: 1,
},
}, {
"0+",
&Pattern{
Affix: "\x00\x01+",
FormatWidth: 2,
MinIntegerDigits: 1,
},
}, {
"0000",
&Pattern{
@@ -51,6 +65,22 @@ var testCases = []struct {
MinIntegerDigits: 1,
MaxFractionDigits: 6,
},
}, {
"#,0",
&Pattern{
FormatWidth: 3,
GroupingSize: [2]uint8{1, 0},
MinIntegerDigits: 1,
},
}, {
"#,0.00",
&Pattern{
FormatWidth: 6,
GroupingSize: [2]uint8{1, 0},
MinIntegerDigits: 1,
MinFractionDigits: 2,
MaxFractionDigits: 2,
},
}, {
"#,##0.###",
&Pattern{
@@ -83,6 +113,11 @@ var testCases = []struct {
MaxIntegerDigits: 1,
MinExponentDigits: 1,
},
}, {
// At least one exponent digit is required. As long as this is true, one can
// determine that scientific rendering is needed if MinExponentDigits > 0.
"#E#",
nil,
}, {
"0E0",
&Pattern{
@@ -176,7 +211,7 @@ var testCases = []struct {
MaxFractionDigits: 3,
},
}, {
// Rounding increments
// Rounding increment
"1.05",
&Pattern{
RoundIncrement: 105,
@@ -185,11 +220,22 @@ var testCases = []struct {
MinFractionDigits: 2,
MaxFractionDigits: 2,
},
}, {
// Rounding increment with grouping
"1,05",
&Pattern{
RoundIncrement: 105,
FormatWidth: 4,
GroupingSize: [2]uint8{2, 0},
MinIntegerDigits: 3,
MinFractionDigits: 0,
MaxFractionDigits: 0,
},
}, {
"0.0%",
&Pattern{
Affix: "\x00\x01%",
Multiplier: 100,
DigitShift: 2,
FormatWidth: 4,
MinIntegerDigits: 1,
MinFractionDigits: 1,
@@ -199,7 +245,7 @@ var testCases = []struct {
"0.0‰",
&Pattern{
Affix: "\x00\x03‰",
Multiplier: 1000,
DigitShift: 3,
FormatWidth: 4,
MinIntegerDigits: 1,
MinFractionDigits: 1,
@@ -219,7 +265,7 @@ var testCases = []struct {
"#,##0.00 ¤;(#,##0.00 ¤)",
&Pattern{Affix: "\x00\x04\u00a0¤\x01(\x05\u00a0¤)",
NegOffset: 6,
Multiplier: 0,
DigitShift: 0,
FormatWidth: 10,
GroupingSize: [2]uint8{3, 0},
MinIntegerDigits: 1,
@@ -272,6 +318,19 @@ var testCases = []struct {
FormatWidth: 7,
Flags: PadAfterSuffix,
},
}, {
`* #0 o''clock`,
&Pattern{Affix: "\x00\x09 o\\'clock",
FormatWidth: 10,
PadRune: 32,
MinIntegerDigits: 0x1},
}, {
`'123'* #0'456'`,
&Pattern{Affix: "\x05'123'\x05'456'",
FormatWidth: 8,
PadRune: 32,
MinIntegerDigits: 0x1,
Flags: PadAfterPrefix},
}, {
// no duplicate padding
"*xpre#suf*x", nil,
@@ -282,19 +341,21 @@ var testCases = []struct {
func TestParsePattern(t *testing.T) {
for i, tc := range testCases {
f, err := ParsePattern(tc.pat)
if !reflect.DeepEqual(f, tc.want) {
t.Errorf("%d:%s:\ngot %#v;\nwant %#v", i, tc.pat, f, tc.want)
}
if got, want := err != nil, tc.want == nil; got != want {
t.Errorf("%d:%s:error: got %v; want %v", i, tc.pat, err, want)
}
t.Run(tc.pat, func(t *testing.T) {
f, err := ParsePattern(tc.pat)
if !reflect.DeepEqual(f, tc.want) {
t.Errorf("%d:%s:\ngot %#v;\nwant %#v", i, tc.pat, f, tc.want)
}
if got, want := err != nil, tc.want == nil; got != want {
t.Errorf("%d:%s:error: got %v; want %v", i, tc.pat, err, want)
}
})
}
}
func TestPatternSize(t *testing.T) {
if sz := unsafe.Sizeof(Pattern{}); sz > 48 {
t.Errorf("got %d; want 48", sz)
t.Errorf("got %d; want <= 48", sz)
}
}
+16
View File
@@ -0,0 +1,16 @@
// Code generated by "stringer -type RoundingMode"; DO NOT EDIT.
package number
import "fmt"
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 fmt.Sprintf("RoundingMode(%d)", i)
}
return _RoundingMode_name[_RoundingMode_index[i]:_RoundingMode_index[i+1]]
}
+283 -280
View File
@@ -5,7 +5,7 @@ package number
import "golang.org/x/text/internal/stringset"
// CLDRVersion is the CLDR version from which the tables in this package are derived.
const CLDRVersion = "30"
const CLDRVersion = "31"
var numSysData = []systemData{ // 58 elements
0: {id: 0x0, digitSize: 0x1, zero: [4]uint8{0x30, 0x0, 0x0, 0x0}},
@@ -255,82 +255,81 @@ var symIndex = [][12]uint8{ // 71 elements
22: [12]uint8{0x0, 0x1, 0x2, 0x3, 0xe, 0x1c, 0x6, 0x7, 0x8, 0x9, 0x1d, 0xb},
23: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0x1e, 0x0},
24: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
25: [12]uint8{0x0, 0x1f, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
25: [12]uint8{0x0, 0x15, 0x2, 0x3, 0x4, 0x1b, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
26: [12]uint8{0x0, 0x1, 0x2, 0x3, 0xe, 0xf, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
27: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x20, 0xb},
27: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x1f, 0xb},
28: [12]uint8{0x0, 0x15, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
29: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x21, 0xb},
30: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x22, 0xb},
31: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x1b, 0x18, 0x13, 0x8, 0x9, 0x23, 0xb},
32: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x18, 0x7, 0x8, 0x9, 0x23, 0xb},
33: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x24, 0xb},
34: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x25, 0xb},
35: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x26, 0xb},
36: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x27, 0xb},
37: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x28, 0xb},
29: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x20, 0xb},
30: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x21, 0xb},
31: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x1b, 0x18, 0x13, 0x8, 0x9, 0x22, 0xb},
32: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x18, 0x7, 0x8, 0x9, 0x22, 0xb},
33: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x23, 0xb},
34: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x24, 0xb},
35: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x25, 0xb},
36: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x26, 0xb},
37: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x27, 0xb},
38: [12]uint8{0x1, 0x0, 0x2, 0x3, 0xe, 0x1c, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
39: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x29, 0xb},
40: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2a, 0xb},
41: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x2b, 0x13, 0x8, 0x9, 0x23, 0xb},
39: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x28, 0xb},
40: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x29, 0xb},
41: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x1b, 0x2a, 0x13, 0x8, 0x9, 0x22, 0xb},
42: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0x0},
43: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x17, 0x7, 0x8, 0x9, 0xa, 0xb},
44: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x2c, 0x17, 0x7, 0x8, 0x9, 0xa, 0xb},
45: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2d, 0x0},
46: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2e, 0xb},
47: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2f, 0xb},
48: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x30, 0x7, 0x8, 0x9, 0xa, 0xb},
49: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x31, 0xb},
50: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x32, 0xb},
51: [12]uint8{0x1, 0x1f, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
52: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x33, 0xb},
53: [12]uint8{0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x7, 0x3b, 0x9, 0xa, 0xb},
54: [12]uint8{0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x7, 0x3b, 0x9, 0x3c, 0xb},
55: [12]uint8{0x34, 0x35, 0x36, 0x11, 0x38, 0x39, 0x3a, 0x7, 0x3b, 0x9, 0xa, 0xb},
56: [12]uint8{0x34, 0x35, 0x36, 0x11, 0x38, 0x3d, 0x3a, 0x7, 0x3b, 0x9, 0xa, 0xb},
57: [12]uint8{0x34, 0xc, 0x36, 0x37, 0x38, 0x3e, 0x3a, 0x7, 0x3b, 0x9, 0xa, 0x0},
58: [12]uint8{0x34, 0x35, 0x36, 0x37, 0x38, 0x3e, 0x3a, 0x7, 0x3f, 0x9, 0x23, 0xb},
59: [12]uint8{0x34, 0x35, 0x36, 0x11, 0x40, 0x41, 0x42, 0x7, 0x3b, 0x9, 0xa, 0x34},
60: [12]uint8{0x34, 0x35, 0x36, 0x43, 0xe, 0x1c, 0x42, 0x7, 0x3b, 0x9, 0x1d, 0xb},
61: [12]uint8{0x34, 0x35, 0x36, 0x11, 0xe, 0x1c, 0x42, 0x7, 0x3b, 0x9, 0xa, 0x34},
62: [12]uint8{0x1, 0xc, 0x36, 0x11, 0x40, 0x44, 0x42, 0x7, 0x3b, 0x9, 0xa, 0x0},
63: [12]uint8{0x34, 0x1, 0x36, 0x11, 0x4, 0x5, 0x42, 0x7, 0x3b, 0x9, 0xa, 0x34},
64: [12]uint8{0x34, 0x35, 0x36, 0x11, 0x40, 0x44, 0x42, 0x7, 0x3b, 0x9, 0x23, 0xb},
65: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x40, 0x41, 0x42, 0x7, 0x8, 0x9, 0xa, 0x34},
66: [12]uint8{0x34, 0x35, 0x36, 0x11, 0x4, 0x5, 0x42, 0x7, 0x3b, 0x9, 0x31, 0x34},
67: [12]uint8{0x34, 0x35, 0x36, 0x11, 0x4, 0x5, 0x42, 0x7, 0x3b, 0x9, 0x32, 0x34},
68: [12]uint8{0x0, 0x1, 0x45, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x27, 0xb},
69: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x46, 0xb},
70: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x47, 0x48, 0xb},
44: [12]uint8{0x1, 0x0, 0x2, 0x3, 0x4, 0x1b, 0x17, 0x7, 0x8, 0x9, 0xa, 0xb},
45: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2b, 0x0},
46: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2c, 0xb},
47: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2d, 0xb},
48: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x2e, 0x7, 0x8, 0x9, 0xa, 0xb},
49: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x2f, 0xb},
50: [12]uint8{0x1, 0xc, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x30, 0xb},
51: [12]uint8{0x1, 0x15, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb},
52: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x31, 0xb},
53: [12]uint8{0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x7, 0x39, 0x9, 0xa, 0xb},
54: [12]uint8{0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x7, 0x39, 0x9, 0x3a, 0xb},
55: [12]uint8{0x32, 0x33, 0x34, 0x11, 0x36, 0x37, 0x38, 0x7, 0x39, 0x9, 0xa, 0xb},
56: [12]uint8{0x32, 0x33, 0x34, 0x11, 0x36, 0x3b, 0x38, 0x7, 0x39, 0x9, 0xa, 0xb},
57: [12]uint8{0x32, 0xc, 0x34, 0x35, 0x36, 0x3c, 0x38, 0x7, 0x39, 0x9, 0xa, 0x0},
58: [12]uint8{0x32, 0x33, 0x34, 0x35, 0x36, 0x3c, 0x38, 0x7, 0x3d, 0x9, 0x22, 0xb},
59: [12]uint8{0x32, 0x33, 0x34, 0x11, 0x3e, 0x3f, 0x40, 0x7, 0x39, 0x9, 0xa, 0x32},
60: [12]uint8{0x32, 0x33, 0x34, 0x41, 0xe, 0x1c, 0x40, 0x7, 0x39, 0x9, 0x1d, 0xb},
61: [12]uint8{0x32, 0x33, 0x34, 0x11, 0xe, 0x1c, 0x40, 0x7, 0x39, 0x9, 0xa, 0x32},
62: [12]uint8{0x1, 0xc, 0x34, 0x11, 0x3e, 0x42, 0x40, 0x7, 0x39, 0x9, 0xa, 0x0},
63: [12]uint8{0x32, 0x1, 0x34, 0x11, 0x4, 0x5, 0x40, 0x7, 0x39, 0x9, 0xa, 0x32},
64: [12]uint8{0x32, 0x33, 0x34, 0x11, 0x3e, 0x42, 0x40, 0x7, 0x39, 0x9, 0x22, 0xb},
65: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x3e, 0x3f, 0x40, 0x7, 0x8, 0x9, 0xa, 0x32},
66: [12]uint8{0x32, 0x33, 0x34, 0x11, 0x4, 0x5, 0x40, 0x7, 0x39, 0x9, 0x2f, 0x32},
67: [12]uint8{0x32, 0x33, 0x34, 0x11, 0x4, 0x5, 0x40, 0x7, 0x39, 0x9, 0x30, 0x32},
68: [12]uint8{0x0, 0x1, 0x43, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x26, 0xb},
69: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x44, 0xb},
70: [12]uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x45, 0x46, 0xb},
} // Size: 876 bytes
var symData = stringset.Set{
Data: "" + // Size: 584 bytes
Data: "" + // Size: 580 bytes
".,;%+-E׉∞NaN:\u00a0\u200e%\u200e\u200e+\u200e-ليس\u00a0رقمًا٪ND·Терхьаш" +
"\u00a0дац'mnne×10^0/00INF−\u200e−ناعددepäluku’ՈչԹარ\u00a0არის\u00a0რიცხვ" +
"იсан\u00a0емес¤¤¤сан\u00a0эмесບໍ່\u200bແມ່ນ\u200bໂຕ\u200bເລກNSဂဏန်းမဟု" +
"တ်သောННне\u00a0числочыыһыла\u00a0буотах·10^–epilohosan\u00a0dälTFЕhaqi" +
"qiy\u00a0son\u00a0emasҳақиқий\u00a0сон\u00a0эмас非數值٫٬؛٪\u061c\u061c+" +
"\u061c-اس؉ليس\u00a0رقم\u200f−\u061c−؉\u200f\u200e+\u200e\u200e-\u200e×۱۰" +
"^\u200e٪\u200e−\u200e၊ཨང་མེན་གྲངས་མེདཨང་མད",
Index: []uint16{ // 74 elements
"\u00a0дац’mnne×10^0/00INF−\u200e−ناعددepälukuՈչԹარ\u00a0არის\u00a0რიცხვი" +
"сан\u00a0емес¤¤¤сан\u00a0эмесບໍ່\u200bແມ່ນ\u200bໂຕ\u200bເລກNSဂဏန်းမဟုတ်" +
"သောННне\u00a0числочыыһыла\u00a0буотах·10^epilohosan\u00a0dälTFЕhaqiqiy" +
"\u00a0son\u00a0emasҳақиқий\u00a0сон\u00a0эмас非數值٫٬؛٪\u061c\u061c+\u061c-" +
"اس؉ليس\u00a0رقم\u200f−\u061c−؉\u200f\u200e+\u200e\u200e-\u200e×۱۰^" +
"\u200e٪\u200e−\u200e၊ཨང་མེན་གྲངས་མེདཨང་མད",
Index: []uint16{ // 72 elements
// Entry 0 - 3F
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0009, 0x000c, 0x000f, 0x0012, 0x0013, 0x0015, 0x001c, 0x0020,
0x0024, 0x0036, 0x0038, 0x003a, 0x003c, 0x0052, 0x0053, 0x0056,
0x0057, 0x005c, 0x0060, 0x0063, 0x0066, 0x006c, 0x0076, 0x007e,
0x0081, 0x0087, 0x00af, 0x00bf, 0x00c5, 0x00d5, 0x0102, 0x0104,
0x012b, 0x012f, 0x013f, 0x015b, 0x0160, 0x0163, 0x016a, 0x0173,
0x0175, 0x0177, 0x0189, 0x01a9, 0x01b2, 0x01b4, 0x01b6, 0x01b8,
0x01bc, 0x01bf, 0x01c2, 0x01c6, 0x01c8, 0x01d6, 0x01dc, 0x01e1,
0x0024, 0x0036, 0x0038, 0x003a, 0x003c, 0x0052, 0x0055, 0x0058,
0x0059, 0x005e, 0x0062, 0x0065, 0x0068, 0x006e, 0x0078, 0x0080,
0x0086, 0x00ae, 0x00be, 0x00c4, 0x00d4, 0x0101, 0x0103, 0x012a,
0x012e, 0x013e, 0x015a, 0x015f, 0x0166, 0x016f, 0x0171, 0x0173,
0x0185, 0x01a5, 0x01ae, 0x01b0, 0x01b2, 0x01b4, 0x01b8, 0x01bb,
0x01be, 0x01c2, 0x01c4, 0x01d2, 0x01d8, 0x01dd, 0x01e2, 0x01e9,
// Entry 40 - 7F
0x01e6, 0x01ed, 0x01f4, 0x01fb, 0x0200, 0x0209, 0x020c, 0x0221,
0x0239, 0x0248,
0x01f0, 0x01f7, 0x01fc, 0x0205, 0x0208, 0x021d, 0x0235, 0x0244,
},
} // Size: 772 bytes
} // Size: 764 bytes
// langToDefaults maps a compact language index to the default numbering system
// and default symbol set
var langToDefaults = [752]uint8{
var langToDefaults = [754]uint8{
// Entry 0 - 3F
0x80, 0x06, 0x13, 0x01, 0x01, 0x01, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x83, 0x02, 0x02, 0x02,
@@ -365,79 +364,80 @@ var langToDefaults = [752]uint8{
0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x14, 0x14,
0x06, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x01,
0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00,
0x06, 0x00, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06,
0x01, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x00,
// Entry 100 - 13F
0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06,
0x00, 0x00, 0x06, 0x06, 0x15, 0x15, 0x06, 0x06,
0x01, 0x01, 0x97, 0x16, 0x16, 0x01, 0x01, 0x01,
0x01, 0x01, 0x17, 0x17, 0x00, 0x00, 0x18, 0x18,
0x18, 0x9a, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x0d, 0x01, 0x01, 0x01, 0x01,
0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
0x06, 0x00, 0x00, 0x06, 0x06, 0x15, 0x15, 0x06,
0x06, 0x01, 0x01, 0x97, 0x16, 0x16, 0x01, 0x01,
0x01, 0x01, 0x01, 0x17, 0x17, 0x00, 0x00, 0x18,
0x18, 0x18, 0x9a, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x06, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x06, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01,
// Entry 140 - 17F
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x9d, 0x00,
0x06, 0x06, 0x19, 0x19, 0x19, 0x19, 0xa0, 0x00,
0x01, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x9d,
0x00, 0x06, 0x06, 0x19, 0x19, 0x19, 0x19, 0xa0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1a, 0x1a, 0x00, 0x00, 0x06,
0x06, 0x06, 0x0b, 0x0b, 0x01, 0x01, 0x1b, 0x1b,
0x0a, 0x0a, 0xa2, 0x00, 0x00, 0x00, 0x06, 0x06,
0x00, 0x00, 0x00, 0x00, 0x1a, 0x1a, 0x00, 0x00,
0x06, 0x06, 0x06, 0x0b, 0x0b, 0x01, 0x01, 0x1b,
0x1b, 0x0a, 0x0a, 0xa2, 0x00, 0x00, 0x00, 0x06,
// Entry 180 - 1BF
0x06, 0x1c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
0x06, 0x06, 0x00, 0x00, 0x00, 0x1d, 0x1d, 0x01,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x01, 0x0d, 0x0d, 0x00, 0x00, 0x1e, 0x1e, 0x06,
0x06, 0x1f, 0x1f, 0x00, 0x00, 0x06, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x1a,
0x00, 0x00, 0x01, 0x01, 0x20, 0x20, 0x00, 0x00,
0x00, 0x21, 0x21, 0x00, 0x00, 0x06, 0x06, 0x00,
0x06, 0x06, 0x1c, 0x06, 0x06, 0x06, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x1d,
0x1d, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x0d, 0x0d, 0x00, 0x00, 0x1e,
0x1e, 0x06, 0x06, 0x1f, 0x1f, 0x00, 0x00, 0x06,
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa5, 0x1a, 0x00, 0x00, 0x01, 0x01, 0x20, 0x20,
0x00, 0x00, 0x00, 0x21, 0x21, 0x00, 0x00, 0x06,
// Entry 1C0 - 1FF
0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06,
0x22, 0x22, 0xa7, 0x00, 0x00, 0x15, 0x15, 0x06,
0x06, 0x00, 0x00, 0x00, 0x00, 0x23, 0x23, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0d, 0x0d, 0x00, 0x00,
0x06, 0x06, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00,
0x00, 0x00, 0xa9, 0x00, 0x00, 0x06, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0xaa, 0x24, 0xac, 0x00,
0x00, 0x00, 0x00, 0xad, 0x14, 0x14, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06,
0x06, 0x06, 0x22, 0x22, 0xa7, 0x00, 0x00, 0x15,
0x15, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x23,
0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0d,
0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06,
0x00, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0xaa, 0x24,
0xac, 0x00, 0x00, 0x00, 0x00, 0xad, 0x14, 0x14,
// Entry 200 - 23F
0x06, 0x06, 0x06, 0xb0, 0x00, 0x00, 0xb1, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x01, 0x01,
0x14, 0x14, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0x06, 0xb0, 0x00, 0x00,
0xb1, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x01, 0x01, 0x14, 0x14, 0x06, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x25, 0x25, 0x25, 0xb4, 0xb6, 0x1a,
0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0xb8,
0x26, 0x06, 0x01, 0x06, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x06,
0x00, 0x00, 0x00, 0x00, 0x25, 0x25, 0x25, 0xb4,
0xb6, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
0x01, 0xb8, 0x26, 0x06, 0x01, 0x06, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
// Entry 240 - 27F
0x00, 0x00, 0x19, 0x19, 0x06, 0x06, 0x06, 0x06,
0x06, 0x00, 0x00, 0x27, 0x27, 0x27, 0x27, 0x27,
0x27, 0x27, 0x06, 0x06, 0x00, 0x00, 0x28, 0x28,
0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x29, 0x29,
0x29, 0x06, 0x06, 0x0d, 0x0d, 0x06, 0x06, 0x01,
0x01, 0x01, 0x01, 0x01, 0x2a, 0x2a, 0x2b, 0x2b,
0x2c, 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x2d, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x06, 0x00, 0x00, 0x19, 0x19, 0x06, 0x06,
0x06, 0x06, 0x06, 0x00, 0x00, 0x27, 0x27, 0x27,
0x27, 0x27, 0x27, 0x27, 0x06, 0x06, 0x00, 0x00,
0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29,
0x29, 0x29, 0x29, 0x06, 0x06, 0x0d, 0x0d, 0x06,
0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2a, 0x2a,
0x2b, 0x2b, 0x2c, 0x2c, 0x00, 0x00, 0x00, 0x2d,
0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Entry 280 - 2BF
0x01, 0x01, 0x01, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
0x00, 0xba, 0x20, 0x20, 0x20, 0x00, 0x06, 0x00,
0x00, 0x01, 0x01, 0x01, 0x01, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x00, 0x00, 0x00, 0xba, 0x20, 0x20, 0x20, 0x00,
0x06, 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, 0x2e, 0x2e, 0x00, 0x2f, 0x2f,
0x06, 0x06, 0x06, 0x00, 0x0d, 0x0d, 0x01, 0x01,
0x00, 0x00, 0x30, 0x30, 0xbd, 0xbf, 0x1a, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x2e, 0x00,
0x2f, 0x2f, 0x06, 0x06, 0x06, 0x00, 0x0d, 0x0d,
0x01, 0x01, 0x00, 0x00, 0x30, 0x30, 0xbd, 0xbf,
// Entry 2C0 - 2FF
0xc2, 0x26, 0xc4, 0x32, 0x31, 0x31, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x34, 0x34, 0x01, 0x01, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x34, 0x34, 0x34, 0x34, 0x00, 0x00,
} // Size: 752 bytes
0x1a, 0xc0, 0xc2, 0x26, 0xc4, 0x32, 0x31, 0x31,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x00,
0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x34, 0x34, 0x01, 0x01, 0xc6, 0x00,
0x00, 0x00, 0x00, 0x00, 0x34, 0x34, 0x34, 0x34,
0x00, 0x00,
} // Size: 754 bytes
// langToAlt is a list of numbering system and symbol set pairs, sorted and
// marked by compact language index.
@@ -464,59 +464,59 @@ var langToAlt = []altSymData{ // 73 elements
20: {compactTag: 0x63, system: 0x3, symIndex: 0x35},
21: {compactTag: 0x7b, system: 0x36, symIndex: 0x46},
22: {compactTag: 0x7b, system: 0x0, symIndex: 0x0},
23: {compactTag: 0x112, system: 0x4, symIndex: 0x3c},
24: {compactTag: 0x112, system: 0x0, symIndex: 0x16},
25: {compactTag: 0x112, system: 0x3, symIndex: 0x37},
26: {compactTag: 0x121, system: 0x0, symIndex: 0x1},
27: {compactTag: 0x121, system: 0x3, symIndex: 0x38},
28: {compactTag: 0x121, system: 0x4, symIndex: 0x3d},
29: {compactTag: 0x156, system: 0x0, symIndex: 0x0},
30: {compactTag: 0x156, system: 0x3, symIndex: 0x37},
31: {compactTag: 0x156, system: 0x4, symIndex: 0x3b},
32: {compactTag: 0x15e, system: 0x0, symIndex: 0x0},
33: {compactTag: 0x15e, system: 0x3, symIndex: 0x35},
34: {compactTag: 0x17a, system: 0x0, symIndex: 0x0},
35: {compactTag: 0x17a, system: 0x3, symIndex: 0x35},
36: {compactTag: 0x17a, system: 0x4, symIndex: 0x3b},
37: {compactTag: 0x1ae, system: 0x4, symIndex: 0x3b},
38: {compactTag: 0x1ae, system: 0x0, symIndex: 0x1a},
39: {compactTag: 0x1ca, system: 0x4, symIndex: 0x3b},
40: {compactTag: 0x1ca, system: 0x0, symIndex: 0x0},
41: {compactTag: 0x1ea, system: 0xb, symIndex: 0x0},
42: {compactTag: 0x1f4, system: 0x23, symIndex: 0x44},
43: {compactTag: 0x1f4, system: 0x0, symIndex: 0x24},
44: {compactTag: 0x1f6, system: 0x4, symIndex: 0x3b},
45: {compactTag: 0x1fb, system: 0x0, symIndex: 0x14},
46: {compactTag: 0x1fb, system: 0x3, symIndex: 0x39},
47: {compactTag: 0x1fb, system: 0x4, symIndex: 0x3e},
48: {compactTag: 0x203, system: 0xb, symIndex: 0x0},
49: {compactTag: 0x206, system: 0x0, symIndex: 0x6},
50: {compactTag: 0x206, system: 0x3, symIndex: 0x35},
51: {compactTag: 0x206, system: 0x4, symIndex: 0x3b},
52: {compactTag: 0x225, system: 0x0, symIndex: 0x0},
53: {compactTag: 0x225, system: 0x4, symIndex: 0x3f},
54: {compactTag: 0x226, system: 0x4, symIndex: 0x3b},
55: {compactTag: 0x226, system: 0x0, symIndex: 0x1a},
56: {compactTag: 0x22f, system: 0x4, symIndex: 0x3b},
57: {compactTag: 0x22f, system: 0x0, symIndex: 0x26},
58: {compactTag: 0x291, system: 0x0, symIndex: 0x20},
59: {compactTag: 0x291, system: 0x3, symIndex: 0x3a},
60: {compactTag: 0x291, system: 0x4, symIndex: 0x40},
61: {compactTag: 0x2bc, system: 0x0, symIndex: 0x1a},
62: {compactTag: 0x2bc, system: 0x4, symIndex: 0x41},
63: {compactTag: 0x2bd, system: 0x4, symIndex: 0x41},
64: {compactTag: 0x2bf, system: 0x0, symIndex: 0x31},
65: {compactTag: 0x2bf, system: 0x4, symIndex: 0x42},
66: {compactTag: 0x2c0, system: 0x4, symIndex: 0x3b},
67: {compactTag: 0x2c0, system: 0x0, symIndex: 0x26},
68: {compactTag: 0x2c2, system: 0x0, symIndex: 0x32},
69: {compactTag: 0x2c2, system: 0x4, symIndex: 0x43},
70: {compactTag: 0x2e4, system: 0x0, symIndex: 0x0},
71: {compactTag: 0x2e4, system: 0x3, symIndex: 0x35},
72: {compactTag: 0x2e4, system: 0x4, symIndex: 0x3b},
23: {compactTag: 0x113, system: 0x4, symIndex: 0x3c},
24: {compactTag: 0x113, system: 0x0, symIndex: 0x16},
25: {compactTag: 0x113, system: 0x3, symIndex: 0x37},
26: {compactTag: 0x122, system: 0x0, symIndex: 0x1},
27: {compactTag: 0x122, system: 0x3, symIndex: 0x38},
28: {compactTag: 0x122, system: 0x4, symIndex: 0x3d},
29: {compactTag: 0x157, system: 0x0, symIndex: 0x0},
30: {compactTag: 0x157, system: 0x3, symIndex: 0x37},
31: {compactTag: 0x157, system: 0x4, symIndex: 0x3b},
32: {compactTag: 0x15f, system: 0x0, symIndex: 0x0},
33: {compactTag: 0x15f, system: 0x3, symIndex: 0x35},
34: {compactTag: 0x17b, system: 0x0, symIndex: 0x0},
35: {compactTag: 0x17b, system: 0x3, symIndex: 0x35},
36: {compactTag: 0x17b, system: 0x4, symIndex: 0x3b},
37: {compactTag: 0x1b0, system: 0x4, symIndex: 0x3b},
38: {compactTag: 0x1b0, system: 0x0, symIndex: 0x1a},
39: {compactTag: 0x1cc, system: 0x4, symIndex: 0x3b},
40: {compactTag: 0x1cc, system: 0x0, symIndex: 0x0},
41: {compactTag: 0x1ec, system: 0xb, symIndex: 0x0},
42: {compactTag: 0x1f6, system: 0x23, symIndex: 0x44},
43: {compactTag: 0x1f6, system: 0x0, symIndex: 0x24},
44: {compactTag: 0x1f8, system: 0x4, symIndex: 0x3b},
45: {compactTag: 0x1fd, system: 0x0, symIndex: 0x14},
46: {compactTag: 0x1fd, system: 0x3, symIndex: 0x39},
47: {compactTag: 0x1fd, system: 0x4, symIndex: 0x3e},
48: {compactTag: 0x205, system: 0xb, symIndex: 0x0},
49: {compactTag: 0x208, system: 0x0, symIndex: 0x6},
50: {compactTag: 0x208, system: 0x3, symIndex: 0x35},
51: {compactTag: 0x208, system: 0x4, symIndex: 0x3b},
52: {compactTag: 0x227, system: 0x0, symIndex: 0x0},
53: {compactTag: 0x227, system: 0x4, symIndex: 0x3f},
54: {compactTag: 0x228, system: 0x4, symIndex: 0x3b},
55: {compactTag: 0x228, system: 0x0, symIndex: 0x1a},
56: {compactTag: 0x231, system: 0x4, symIndex: 0x3b},
57: {compactTag: 0x231, system: 0x0, symIndex: 0x26},
58: {compactTag: 0x293, system: 0x0, symIndex: 0x20},
59: {compactTag: 0x293, system: 0x3, symIndex: 0x3a},
60: {compactTag: 0x293, system: 0x4, symIndex: 0x40},
61: {compactTag: 0x2be, system: 0x0, symIndex: 0x1a},
62: {compactTag: 0x2be, system: 0x4, symIndex: 0x41},
63: {compactTag: 0x2bf, system: 0x4, symIndex: 0x41},
64: {compactTag: 0x2c1, system: 0x0, symIndex: 0x31},
65: {compactTag: 0x2c1, system: 0x4, symIndex: 0x42},
66: {compactTag: 0x2c2, system: 0x4, symIndex: 0x3b},
67: {compactTag: 0x2c2, system: 0x0, symIndex: 0x26},
68: {compactTag: 0x2c4, system: 0x0, symIndex: 0x32},
69: {compactTag: 0x2c4, system: 0x4, symIndex: 0x43},
70: {compactTag: 0x2e6, system: 0x0, symIndex: 0x0},
71: {compactTag: 0x2e6, system: 0x3, symIndex: 0x35},
72: {compactTag: 0x2e6, system: 0x4, symIndex: 0x3b},
} // Size: 316 bytes
var tagToDecimal = []uint8{ // 752 elements
var tagToDecimal = []uint8{ // 754 elements
// Entry 0 - 3F
0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
@@ -566,10 +566,10 @@ var tagToDecimal = []uint8{ // 752 elements
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05,
0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
// Entry 180 - 1BF
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
@@ -577,16 +577,16 @@ var tagToDecimal = []uint8{ // 752 elements
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x05, 0x05,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05,
0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
// Entry 1C0 - 1FF
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05,
0x01, 0x01, 0x05, 0x05, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x05, 0x05, 0x01, 0x01, 0x05, 0x05, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
// Entry 200 - 23F
@@ -594,8 +594,8 @@ var tagToDecimal = []uint8{ // 752 elements
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x05, 0x05, 0x01, 0x01, 0x01, 0x05, 0x01, 0x01,
0x05, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x05, 0x05, 0x01, 0x01, 0x01, 0x05,
0x01, 0x01, 0x05, 0x05, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
// Entry 240 - 27F
@@ -611,7 +611,7 @@ var tagToDecimal = []uint8{ // 752 elements
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x05, 0x05, 0x05, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x05,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
@@ -623,9 +623,10 @@ var tagToDecimal = []uint8{ // 752 elements
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
} // Size: 776 bytes
0x01, 0x01,
} // Size: 778 bytes
var tagToScientific = []uint8{ // 752 elements
var tagToScientific = []uint8{ // 754 elements
// Entry 0 - 3F
0x02, 0x02, 0x09, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
@@ -675,10 +676,10 @@ var tagToScientific = []uint8{ // 752 elements
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, 0x02, 0x02, 0x0d,
0x0d, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0d, 0x0d,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x0d, 0x0d, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
// Entry 180 - 1BF
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
@@ -691,11 +692,11 @@ var tagToScientific = []uint8{ // 752 elements
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
// Entry 1C0 - 1FF
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x0e, 0x0e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x0e, 0x0e, 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, 0x02, 0x0d, 0x0d, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x0d, 0x0d, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
// Entry 200 - 23F
@@ -703,8 +704,8 @@ var tagToScientific = []uint8{ // 752 elements
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, 0x0d, 0x02, 0x02,
0x0d, 0x0d, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0d,
0x02, 0x02, 0x0d, 0x0d, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
// Entry 240 - 27F
@@ -713,7 +714,7 @@ var tagToScientific = []uint8{ // 752 elements
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, 0x0e, 0x0e, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0e, 0x0e,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
// Entry 280 - 2BF
@@ -732,9 +733,10 @@ var tagToScientific = []uint8{ // 752 elements
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
} // Size: 776 bytes
0x02, 0x02,
} // Size: 778 bytes
var tagToPercent = []uint8{ // 752 elements
var tagToPercent = []uint8{ // 754 elements
// Entry 0 - 3F
0x04, 0x04, 0x0a, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
@@ -769,87 +771,88 @@ var tagToPercent = []uint8{ // 752 elements
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x03,
0x03, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04,
0x03, 0x03, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03,
// Entry 100 - 13F
0x03, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x0b, 0x0b,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03,
0x03, 0x03, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x0b,
0x0b, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
// Entry 140 - 17F
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x06,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x04,
0x04, 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04,
0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06,
0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x06,
0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
// Entry 180 - 1BF
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06,
0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
// Entry 1C0 - 1FF
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 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, 0x03, 0x03, 0x03, 0x04, 0x04,
// Entry 200 - 23F
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x06, 0x06, 0x04, 0x04, 0x04, 0x06, 0x04, 0x04,
0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
// Entry 240 - 27F
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
0x03, 0x03, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
// Entry 280 - 2BF
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x03, 0x03, 0x04, 0x04, 0x04,
0x0f, 0x0f, 0x0f, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x04,
// Entry 2C0 - 2FF
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x06,
0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
// Entry 1C0 - 1FF
0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
0x03, 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, 0x03, 0x03, 0x03,
// Entry 200 - 23F
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
} // Size: 776 bytes
0x04, 0x04, 0x06, 0x06, 0x04, 0x04, 0x04, 0x06,
0x04, 0x04, 0x06, 0x06, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
// Entry 240 - 27F
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x04, 0x04, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x03,
0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
// Entry 280 - 2BF
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x04,
0x04, 0x04, 0x0f, 0x0f, 0x0f, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x06,
// Entry 2C0 - 2FF
0x06, 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, 0x03, 0x03, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04,
} // Size: 778 bytes
var formats = []Pattern{Pattern{Affix: "",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0x0,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x0,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x0,
@@ -863,10 +866,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0x9,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x9,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x3,
0x0},
Flags: 0x0,
@@ -880,10 +883,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0x3,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x3,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x0,
@@ -897,10 +900,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x00\x03\u00a0%",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x64,
FormatWidth: 0x7,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x7,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x3,
0x0},
Flags: 0x0,
@@ -914,10 +917,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x00\x01%",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x64,
FormatWidth: 0x6,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x6,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x3,
0x0},
Flags: 0x0,
@@ -931,10 +934,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0xc,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0xc,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x3,
0x2},
Flags: 0x0,
@@ -948,10 +951,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x00\x01%",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x64,
FormatWidth: 0x9,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x9,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x3,
0x2},
Flags: 0x0,
@@ -965,10 +968,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x00\x03\u00a0%",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x64,
FormatWidth: 0xa,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0xa,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x3,
0x2},
Flags: 0x0,
@@ -982,10 +985,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0x9,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x9,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x0,
@@ -999,13 +1002,13 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0xd,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0xd,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x2,
Flags: 0x4,
MinIntegerDigits: 0x1,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x6,
@@ -1016,10 +1019,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x00\x01%",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x64,
FormatWidth: 0x3,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x3,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x0,
@@ -1033,11 +1036,11 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x03%\u00a0\x00",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x64,
FormatWidth: 0x7,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x7,
GroupingSize: [2]uint8{0x0,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x3,
0x0},
Flags: 0x0,
MinIntegerDigits: 0x1,
@@ -1050,10 +1053,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x03%\u00a0\x00\x04%\u00a0-\x00",
Offset: 0x0,
NegOffset: 0x5,
Multiplier: 0x64,
FormatWidth: 0x7,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x7,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x3,
0x0},
Flags: 0x0,
@@ -1067,10 +1070,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x01[\x01]",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0x5,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x5,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x0,
@@ -1084,10 +1087,10 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x0,
FormatWidth: 0x1,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x1,
DigitShift: 0x0,
GroupingSize: [2]uint8{0x0,
0x0},
Flags: 0x0,
@@ -1101,11 +1104,11 @@ var formats = []Pattern{Pattern{Affix: "",
Pattern{Affix: "\x01%\x00",
Offset: 0x0,
NegOffset: 0x0,
Multiplier: 0x64,
FormatWidth: 0x6,
RoundIncrement: 0x0,
PadRune: 0,
FormatWidth: 0x6,
GroupingSize: [2]uint8{0x0,
DigitShift: 0x2,
GroupingSize: [2]uint8{0x3,
0x0},
Flags: 0x0,
MinIntegerDigits: 0x1,
@@ -1116,4 +1119,4 @@ var formats = []Pattern{Pattern{Affix: "",
MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0}}
// Total table size 7101 bytes (6KiB); checksum: A4A81DF0
// Total table size 7101 bytes (6KiB); checksum: 5190D0B3
+63 -62
View File
@@ -4,7 +4,7 @@ package internal
// Parent maps a compact index of a tag to the compact index of the parent of
// this tag.
var Parent = []uint16{ // 752 elements
var Parent = []uint16{ // 754 elements
// Entry 0 - 3F
0x0000, 0x0053, 0x00e5, 0x0000, 0x0003, 0x0003, 0x0000, 0x0006,
0x0000, 0x0008, 0x0000, 0x000a, 0x0000, 0x000c, 0x000c, 0x000c,
@@ -40,77 +40,78 @@ var Parent = []uint16{ // 752 elements
0x0086, 0x0086, 0x0086, 0x0086, 0x0085, 0x0085, 0x0086, 0x0086,
0x0085, 0x0086, 0x0086, 0x0086, 0x0086, 0x0086, 0x0000, 0x00ee,
0x0000, 0x00f0, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f1,
0x00f1, 0x00f1, 0x00f0, 0x00f1, 0x00f0, 0x00f0, 0x00f1, 0x00f1,
0x00f1, 0x00f1, 0x00f1, 0x00f0, 0x00f1, 0x00f0, 0x00f0, 0x00f1,
// Entry 100 - 13F
0x00f0, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f0, 0x00f1, 0x00f1,
0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x0000, 0x010c, 0x0000, 0x010e,
0x0000, 0x0110, 0x0000, 0x0112, 0x0112, 0x0000, 0x0115, 0x0115,
0x0115, 0x0115, 0x0000, 0x011a, 0x0000, 0x011c, 0x0000, 0x011e,
0x011e, 0x0000, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121,
0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121,
0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121,
0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121,
0x00f1, 0x00f0, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f0, 0x00f1,
0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x0000, 0x010d, 0x0000,
0x010f, 0x0000, 0x0111, 0x0000, 0x0113, 0x0113, 0x0000, 0x0116,
0x0116, 0x0116, 0x0116, 0x0000, 0x011b, 0x0000, 0x011d, 0x0000,
0x011f, 0x011f, 0x0000, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
// Entry 140 - 17F
0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121,
0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121, 0x0121,
0x0000, 0x0150, 0x0000, 0x0152, 0x0000, 0x0154, 0x0000, 0x0156,
0x0000, 0x0158, 0x0000, 0x015a, 0x015a, 0x015a, 0x0000, 0x015e,
0x0000, 0x0000, 0x0161, 0x0000, 0x0163, 0x0000, 0x0165, 0x0165,
0x0165, 0x0000, 0x0169, 0x0000, 0x016b, 0x0000, 0x016d, 0x0000,
0x016f, 0x016f, 0x0000, 0x0172, 0x0000, 0x0174, 0x0000, 0x0176,
0x0000, 0x0178, 0x0000, 0x017a, 0x0000, 0x017c, 0x0000, 0x017e,
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122, 0x0122,
0x0122, 0x0000, 0x0151, 0x0000, 0x0153, 0x0000, 0x0155, 0x0000,
0x0157, 0x0000, 0x0159, 0x0000, 0x015b, 0x015b, 0x015b, 0x0000,
0x015f, 0x0000, 0x0000, 0x0162, 0x0000, 0x0164, 0x0000, 0x0166,
0x0166, 0x0166, 0x0000, 0x016a, 0x0000, 0x016c, 0x0000, 0x016e,
0x0000, 0x0170, 0x0170, 0x0000, 0x0173, 0x0000, 0x0175, 0x0000,
0x0177, 0x0000, 0x0179, 0x0000, 0x017b, 0x0000, 0x017d, 0x0000,
// Entry 180 - 1BF
0x0000, 0x0180, 0x0180, 0x0180, 0x0000, 0x0000, 0x0185, 0x0000,
0x0000, 0x0188, 0x0000, 0x018a, 0x0000, 0x0000, 0x018d, 0x0000,
0x018f, 0x0000, 0x0000, 0x0192, 0x0000, 0x0000, 0x0195, 0x0000,
0x017f, 0x0000, 0x0181, 0x0181, 0x0181, 0x0181, 0x0000, 0x0000,
0x0187, 0x0000, 0x0000, 0x018a, 0x0000, 0x018c, 0x0000, 0x0000,
0x018f, 0x0000, 0x0191, 0x0000, 0x0000, 0x0194, 0x0000, 0x0000,
0x0197, 0x0000, 0x0199, 0x0000, 0x019b, 0x0000, 0x019d, 0x0000,
0x019f, 0x0000, 0x01a1, 0x0000, 0x01a3, 0x0000, 0x01a5, 0x0000,
0x01a7, 0x0000, 0x01a9, 0x01a9, 0x0000, 0x01ac, 0x0000, 0x01ae,
0x0000, 0x01b0, 0x0000, 0x01b2, 0x0000, 0x01b4, 0x0000, 0x0000,
0x01b7, 0x0000, 0x01b9, 0x0000, 0x01bb, 0x0000, 0x01bd, 0x0000,
0x01a7, 0x0000, 0x01a9, 0x0000, 0x01ab, 0x01ab, 0x0000, 0x01ae,
0x0000, 0x01b0, 0x0000, 0x01b2, 0x0000, 0x01b4, 0x0000, 0x01b6,
0x0000, 0x0000, 0x01b9, 0x0000, 0x01bb, 0x0000, 0x01bd, 0x0000,
// Entry 1C0 - 1FF
0x01bf, 0x0000, 0x01c1, 0x0000, 0x01c3, 0x01c3, 0x01c3, 0x01c3,
0x0000, 0x01c8, 0x0000, 0x01ca, 0x01ca, 0x0000, 0x01cd, 0x0000,
0x01bf, 0x0000, 0x01c1, 0x0000, 0x01c3, 0x0000, 0x01c5, 0x01c5,
0x01c5, 0x01c5, 0x0000, 0x01ca, 0x0000, 0x01cc, 0x01cc, 0x0000,
0x01cf, 0x0000, 0x01d1, 0x0000, 0x01d3, 0x0000, 0x01d5, 0x0000,
0x01d7, 0x01d7, 0x0000, 0x01da, 0x0000, 0x01dc, 0x0000, 0x01de,
0x01d7, 0x0000, 0x01d9, 0x01d9, 0x0000, 0x01dc, 0x0000, 0x01de,
0x0000, 0x01e0, 0x0000, 0x01e2, 0x0000, 0x01e4, 0x0000, 0x01e6,
0x0000, 0x01e8, 0x0000, 0x01ea, 0x0000, 0x01ec, 0x01ec, 0x01ec,
0x0000, 0x01f0, 0x0000, 0x01f2, 0x0000, 0x01f4, 0x0000, 0x01f6,
0x0000, 0x0000, 0x01f9, 0x0000, 0x01fb, 0x01fb, 0x0000, 0x01fe,
0x0000, 0x01e8, 0x0000, 0x01ea, 0x0000, 0x01ec, 0x0000, 0x01ee,
0x01ee, 0x01ee, 0x0000, 0x01f2, 0x0000, 0x01f4, 0x0000, 0x01f6,
0x0000, 0x01f8, 0x0000, 0x0000, 0x01fb, 0x0000, 0x01fd, 0x01fd,
// Entry 200 - 23F
0x0000, 0x0200, 0x0200, 0x0000, 0x0203, 0x0203, 0x0000, 0x0206,
0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0206, 0x0000, 0x020e,
0x0000, 0x0210, 0x0000, 0x0212, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0218, 0x0000, 0x0000, 0x021b, 0x0000, 0x021d, 0x021d,
0x0000, 0x0220, 0x0000, 0x0222, 0x0222, 0x0000, 0x0000, 0x0226,
0x0225, 0x0225, 0x0000, 0x0000, 0x022b, 0x0000, 0x022d, 0x0000,
0x022f, 0x0000, 0x023b, 0x0231, 0x023b, 0x023b, 0x023b, 0x023b,
0x023b, 0x023b, 0x023b, 0x0231, 0x023b, 0x023b, 0x0000, 0x023e,
0x0000, 0x0200, 0x0000, 0x0202, 0x0202, 0x0000, 0x0205, 0x0205,
0x0000, 0x0208, 0x0208, 0x0208, 0x0208, 0x0208, 0x0208, 0x0208,
0x0000, 0x0210, 0x0000, 0x0212, 0x0000, 0x0214, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x021a, 0x0000, 0x0000, 0x021d, 0x0000,
0x021f, 0x021f, 0x0000, 0x0222, 0x0000, 0x0224, 0x0224, 0x0000,
0x0000, 0x0228, 0x0227, 0x0227, 0x0000, 0x0000, 0x022d, 0x0000,
0x022f, 0x0000, 0x0231, 0x0000, 0x023d, 0x0233, 0x023d, 0x023d,
0x023d, 0x023d, 0x023d, 0x023d, 0x023d, 0x0233, 0x023d, 0x023d,
// Entry 240 - 27F
0x023e, 0x023e, 0x0000, 0x0242, 0x0000, 0x0244, 0x0000, 0x0246,
0x0246, 0x0000, 0x0249, 0x0000, 0x024b, 0x024b, 0x024b, 0x024b,
0x024b, 0x024b, 0x0000, 0x0252, 0x0000, 0x0254, 0x0000, 0x0256,
0x0000, 0x0258, 0x0000, 0x025a, 0x0000, 0x0000, 0x025d, 0x025d,
0x025d, 0x0000, 0x0261, 0x0000, 0x0263, 0x0000, 0x0265, 0x0000,
0x0000, 0x0268, 0x0267, 0x0267, 0x0000, 0x026c, 0x0000, 0x026e,
0x0000, 0x0270, 0x0000, 0x0000, 0x0000, 0x0000, 0x0275, 0x0000,
0x0000, 0x0278, 0x0000, 0x027a, 0x027a, 0x027a, 0x027a, 0x0000,
0x0000, 0x0240, 0x0240, 0x0240, 0x0000, 0x0244, 0x0000, 0x0246,
0x0000, 0x0248, 0x0248, 0x0000, 0x024b, 0x0000, 0x024d, 0x024d,
0x024d, 0x024d, 0x024d, 0x024d, 0x0000, 0x0254, 0x0000, 0x0256,
0x0000, 0x0258, 0x0000, 0x025a, 0x0000, 0x025c, 0x0000, 0x0000,
0x025f, 0x025f, 0x025f, 0x0000, 0x0263, 0x0000, 0x0265, 0x0000,
0x0267, 0x0000, 0x0000, 0x026a, 0x0269, 0x0269, 0x0000, 0x026e,
0x0000, 0x0270, 0x0000, 0x0272, 0x0000, 0x0000, 0x0000, 0x0000,
0x0277, 0x0000, 0x0000, 0x027a, 0x0000, 0x027c, 0x027c, 0x027c,
// Entry 280 - 2BF
0x027f, 0x027f, 0x027f, 0x0000, 0x0283, 0x0283, 0x0283, 0x0283,
0x0283, 0x0000, 0x0289, 0x0289, 0x0289, 0x0289, 0x0000, 0x0000,
0x0000, 0x0000, 0x0291, 0x0291, 0x0291, 0x0000, 0x0295, 0x0295,
0x0295, 0x0295, 0x0000, 0x0000, 0x029b, 0x029b, 0x029b, 0x029b,
0x0000, 0x02a0, 0x0000, 0x02a2, 0x02a2, 0x0000, 0x02a5, 0x0000,
0x02a7, 0x02a7, 0x0000, 0x0000, 0x02ab, 0x0000, 0x0000, 0x02ae,
0x0000, 0x02b0, 0x02b0, 0x0000, 0x0000, 0x02b4, 0x0000, 0x02b6,
0x0000, 0x02b8, 0x0000, 0x02ba, 0x0000, 0x02bc, 0x02bc, 0x0000,
0x027c, 0x0000, 0x0281, 0x0281, 0x0281, 0x0000, 0x0285, 0x0285,
0x0285, 0x0285, 0x0285, 0x0000, 0x028b, 0x028b, 0x028b, 0x028b,
0x0000, 0x0000, 0x0000, 0x0000, 0x0293, 0x0293, 0x0293, 0x0000,
0x0297, 0x0297, 0x0297, 0x0297, 0x0000, 0x0000, 0x029d, 0x029d,
0x029d, 0x029d, 0x0000, 0x02a2, 0x0000, 0x02a4, 0x02a4, 0x0000,
0x02a7, 0x0000, 0x02a9, 0x02a9, 0x0000, 0x0000, 0x02ad, 0x0000,
0x0000, 0x02b0, 0x0000, 0x02b2, 0x02b2, 0x0000, 0x0000, 0x02b6,
0x0000, 0x02b8, 0x0000, 0x02ba, 0x0000, 0x02bc, 0x0000, 0x02be,
// Entry 2C0 - 2FF
0x0000, 0x02c0, 0x0000, 0x02c2, 0x02bf, 0x02bf, 0x0000, 0x0000,
0x02c7, 0x02c6, 0x02c6, 0x0000, 0x0000, 0x02cc, 0x0000, 0x02ce,
0x0000, 0x02d0, 0x0000, 0x0000, 0x02d3, 0x0000, 0x0000, 0x0000,
0x02d7, 0x0000, 0x02d9, 0x0000, 0x02db, 0x0000, 0x02dd, 0x02dd,
0x0000, 0x02e0, 0x0000, 0x02e2, 0x0000, 0x02e4, 0x02e4, 0x02e4,
0x02e4, 0x02e4, 0x0000, 0x02ea, 0x02eb, 0x02ea, 0x0000, 0x02ee,
} // Size: 1528 bytes
0x02be, 0x0000, 0x0000, 0x02c2, 0x0000, 0x02c4, 0x02c1, 0x02c1,
0x0000, 0x0000, 0x02c9, 0x02c8, 0x02c8, 0x0000, 0x0000, 0x02ce,
0x0000, 0x02d0, 0x0000, 0x02d2, 0x0000, 0x0000, 0x02d5, 0x0000,
0x0000, 0x0000, 0x02d9, 0x0000, 0x02db, 0x0000, 0x02dd, 0x0000,
0x02df, 0x02df, 0x0000, 0x02e2, 0x0000, 0x02e4, 0x0000, 0x02e6,
0x02e6, 0x02e6, 0x02e6, 0x02e6, 0x0000, 0x02ec, 0x02ed, 0x02ec,
0x0000, 0x02f0,
} // Size: 1532 bytes
// Total table size 1528 bytes (1KiB); checksum: B99CF952
// Total table size 1532 bytes (1KiB); checksum: 90718A2