summaryrefslogtreecommitdiffstats
path: root/vendor/golang.org/x/text/internal/number
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/text/internal/number')
-rw-r--r--vendor/golang.org/x/text/internal/number/decimal.go185
-rw-r--r--vendor/golang.org/x/text/internal/number/decimal_test.go63
-rwxr-xr-xvendor/golang.org/x/text/internal/number/format.go176
-rwxr-xr-xvendor/golang.org/x/text/internal/number/format_test.go70
-rw-r--r--vendor/golang.org/x/text/internal/number/pattern.go92
-rw-r--r--vendor/golang.org/x/text/internal/number/pattern_test.go333
-rw-r--r--vendor/golang.org/x/text/internal/number/tables.go378
7 files changed, 778 insertions, 519 deletions
diff --git a/vendor/golang.org/x/text/internal/number/decimal.go b/vendor/golang.org/x/text/internal/number/decimal.go
index 199c7e416..62074e7d7 100644
--- a/vendor/golang.org/x/text/internal/number/decimal.go
+++ b/vendor/golang.org/x/text/internal/number/decimal.go
@@ -25,22 +25,39 @@ const (
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
+const maxIntDigits = 20
+
+// A Decimal represents a floating point number in decimal format.
+// Digits represents a number [0, 1.0), and the absolute value represented by
+// Decimal is Digits * 10^Exp. Leading and trailing zeros may be omitted and Exp
+// may point outside a valid position in Digits.
+//
+// Examples:
+// Number Decimal
+// 12345 Digits: [1, 2, 3, 4, 5], Exp: 5
+// 12.345 Digits: [1, 2, 3, 4, 5], Exp: 2
+// 12000 Digits: [1, 2], Exp: 5
+// 12000.00 Digits: [1, 2], Exp: 5
+// 0.00123 Digits: [1, 2, 3], Exp: -2
+// 0 Digits: [], Exp: 0
+type Decimal struct {
+ digits
- Precision int32 // maximum number of significant digits.
- Scale int32 // maximum number of decimals after the dot.
+ buf [maxIntDigits]byte
}
-const maxIntDigits = 20
+type digits struct {
+ Digits []byte // mantissa digits, big-endian
+ Exp int32 // exponent
+ Neg bool
+ Inf bool // Takes precedence over Digits and Exp.
+ NaN bool // Takes precedence over Inf.
+}
-// 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.
+// Digits represents a floating point number represented in digits of the
+// base in which a number is to be displayed. It is similar to Decimal, but
+// keeps track of trailing fraction zeros and the comma placement for
+// engineering notation. Digits must have at least one digit.
//
// Examples:
// Number Decimal
@@ -51,25 +68,31 @@ const maxIntDigits = 20
// 12000.00 Digits: [1, 2], Exp: 5 End: 7
// 0.00123 Digits: [1, 2, 3], Exp: -2 End: 3
// 0 Digits: [], Exp: 0 End: 1
-// scientific:
-// 0 Digits: [], Exp: 0, End: 1, Comma: 0
+// scientific (actual exp is Exp - Comma)
+// 0e0 Digits: [0], Exp: 1, End: 1, Comma: 1
+// .0e0 Digits: [0], Exp: 0, End: 1, Comma: 0
+// 0.0e0 Digits: [0], Exp: 1, End: 2, Comma: 1
// 1.23e4 Digits: [1, 2, 3], Exp: 5, End: 3, Comma: 1
+// .123e5 Digits: [1, 2, 3], Exp: 5, End: 3, Comma: 0
// engineering
// 12.3e3 Digits: [1, 2, 3], Exp: 5, End: 3, Comma: 2
-type Decimal struct {
- Digits []byte // mantissa digits, big-endian
- Exp int32 // exponent
+type Digits struct {
+ digits
// End indicates the end position of the number.
End int32 // For decimals Exp <= End. For scientific len(Digits) <= End.
// Comma is used for the comma position for scientific (always 0 or 1) and
// engineering notation (always 0, 1, 2, or 3).
Comma uint8
+ // IsScientific indicates whether this number is to be rendered as a
+ // scientific number.
+ IsScientific bool
+}
- Neg bool
- Inf bool // Takes precedence over Digits and Exp.
- NaN bool // Takes precedence over Inf.
-
- buf [maxIntDigits]byte
+func (d *Digits) NumFracDigits() int {
+ if d.Exp >= d.End {
+ return 0
+ }
+ return int(d.End - d.Exp)
}
// normalize returns a new Decimal with leading and trailing zeros removed.
@@ -151,7 +174,7 @@ func appendZeros(buf []byte, n int) []byte {
return buf
}
-func (d *Decimal) round(mode RoundingMode, n int) {
+func (d *digits) round(mode RoundingMode, n int) {
if n >= len(d.Digits) {
return
}
@@ -227,7 +250,7 @@ func (r RoundingMode) roundFloat(x float64) float64 {
return i
}
-func (x *Decimal) roundUp(n int) {
+func (x *digits) roundUp(n int) {
if n < 0 || n >= len(x.Digits) {
return // nothing to do
}
@@ -248,7 +271,7 @@ func (x *Decimal) roundUp(n int) {
// x already trimmed
}
-func (x *Decimal) roundDown(n int) {
+func (x *digits) roundDown(n int) {
if n < 0 || n >= len(x.Digits) {
return // nothing to do
}
@@ -258,7 +281,7 @@ func (x *Decimal) roundDown(n int) {
// trim cuts off any trailing zeros from x's mantissa;
// they are meaningless for the value of x.
-func trim(x *Decimal) {
+func trim(x *digits) {
i := len(x.Digits)
for i > 0 && x.Digits[i-1] == 0 {
i--
@@ -272,7 +295,7 @@ func trim(x *Decimal) {
// A Converter converts a number into decimals according to the given rounding
// criteria.
type Converter interface {
- Convert(d *Decimal, r *RoundingContext)
+ Convert(d *Decimal, r RoundingContext)
}
const (
@@ -282,7 +305,7 @@ const (
// Convert converts the given number to the decimal representation using the
// supplied RoundingContext.
-func (d *Decimal) Convert(r *RoundingContext, number interface{}) {
+func (d *Decimal) Convert(r RoundingContext, number interface{}) {
switch f := number.(type) {
case Converter:
d.clear()
@@ -312,6 +335,8 @@ func (d *Decimal) Convert(r *RoundingContext, number interface{}) {
case uint64:
d.ConvertInt(r, unsigned, f)
+ default:
+ d.NaN = true
// TODO:
// case string: if produced by strconv, allows for easy arbitrary pos.
// case reflect.Value:
@@ -324,7 +349,7 @@ func (d *Decimal) Convert(r *RoundingContext, number interface{}) {
}
// ConvertInt converts an integer to decimals.
-func (d *Decimal) ConvertInt(r *RoundingContext, signed bool, x uint64) {
+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 {
@@ -344,12 +369,30 @@ func (d *Decimal) ConvertInt(r *RoundingContext, signed bool, x uint64) {
}
// ConvertFloat converts a floating point number to decimals.
-func (d *Decimal) ConvertFloat(r *RoundingContext, x float64, size int) {
+func (d *Decimal) ConvertFloat(r RoundingContext, x float64, size int) {
d.clear()
if math.IsNaN(x) {
d.NaN = true
return
}
+ // Simple case: decimal notation
+ if r.Increment > 0 {
+ scale := int(r.IncrementScale)
+ mult := 1.0
+ if scale > len(scales) {
+ mult = math.Pow(10, float64(scale))
+ } else {
+ mult = scales[scale]
+ }
+ // We multiply x instead of dividing inc as it gives less rounding
+ // issues.
+ x *= mult
+ x /= float64(r.Increment)
+ x = r.Mode.roundFloat(x)
+ x *= float64(r.Increment)
+ x /= mult
+ }
+
abs := x
if x < 0 {
d.Neg = true
@@ -359,63 +402,59 @@ func (d *Decimal) ConvertFloat(r *RoundingContext, x float64, size int) {
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.
+ // By default we get the exact decimal representation.
+ verb := byte('g')
+ prec := -1
+ // Determine rounding, if possible. As the strconv API does not return the
+ // rounding accuracy (exact/rounded up|down), we can only round using
+ // ToNearestEven.
// 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)
+ //
+ // TODO: At this point strconv's rounding is imprecise to the point that it
+ // is not useable for this purpose.
+ // See https://github.com/golang/go/issues/21714
+ // if r.Mode == ToNearestEven {
+ // if n := r.RoundSignificantDigits(); n >= 0 {
+ // prec = n
+ // } else if n = r.RoundFractionDigits(); n >= 0 {
+ // prec = n
+ // verb = 'f'
+ // }
+ // }
+
+ b := strconv.AppendFloat(d.Digits[:0], abs, verb, prec, size)
i := 0
k := 0
- // No need to check i < len(b) as we always have an 'e'.
- for {
+ beforeDot := 1
+ for i < len(b) {
if c := b[i]; '0' <= c && c <= '9' {
b[k] = c - '0'
k++
- } else if c != '.' {
+ d.Exp += int32(beforeDot)
+ } else if c == '.' {
+ beforeDot = 0
+ d.Exp = int32(k)
+ } else {
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
+ if i != len(b) {
+ i += len("e")
+ pSign := i
+ exp := 0
+ for i++; i < len(b); i++ {
+ exp *= 10
+ exp += int(b[i] - '0')
+ }
+ if b[pSign] == '-' {
+ exp = -exp
+ }
+ d.Exp = int32(exp) + 1
}
- d.Exp = int32(exp) + 1
}
func (d *Decimal) fillIntDigits(x uint64) {
diff --git a/vendor/golang.org/x/text/internal/number/decimal_test.go b/vendor/golang.org/x/text/internal/number/decimal_test.go
index 5c8170049..04aa8b2c8 100644
--- a/vendor/golang.org/x/text/internal/number/decimal_test.go
+++ b/vendor/golang.org/x/text/internal/number/decimal_test.go
@@ -22,6 +22,15 @@ func mkfloat(num string) float64 {
// digits are shifted. Numbers may have an additional exponent or be the special
// value NaN, Inf, or -Inf.
func mkdec(num string) (d Decimal) {
+ var r RoundingContext
+ d.Convert(r, dec(num))
+ return
+}
+
+type dec string
+
+func (s dec) Convert(d *Decimal, _ RoundingContext) {
+ num := string(s)
if num[0] == '-' {
d.Neg = true
num = num[1:]
@@ -52,7 +61,7 @@ func mkdec(num string) (d Decimal) {
for i := range d.Digits {
d.Digits[i] -= '0'
}
- return d.normalize()
+ *d = d.normalize()
}
func byteNum(s string) []byte {
@@ -77,11 +86,11 @@ func TestDecimalString(t *testing.T) {
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"},
+ {Decimal{digits: digits{Digits: nil, Exp: 1000}}, "0"}, // exponent of 1000 is ignored
+ {Decimal{digits: digits{Digits: byteNum("12345"), Exp: 0}}, "0.12345"},
+ {Decimal{digits: digits{Digits: byteNum("12345"), Exp: -3}}, "0.00012345"},
+ {Decimal{digits: digits{Digits: byteNum("12345"), Exp: +3}}, "123.45"},
+ {Decimal{digits: digits{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)
@@ -232,16 +241,28 @@ func TestRounding(t *testing.T) {
}
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}
+ scale2 := RoundingContext{}
+ scale2.SetScale(2)
+ scale2away := RoundingContext{Mode: AwayFromZero}
+ scale2away.SetScale(2)
+ inc0_05 := RoundingContext{Increment: 5, IncrementScale: 2}
+ inc0_05.SetScale(2)
+ inc50 := RoundingContext{Increment: 50}
+ prec3 := RoundingContext{}
+ prec3.SetPrecision(3)
+ roundShift := RoundingContext{DigitShift: 2, MaxFractionDigits: 2}
testCases := []struct {
x interface{}
- rc *RoundingContext
+ rc RoundingContext
out string
}{
+ // TODO: uncommented tests can be restored when convert does its own
+ // rounding.
+ // {-0.001, scale2, "-0.00"}, // not normalized
+ // {0.1234, prec3, "0.123"},
+ // {1234.0, prec3, "1230"},
+ // {1.2345e10, prec3, "12300000000"},
+
{int8(-34), scale2, "-34"},
{int16(-234), scale2, "-234"},
{int32(-234), scale2, "-234"},
@@ -252,25 +273,25 @@ func TestConvert(t *testing.T) {
{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"},
+ {-1e9, scale2, "-1000000000"},
+ {0.234, scale2away, "0.234"}, // rounding postponed as not ToNearestEven
{0.03, inc0_05, "0.05"},
{0.025, inc0_05, "0"},
- {0.075, inc0_05, "0.10"},
+ {0.075, inc0_05, "0.1"},
{325, inc50, "300"},
{375, inc50, "400"},
+ // Here the scale is 2, but the digits get shifted left. As we use
+ // AppendFloat to do the rounding an exta 0 gets added.
+ {0.123, roundShift, "0.123"},
+
{converter(3), scale2, "100"},
{math.Inf(1), inc50, "Inf"},
{math.Inf(-1), inc50, "-Inf"},
{math.NaN(), inc50, "NaN"},
+ {"clearly not a number", scale2, "NaN"},
}
for _, tc := range testCases {
var d Decimal
@@ -285,7 +306,7 @@ func TestConvert(t *testing.T) {
type converter int
-func (c converter) Convert(d *Decimal, r *RoundingContext) {
+func (c converter) Convert(d *Decimal, r RoundingContext) {
d.Digits = append(d.Digits, 1, 0, 0)
d.Exp = 3
}
diff --git a/vendor/golang.org/x/text/internal/number/format.go b/vendor/golang.org/x/text/internal/number/format.go
index 533a85a28..910bdeb02 100755
--- a/vendor/golang.org/x/text/internal/number/format.go
+++ b/vendor/golang.org/x/text/internal/number/format.go
@@ -16,6 +16,13 @@ import (
// - allow user-defined superscript notation (such as <sup>4</sup>)
// - same for non-breaking spaces, like &nbsp;
+// A VisibleDigits computes digits, comma placement and trailing zeros as they
+// will be shown to the user.
+type VisibleDigits interface {
+ Digits(buf []byte, t language.Tag, scale int) Digits
+ // TODO: Do we also need to add the verb or pass a format.State?
+}
+
// Formatting proceeds along the following lines:
// 0) Compose rounding information from format and context.
// 1) Convert a number into a Decimal.
@@ -28,7 +35,6 @@ import (
type Formatter struct {
Pattern
Info
- RoundingContext
}
func (f *Formatter) init(t language.Tag, index []uint8) {
@@ -57,12 +63,16 @@ func (f *Formatter) InitDecimal(t language.Tag) {
// given language.
func (f *Formatter) InitScientific(t language.Tag) {
f.init(t, tagToScientific)
+ f.Pattern.MinFractionDigits = 0
+ f.Pattern.MaxFractionDigits = -1
}
// InitEngineering initializes a Formatter using the default Pattern for the
// given language.
func (f *Formatter) InitEngineering(t language.Tag) {
f.init(t, tagToScientific)
+ f.Pattern.MinFractionDigits = 0
+ f.Pattern.MaxFractionDigits = -1
f.Pattern.MaxIntegerDigits = 3
f.Pattern.MinIntegerDigits = 1
}
@@ -82,17 +92,29 @@ func (f *Formatter) InitPerMille(t language.Tag) {
func (f *Formatter) Append(dst []byte, x interface{}) []byte {
var d Decimal
- d.Convert(&f.RoundingContext, x)
- return f.Format(dst, &d)
+ r := f.RoundingContext
+ d.Convert(r, x)
+ return f.Render(dst, FormatDigits(&d, r))
+}
+
+func FormatDigits(d *Decimal, r RoundingContext) Digits {
+ if r.isScientific() {
+ return scientificVisibleDigits(r, d)
+ }
+ return decimalVisibleDigits(r, d)
}
func (f *Formatter) Format(dst []byte, d *Decimal) []byte {
+ return f.Render(dst, FormatDigits(d, f.RoundingContext))
+}
+
+func (f *Formatter) Render(dst []byte, d Digits) []byte {
var result []byte
var postPrefix, preSuffix int
- if f.MinExponentDigits > 0 {
- result, postPrefix, preSuffix = appendScientific(dst, f, d)
+ if d.IsScientific {
+ result, postPrefix, preSuffix = appendScientific(dst, f, &d)
} else {
- result, postPrefix, preSuffix = appendDecimal(dst, f, d)
+ result, postPrefix, preSuffix = appendDecimal(dst, f, &d)
}
if f.PadRune == 0 {
return result
@@ -131,80 +153,79 @@ func (f *Formatter) Format(dst []byte, d *Decimal) []byte {
return result
}
-// TODO: just return visible digits.
-func decimalVisibleDigits(f *Formatter, d *Decimal) Decimal {
+// decimalVisibleDigits converts d according to the RoundingContext. Note that
+// the exponent may change as a result of this operation.
+func decimalVisibleDigits(r RoundingContext, d *Decimal) Digits {
if d.NaN || d.Inf {
- return *d
+ return Digits{digits: digits{Neg: d.Neg, NaN: d.NaN, Inf: d.Inf}}
}
- n := d.normalize()
- if maxSig := int(f.MaxSignificantDigits); maxSig > 0 {
- // TODO: really round to zero?
- n.round(ToZero, maxSig)
- }
- digits := n.Digits
+ n := Digits{digits: d.normalize().digits}
+
exp := n.Exp
- exp += int32(f.Pattern.DigitShift)
+ exp += int32(r.DigitShift)
// Cap integer digits. Remove *most-significant* digits.
- if f.MaxIntegerDigits > 0 {
- if p := int(exp) - int(f.MaxIntegerDigits); p > 0 {
- if p > len(digits) {
- p = len(digits)
+ if r.MaxIntegerDigits > 0 {
+ if p := int(exp) - int(r.MaxIntegerDigits); p > 0 {
+ if p > len(n.Digits) {
+ p = len(n.Digits)
}
- if digits = digits[p:]; len(digits) == 0 {
+ if n.Digits = n.Digits[p:]; len(n.Digits) == 0 {
exp = 0
} else {
exp -= int32(p)
}
// Strip leading zeros.
- for len(digits) > 0 && digits[0] == 0 {
- digits = digits[1:]
+ for len(n.Digits) > 0 && n.Digits[0] == 0 {
+ n.Digits = n.Digits[1:]
exp--
}
}
}
- // Rounding usually is done by convert, but we don't rely on it.
- numFrac := len(digits) - int(exp)
- if f.MaxSignificantDigits == 0 && int(f.MaxFractionDigits) < numFrac {
- p := int(exp) + int(f.MaxFractionDigits)
- if p <= 0 {
+ // Rounding if not already done by Convert.
+ p := len(n.Digits)
+ if maxSig := int(r.MaxSignificantDigits); maxSig > 0 {
+ p = maxSig
+ }
+ if maxFrac := int(r.MaxFractionDigits); maxFrac >= 0 {
+ if cap := int(exp) + maxFrac; cap < p {
+ p = int(exp) + maxFrac
+ }
+ if p < 0 {
p = 0
- } else if p >= len(digits) {
- p = len(digits)
}
- digits = digits[:p] // TODO: round
}
+ n.round(r.Mode, p)
// set End (trailing zeros)
- n.End = int32(len(digits))
- if len(digits) == 0 {
- if f.MinFractionDigits > 0 {
- n.End = int32(f.MinFractionDigits)
+ n.End = int32(len(n.Digits))
+ if n.End == 0 {
+ exp = 0
+ if r.MinFractionDigits > 0 {
+ n.End = int32(r.MinFractionDigits)
}
- if p := int32(f.MinSignificantDigits) - 1; p > n.End {
+ if p := int32(r.MinSignificantDigits) - 1; p > n.End {
n.End = p
}
} else {
- if end := exp + int32(f.MinFractionDigits); end > n.End {
+ if end := exp + int32(r.MinFractionDigits); end > n.End {
n.End = end
}
- if n.End < int32(f.MinSignificantDigits) {
- n.End = int32(f.MinSignificantDigits)
+ if n.End < int32(r.MinSignificantDigits) {
+ n.End = int32(r.MinSignificantDigits)
}
}
- n.Digits = digits
n.Exp = exp
return n
}
// appendDecimal appends a formatted number to dst. It returns two possible
// insertion points for padding.
-func appendDecimal(dst []byte, f *Formatter, d *Decimal) (b []byte, postPre, preSuf int) {
- if dst, ok := f.renderSpecial(dst, d); ok {
+func appendDecimal(dst []byte, f *Formatter, n *Digits) (b []byte, postPre, preSuf int) {
+ if dst, ok := f.renderSpecial(dst, n); ok {
return dst, 0, len(dst)
}
- n := decimalVisibleDigits(f, d)
digits := n.Digits
exp := n.Exp
@@ -224,7 +245,7 @@ func appendDecimal(dst []byte, f *Formatter, d *Decimal) (b []byte, postPre, pre
fracDigits = digits
}
- neg := d.Neg
+ neg := n.Neg
affix, suffix := f.getAffixes(neg)
dst = appendAffix(dst, f, affix, neg)
savedLen := len(dst)
@@ -257,7 +278,7 @@ func appendDecimal(dst []byte, f *Formatter, d *Decimal) (b []byte, postPre, pre
if numFrac > 0 || f.Flags&AlwaysDecimalSeparator != 0 {
dst = append(dst, f.Symbol(SymDecimal)...)
}
- // Add leading zeros
+ // Add trailing zeros
i = 0
for n := -int(n.Exp); i < n; i++ {
dst = f.AppendDigit(dst, 0)
@@ -272,69 +293,65 @@ func appendDecimal(dst []byte, f *Formatter, d *Decimal) (b []byte, postPre, pre
return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
}
-func scientificVisibleDigits(f *Formatter, d *Decimal) Decimal {
+func scientificVisibleDigits(r RoundingContext, d *Decimal) Digits {
if d.NaN || d.Inf {
- return *d
+ return Digits{digits: digits{Neg: d.Neg, NaN: d.NaN, Inf: d.Inf}}
+ }
+ n := Digits{digits: d.normalize().digits, IsScientific: true}
+
+ // Normalize to have at least one digit. This simplifies engineering
+ // notation.
+ if len(n.Digits) == 0 {
+ n.Digits = append(n.Digits, 0)
+ n.Exp = 1
}
- n := d.normalize()
// Significant digits are transformed by the parser for scientific notation
// and do not need to be handled here.
- maxInt, numInt := int(f.MaxIntegerDigits), int(f.MinIntegerDigits)
+ maxInt, numInt := int(r.MaxIntegerDigits), int(r.MinIntegerDigits)
if numInt == 0 {
numInt = 1
}
- maxSig := int(f.MaxFractionDigits) + numInt
- minSig := int(f.MinFractionDigits) + numInt
-
- if maxSig > 0 {
- // TODO: really round to zero?
- 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 {
+ 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
+ d := int(n.Exp-1) % maxInt
if d < 0 {
d += maxInt
}
- exp -= int32(d)
numInt += d
- } else {
- exp -= int32(numInt)
}
+ p := len(n.Digits)
+ if maxSig := int(r.MaxSignificantDigits); maxSig > 0 {
+ p = maxSig
+ }
+ if maxFrac := int(r.MaxFractionDigits); maxFrac >= 0 && numInt+maxFrac < p {
+ p = numInt + maxFrac
+ }
+ n.round(r.Mode, p)
+
n.Comma = uint8(numInt)
- n.End = int32(len(digits))
- if n.End < int32(minSig) {
- n.End = int32(minSig)
+ n.End = int32(len(n.Digits))
+ if minSig := int32(r.MinFractionDigits) + int32(numInt); n.End < minSig {
+ n.End = minSig
}
- n.Digits = digits
- n.Exp = exp
return n
}
// 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 {
+func appendScientific(dst []byte, f *Formatter, n *Digits) (b []byte, postPre, preSuf int) {
+ if dst, ok := f.renderSpecial(dst, n); ok {
return dst, 0, 0
}
- // n := d.normalize()
- n := scientificVisibleDigits(f, d)
digits := n.Digits
- exp := n.Exp
numInt := int(n.Comma)
numFrac := int(n.End) - int(n.Comma)
@@ -345,7 +362,7 @@ func appendScientific(dst []byte, f *Formatter, d *Decimal) (b []byte, postPre,
} else {
intDigits = digits
}
- neg := d.Neg
+ neg := n.Neg
affix, suffix := f.getAffixes(neg)
dst = appendAffix(dst, f, affix, neg)
savedLen := len(dst)
@@ -379,6 +396,7 @@ func appendScientific(dst []byte, f *Formatter, d *Decimal) (b []byte, postPre,
buf := [12]byte{}
// TODO: use exponential if superscripting is not available (no Latin
// numbers or no tags) and use exponential in all other cases.
+ exp := n.Exp - int32(n.Comma)
exponential := f.Symbol(SymExponential)
if exponential == "E" {
dst = append(dst, "\u202f"...) // NARROW NO-BREAK SPACE
@@ -463,7 +481,7 @@ func (f *Formatter) getAffixes(neg bool) (affix, suffix string) {
return affix, suffix
}
-func (f *Formatter) renderSpecial(dst []byte, d *Decimal) (b []byte, ok bool) {
+func (f *Formatter) renderSpecial(dst []byte, d *Digits) (b []byte, ok bool) {
if d.NaN {
return fmtNaN(dst, f), true
}
@@ -477,7 +495,7 @@ func fmtNaN(dst []byte, f *Formatter) []byte {
return append(dst, f.Symbol(SymNan)...)
}
-func fmtInfinite(dst []byte, f *Formatter, d *Decimal) []byte {
+func fmtInfinite(dst []byte, f *Formatter, d *Digits) []byte {
affix, suffix := f.getAffixes(d.Neg)
dst = appendAffix(dst, f, affix, d.Neg)
dst = append(dst, f.Symbol(SymInfinity)...)
diff --git a/vendor/golang.org/x/text/internal/number/format_test.go b/vendor/golang.org/x/text/internal/number/format_test.go
index 4c47bc568..01a089430 100755
--- a/vendor/golang.org/x/text/internal/number/format_test.go
+++ b/vendor/golang.org/x/text/internal/number/format_test.go
@@ -112,7 +112,7 @@ func TestAppendDecimal(t *testing.T) {
test: pairs{
"0": "0",
"1234.5678": "1234.5678",
- "0.123456789": "0.123456",
+ "0.123456789": "0.123457",
"NaN": "NaN",
"Inf": "∞",
},
@@ -142,7 +142,7 @@ func TestAppendDecimal(t *testing.T) {
pattern: "#,##0.###",
test: pairs{
"0": "0",
- "1234.5678": "1,234.567",
+ "1234.5678": "1,234.568",
"0.123456789": "0.123",
},
}, {
@@ -157,7 +157,7 @@ func TestAppendDecimal(t *testing.T) {
test: pairs{
"0": "0,00,000",
"123456789012": "1,23,45,67,89,012",
- "12.3456789": "0,00,012.345",
+ "12.3456789": "0,00,012.346",
"0.123456789": "0,00,000.123",
},
@@ -193,7 +193,9 @@ func TestAppendDecimal(t *testing.T) {
}, {
pattern: "#,max_int=2",
pat: &Pattern{
- MaxIntegerDigits: 2,
+ RoundingContext: RoundingContext{
+ MaxIntegerDigits: 2,
+ },
},
test: pairs{
"2017": "17",
@@ -201,8 +203,10 @@ func TestAppendDecimal(t *testing.T) {
}, {
pattern: "0,max_int=2",
pat: &Pattern{
- MaxIntegerDigits: 2,
- MinIntegerDigits: 1,
+ RoundingContext: RoundingContext{
+ MaxIntegerDigits: 2,
+ MinIntegerDigits: 1,
+ },
},
test: pairs{
"2000": "0",
@@ -212,8 +216,10 @@ func TestAppendDecimal(t *testing.T) {
}, {
pattern: "00,max_int=2",
pat: &Pattern{
- MaxIntegerDigits: 2,
- MinIntegerDigits: 2,
+ RoundingContext: RoundingContext{
+ MaxIntegerDigits: 2,
+ MinIntegerDigits: 2,
+ },
},
test: pairs{
"2000": "00",
@@ -223,8 +229,10 @@ func TestAppendDecimal(t *testing.T) {
}, {
pattern: "@@@@,max_int=2",
pat: &Pattern{
- MaxIntegerDigits: 2,
- MinSignificantDigits: 4,
+ RoundingContext: RoundingContext{
+ MaxIntegerDigits: 2,
+ MinSignificantDigits: 4,
+ },
},
test: pairs{
"2017": "17.00",
@@ -237,7 +245,7 @@ func TestAppendDecimal(t *testing.T) {
pattern: "@@##",
test: pairs{
"1": "1.0",
- "0.1": "0.10",
+ "0.1": "0.10", // leading zero does not count as significant digit
"123": "123",
"1234": "1234",
"12345": "12340",
@@ -281,22 +289,25 @@ func TestAppendDecimal(t *testing.T) {
pattern: "##0E00",
test: pairs{
"100": "100\u202f×\u202f10⁰⁰",
- "12345": "10\u202f×\u202f10⁰³",
- "123.456": "100\u202f×\u202f10⁰⁰",
+ "12345": "12\u202f×\u202f10⁰³",
+ "123.456": "123\u202f×\u202f10⁰⁰",
},
}, {
pattern: "##0.###E00",
test: pairs{
- "100": "100\u202f×\u202f10⁰⁰",
- "12345": "12.34\u202f×\u202f10⁰³",
- "123.456": "123.4\u202f×\u202f10⁰⁰",
+ "100": "100\u202f×\u202f10⁰⁰",
+ "12345": "12.345\u202f×\u202f10⁰³",
+ "123456": "123.456\u202f×\u202f10⁰³",
+ "123.456": "123.456\u202f×\u202f10⁰⁰",
+ "123.4567": "123.457\u202f×\u202f10⁰⁰",
},
}, {
pattern: "##0.000E00",
test: pairs{
- "100": "100.0\u202f×\u202f10⁰⁰",
- "12345": "12.34\u202f×\u202f10⁰³",
- "123.456": "123.4\u202f×\u202f10⁰⁰",
+ "100": "100.000\u202f×\u202f10⁰⁰",
+ "12345": "12.345\u202f×\u202f10⁰³",
+ "123.456": "123.456\u202f×\u202f10⁰⁰",
+ "12.3456": "12.346\u202f×\u202f10⁰⁰",
},
}, {
pattern: "@@E0",
@@ -441,11 +452,12 @@ func TestAppendDecimal(t *testing.T) {
}
var f Formatter
f.InitPattern(language.English, pat)
- for dec, want := range tc.test {
+ for num, 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)
+ t.Run(tc.pattern+"/"+num, func(t *testing.T) {
+ var d Decimal
+ d.Convert(f.RoundingContext, dec(num))
+ buf = f.Format(buf[:0], &d)
if got := string(buf); got != want {
t.Errorf("\n got %[1]q (%[1]s)\nwant %[2]q (%[2]s)", got, want)
}
@@ -470,7 +482,8 @@ func TestLocales(t *testing.T) {
t.Run(fmt.Sprint(tc.tag, "/", tc.num), func(t *testing.T) {
var f Formatter
f.InitDecimal(tc.tag)
- d := mkdec(tc.num)
+ var d Decimal
+ d.Convert(f.RoundingContext, dec(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)
@@ -488,7 +501,8 @@ func TestFormatters(t *testing.T) {
}{
{f.InitDecimal, "123456.78", "123,456.78"},
{f.InitScientific, "123456.78", "1.23\u202f×\u202f10⁵"},
- {f.InitEngineering, "123456.78", "123\u202f×\u202f10³"},
+ {f.InitEngineering, "123456.78", "123.46\u202f×\u202f10³"},
+ {f.InitEngineering, "1234", "1.23\u202f×\u202f10³"},
{f.InitPercent, "0.1234", "12.34%"},
{f.InitPerMille, "0.1234", "123.40‰"},
@@ -496,9 +510,9 @@ func TestFormatters(t *testing.T) {
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)
+ f.SetScale(2)
+ var d Decimal
+ d.Convert(f.RoundingContext, dec(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)
diff --git a/vendor/golang.org/x/text/internal/number/pattern.go b/vendor/golang.org/x/text/internal/number/pattern.go
index ef7f087fe..b95ca40e8 100644
--- a/vendor/golang.org/x/text/internal/number/pattern.go
+++ b/vendor/golang.org/x/text/internal/number/pattern.go
@@ -39,31 +39,84 @@ import (
//
// This type is only intended for internal use.
type Pattern struct {
- // TODO: this struct can be packed a lot better than it is now. Should be
- // possible to make it 32 bytes.
-
- Affix string // includes prefix and suffix. First byte is prefix length.
- Offset uint16 // Offset into Affix for prefix and suffix
- NegOffset uint16 // Offset into Affix for negative prefix and suffix or 0.
+ RoundingContext
+ Affix string // includes prefix and suffix. First byte is prefix length.
+ Offset uint16 // Offset into Affix for prefix and suffix
+ NegOffset uint16 // Offset into Affix for negative prefix and suffix or 0.
+ PadRune rune
FormatWidth uint16
- RoundIncrement uint32 // Use Min*Digits to determine scale
- PadRune rune
- DigitShift uint8 // Number of decimals to shift. Used for % and ‰.
-
GroupingSize [2]uint8
Flags PatternFlag
+}
+
+// A RoundingContext indicates how a number should be converted to digits.
+// It contains all information needed to determine the "visible digits" as
+// required by the pluralization rules.
+type RoundingContext struct {
+ // TODO: unify these two fields so that there is a more unambiguous meaning
+ // of how precision is handled.
+ MaxSignificantDigits int16 // -1 is unlimited
+ MaxFractionDigits int16 // -1 is unlimited
+
+ Increment uint32
+ IncrementScale uint8 // May differ from printed scale.
+
+ Mode RoundingMode
+
+ DigitShift uint8 // Number of decimals to shift. Used for % and ‰.
// Number of digits.
- // TODO: consider using uint32
- MinIntegerDigits uint8
+ MinIntegerDigits uint8
+
MaxIntegerDigits uint8
MinFractionDigits uint8
- MaxFractionDigits uint8
MinSignificantDigits uint8
- MaxSignificantDigits uint8
- MinExponentDigits uint8
+
+ MinExponentDigits uint8
+}
+
+// RoundSignificantDigits returns the number of significant digits an
+// implementation of Convert may round to or n < 0 if there is no maximum or
+// a maximum is not recommended.
+func (r *RoundingContext) RoundSignificantDigits() (n int) {
+ if r.MaxFractionDigits == 0 && r.MaxSignificantDigits > 0 {
+ return int(r.MaxSignificantDigits)
+ } else if r.isScientific() && r.MaxIntegerDigits == 1 {
+ if r.MaxSignificantDigits == 0 ||
+ int(r.MaxFractionDigits+1) == int(r.MaxSignificantDigits) {
+ // Note: don't add DigitShift: it is only used for decimals.
+ return int(r.MaxFractionDigits) + 1
+ }
+ }
+ return -1
+}
+
+// RoundFractionDigits returns the number of fraction digits an implementation
+// of Convert may round to or n < 0 if there is no maximum or a maximum is not
+// recommended.
+func (r *RoundingContext) RoundFractionDigits() (n int) {
+ if r.MinExponentDigits == 0 &&
+ r.MaxSignificantDigits == 0 &&
+ r.MaxFractionDigits >= 0 {
+ return int(r.MaxFractionDigits) + int(r.DigitShift)
+ }
+ return -1
+}
+
+// SetScale fixes the RoundingContext to a fixed number of fraction digits.
+func (r *RoundingContext) SetScale(scale int) {
+ r.MinFractionDigits = uint8(scale)
+ r.MaxFractionDigits = int16(scale)
+}
+
+func (r *RoundingContext) SetPrecision(prec int) {
+ r.MaxSignificantDigits = int16(prec)
+}
+
+func (r *RoundingContext) isScientific() bool {
+ return r.MinExponentDigits > 0
}
func (f *Pattern) needsSep(pos int) bool {
@@ -177,6 +230,9 @@ func ParsePattern(s string) (f *Pattern, err error) {
} else {
p.Affix = affix
}
+ if p.Increment == 0 {
+ p.IncrementScale = 0
+ }
return p.Pattern, nil
}
@@ -302,6 +358,7 @@ func (p *parser) number(r rune) state {
case '@':
p.groupingCount++
p.leadingSharps = 0
+ p.MaxFractionDigits = -1
return p.sigDigits(r)
case ',':
if p.leadingSharps == 0 { // no leading commas
@@ -339,7 +396,7 @@ func (p *parser) integer(r rune) state {
p.updateGrouping()
return next
}
- p.RoundIncrement = p.RoundIncrement*10 + uint32(r-'0')
+ p.Increment = p.Increment*10 + uint32(r-'0')
p.groupingCount++
p.MinIntegerDigits++
return p.integer
@@ -389,7 +446,8 @@ func (p *parser) normalizeSigDigitsWithExponent() state {
func (p *parser) fraction(r rune) state {
switch r {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
- p.RoundIncrement = p.RoundIncrement*10 + uint32(r-'0')
+ p.Increment = p.Increment*10 + uint32(r-'0')
+ p.IncrementScale++
p.MinFractionDigits++
p.MaxFractionDigits++
case '#':
diff --git a/vendor/golang.org/x/text/internal/number/pattern_test.go b/vendor/golang.org/x/text/internal/number/pattern_test.go
index 97ff64d55..a7517d004 100644
--- a/vendor/golang.org/x/text/internal/number/pattern_test.go
+++ b/vendor/golang.org/x/text/internal/number/pattern_test.go
@@ -22,96 +22,122 @@ var testCases = []struct {
}, {
"0",
&Pattern{
- FormatWidth: 1,
- MinIntegerDigits: 1,
+ FormatWidth: 1,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ },
},
}, {
"+0",
&Pattern{
- Affix: "\x01+\x00",
- FormatWidth: 2,
- MinIntegerDigits: 1,
+ Affix: "\x01+\x00",
+ FormatWidth: 2,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ },
},
}, {
"0+",
&Pattern{
- Affix: "\x00\x01+",
- FormatWidth: 2,
- MinIntegerDigits: 1,
+ Affix: "\x00\x01+",
+ FormatWidth: 2,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ },
},
}, {
"0000",
&Pattern{
- FormatWidth: 4,
- MinIntegerDigits: 4,
+ FormatWidth: 4,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 4,
+ },
},
}, {
".#",
&Pattern{
- FormatWidth: 2,
- MaxFractionDigits: 1,
+ FormatWidth: 2,
+ RoundingContext: RoundingContext{
+ MaxFractionDigits: 1,
+ },
},
}, {
"#0.###",
&Pattern{
- FormatWidth: 6,
- MinIntegerDigits: 1,
- MaxFractionDigits: 3,
+ FormatWidth: 6,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ MaxFractionDigits: 3,
+ },
},
}, {
"#0.######",
&Pattern{
- FormatWidth: 9,
- MinIntegerDigits: 1,
- MaxFractionDigits: 6,
+ FormatWidth: 9,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ MaxFractionDigits: 6,
+ },
},
}, {
"#,0",
&Pattern{
- FormatWidth: 3,
- GroupingSize: [2]uint8{1, 0},
- MinIntegerDigits: 1,
+ FormatWidth: 3,
+ GroupingSize: [2]uint8{1, 0},
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ },
},
}, {
"#,0.00",
&Pattern{
- FormatWidth: 6,
- GroupingSize: [2]uint8{1, 0},
- MinIntegerDigits: 1,
- MinFractionDigits: 2,
- MaxFractionDigits: 2,
+ FormatWidth: 6,
+ GroupingSize: [2]uint8{1, 0},
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ MinFractionDigits: 2,
+ MaxFractionDigits: 2,
+ },
},
}, {
"#,##0.###",
&Pattern{
- FormatWidth: 9,
- GroupingSize: [2]uint8{3, 0},
- MinIntegerDigits: 1,
- MaxFractionDigits: 3,
+ FormatWidth: 9,
+ GroupingSize: [2]uint8{3, 0},
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ MaxFractionDigits: 3,
+ },
},
}, {
"#,##,##0.###",
&Pattern{
- FormatWidth: 12,
- GroupingSize: [2]uint8{3, 2},
- MinIntegerDigits: 1,
- MaxFractionDigits: 3,
+ FormatWidth: 12,
+ GroupingSize: [2]uint8{3, 2},
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ MaxFractionDigits: 3,
+ },
},
}, {
// Ignore additional separators.
"#,####,##,##0.###",
&Pattern{
- FormatWidth: 17,
- GroupingSize: [2]uint8{3, 2},
- MinIntegerDigits: 1,
- MaxFractionDigits: 3,
+ FormatWidth: 17,
+ GroupingSize: [2]uint8{3, 2},
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ MaxFractionDigits: 3,
+ },
},
}, {
"#E0",
&Pattern{
- FormatWidth: 3,
- MaxIntegerDigits: 1,
- MinExponentDigits: 1,
+ FormatWidth: 3,
+ RoundingContext: RoundingContext{
+ MaxIntegerDigits: 1,
+ MinExponentDigits: 1,
+ },
},
}, {
// At least one exponent digit is required. As long as this is true, one can
@@ -121,30 +147,47 @@ var testCases = []struct {
}, {
"0E0",
&Pattern{
- FormatWidth: 3,
- MinIntegerDigits: 1,
- MinExponentDigits: 1,
+ FormatWidth: 3,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ MinExponentDigits: 1,
+ },
+ },
+}, {
+ "##0.###E00",
+ &Pattern{
+ FormatWidth: 10,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ MaxIntegerDigits: 3,
+ MaxFractionDigits: 3,
+ MinExponentDigits: 2,
+ },
},
}, {
"##00.0#E0",
&Pattern{
- FormatWidth: 9,
- MinIntegerDigits: 2,
- MaxIntegerDigits: 4,
- MinFractionDigits: 1,
- MaxFractionDigits: 2,
- MinExponentDigits: 1,
+ FormatWidth: 9,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 2,
+ MaxIntegerDigits: 4,
+ MinFractionDigits: 1,
+ MaxFractionDigits: 2,
+ MinExponentDigits: 1,
+ },
},
}, {
"#00.0E+0",
&Pattern{
- FormatWidth: 8,
- Flags: AlwaysExpSign,
- MinIntegerDigits: 2,
- MaxIntegerDigits: 3,
- MinFractionDigits: 1,
- MaxFractionDigits: 1,
- MinExponentDigits: 1,
+ FormatWidth: 8,
+ Flags: AlwaysExpSign,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 2,
+ MaxIntegerDigits: 3,
+ MinFractionDigits: 1,
+ MaxFractionDigits: 1,
+ MinExponentDigits: 1,
+ },
},
}, {
"0.0E++0",
@@ -156,45 +199,58 @@ var testCases = []struct {
// significant digits
"@",
&Pattern{
- FormatWidth: 1,
- MinSignificantDigits: 1,
- MaxSignificantDigits: 1,
+ FormatWidth: 1,
+ RoundingContext: RoundingContext{
+ MinSignificantDigits: 1,
+ MaxSignificantDigits: 1,
+ MaxFractionDigits: -1,
+ },
},
}, {
// significant digits
"@@@@",
&Pattern{
- FormatWidth: 4,
- MinSignificantDigits: 4,
- MaxSignificantDigits: 4,
+ FormatWidth: 4,
+ RoundingContext: RoundingContext{
+ MinSignificantDigits: 4,
+ MaxSignificantDigits: 4,
+ MaxFractionDigits: -1,
+ },
},
}, {
"@###",
&Pattern{
- FormatWidth: 4,
- MinSignificantDigits: 1,
- MaxSignificantDigits: 4,
+ FormatWidth: 4,
+ RoundingContext: RoundingContext{
+ MinSignificantDigits: 1,
+ MaxSignificantDigits: 4,
+ MaxFractionDigits: -1,
+ },
},
}, {
// Exponents in significant digits mode gets normalized.
"@@E0",
&Pattern{
- FormatWidth: 4,
- MinIntegerDigits: 1,
- MaxIntegerDigits: 1,
- MinFractionDigits: 1,
- MaxFractionDigits: 1,
- MinExponentDigits: 1,
+ FormatWidth: 4,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ MaxIntegerDigits: 1,
+ MinFractionDigits: 1,
+ MaxFractionDigits: 1,
+ MinExponentDigits: 1,
+ },
},
}, {
"@###E00",
&Pattern{
- FormatWidth: 7,
- MinIntegerDigits: 1,
- MaxIntegerDigits: 1,
- MinFractionDigits: 0,
- MaxFractionDigits: 3,
- MinExponentDigits: 2,
+ FormatWidth: 7,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ MaxIntegerDigits: 1,
+ MinFractionDigits: 0,
+ MaxFractionDigits: 3,
+ MinExponentDigits: 2,
+ },
},
}, {
// The significant digits mode does not allow fractions.
@@ -204,73 +260,89 @@ var testCases = []struct {
//alternative negative pattern
"#0.###;(#0.###)",
&Pattern{
- Affix: "\x00\x00\x01(\x01)",
- NegOffset: 2,
- FormatWidth: 6,
- MinIntegerDigits: 1,
- MaxFractionDigits: 3,
+ Affix: "\x00\x00\x01(\x01)",
+ NegOffset: 2,
+ FormatWidth: 6,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ MaxFractionDigits: 3,
+ },
},
}, {
// Rounding increment
"1.05",
&Pattern{
- RoundIncrement: 105,
- FormatWidth: 4,
- MinIntegerDigits: 1,
- MinFractionDigits: 2,
- MaxFractionDigits: 2,
+ FormatWidth: 4,
+ RoundingContext: RoundingContext{
+ Increment: 105,
+ IncrementScale: 2,
+ MinIntegerDigits: 1,
+ 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,
+ FormatWidth: 4,
+ GroupingSize: [2]uint8{2, 0},
+ RoundingContext: RoundingContext{
+ Increment: 105,
+ IncrementScale: 0,
+ MinIntegerDigits: 3,
+ MinFractionDigits: 0,
+ MaxFractionDigits: 0,
+ },
},
}, {
"0.0%",
&Pattern{
- Affix: "\x00\x01%",
- DigitShift: 2,
- FormatWidth: 4,
- MinIntegerDigits: 1,
- MinFractionDigits: 1,
- MaxFractionDigits: 1,
+ Affix: "\x00\x01%",
+ FormatWidth: 4,
+ RoundingContext: RoundingContext{
+ DigitShift: 2,
+ MinIntegerDigits: 1,
+ MinFractionDigits: 1,
+ MaxFractionDigits: 1,
+ },
},
}, {
"0.0‰",
&Pattern{
- Affix: "\x00\x03‰",
- DigitShift: 3,
- FormatWidth: 4,
- MinIntegerDigits: 1,
- MinFractionDigits: 1,
- MaxFractionDigits: 1,
+ Affix: "\x00\x03‰",
+ FormatWidth: 4,
+ RoundingContext: RoundingContext{
+ DigitShift: 3,
+ MinIntegerDigits: 1,
+ MinFractionDigits: 1,
+ MaxFractionDigits: 1,
+ },
},
}, {
"#,##0.00¤",
&Pattern{
- Affix: "\x00\x02¤",
- FormatWidth: 9,
- GroupingSize: [2]uint8{3, 0},
- MinIntegerDigits: 1,
- MinFractionDigits: 2,
- MaxFractionDigits: 2,
+ Affix: "\x00\x02¤",
+ FormatWidth: 9,
+ GroupingSize: [2]uint8{3, 0},
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 1,
+ MinFractionDigits: 2,
+ MaxFractionDigits: 2,
+ },
},
}, {
"#,##0.00 ¤;(#,##0.00 ¤)",
&Pattern{Affix: "\x00\x04\u00a0¤\x01(\x05\u00a0¤)",
- NegOffset: 6,
- DigitShift: 0,
- FormatWidth: 10,
- GroupingSize: [2]uint8{3, 0},
- MinIntegerDigits: 1,
- MinFractionDigits: 2,
- MaxFractionDigits: 2,
+ NegOffset: 6,
+ FormatWidth: 10,
+ GroupingSize: [2]uint8{3, 0},
+ RoundingContext: RoundingContext{
+ DigitShift: 0,
+ MinIntegerDigits: 1,
+ MinFractionDigits: 2,
+ MaxFractionDigits: 2,
+ },
},
}, {
// padding
@@ -321,16 +393,21 @@ var testCases = []struct {
}, {
`* #0 o''clock`,
&Pattern{Affix: "\x00\x09 o\\'clock",
- FormatWidth: 10,
- PadRune: 32,
- MinIntegerDigits: 0x1},
+ FormatWidth: 10,
+ PadRune: 32,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 0x1,
+ },
+ },
}, {
`'123'* #0'456'`,
&Pattern{Affix: "\x05'123'\x05'456'",
- FormatWidth: 8,
- PadRune: 32,
- MinIntegerDigits: 0x1,
- Flags: PadAfterPrefix},
+ FormatWidth: 8,
+ PadRune: 32,
+ RoundingContext: RoundingContext{
+ MinIntegerDigits: 0x1,
+ },
+ Flags: PadAfterPrefix},
}, {
// no duplicate padding
"*xpre#suf*x", nil,
@@ -354,8 +431,8 @@ func TestParsePattern(t *testing.T) {
}
func TestPatternSize(t *testing.T) {
- if sz := unsafe.Sizeof(Pattern{}); sz > 48 {
- t.Errorf("got %d; want <= 48", sz)
+ if sz := unsafe.Sizeof(Pattern{}); sz > 56 {
+ t.Errorf("got %d; want <= 56", sz)
}
}
diff --git a/vendor/golang.org/x/text/internal/number/tables.go b/vendor/golang.org/x/text/internal/number/tables.go
index b08acc48c..286712b17 100644
--- a/vendor/golang.org/x/text/internal/number/tables.go
+++ b/vendor/golang.org/x/text/internal/number/tables.go
@@ -846,277 +846,309 @@ var tagToPercent = []uint8{ // 754 elements
0x04, 0x04,
} // Size: 778 bytes
-var formats = []Pattern{Pattern{Affix: "",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x0,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x0,
- GroupingSize: [2]uint8{0x0,
- 0x0},
- Flags: 0x0,
+var formats = []Pattern{Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
MinIntegerDigits: 0x0,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0},
- Pattern{Affix: "",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x9,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x0,
- GroupingSize: [2]uint8{0x3,
- 0x0},
- Flags: 0x0,
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x0,
+ GroupingSize: [2]uint8{0x0,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 3,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
MinIntegerDigits: 0x1,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x3,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0},
- Pattern{Affix: "",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x3,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x0,
- GroupingSize: [2]uint8{0x0,
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x9,
+ GroupingSize: [2]uint8{0x3,
0x0},
- Flags: 0x0,
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
MinIntegerDigits: 0x0,
MaxIntegerDigits: 0x1,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x1},
- Pattern{Affix: "\x00\x03\u00a0%",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x7,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x2,
- GroupingSize: [2]uint8{0x3,
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x3,
+ GroupingSize: [2]uint8{0x0,
0x0},
- Flags: 0x0,
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
MinIntegerDigits: 0x1,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0},
- Pattern{Affix: "\x00\x01%",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x6,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x2,
+ Affix: "\x00\x03\u00a0%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x7,
GroupingSize: [2]uint8{0x3,
0x0},
- Flags: 0x0,
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
MinIntegerDigits: 0x1,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0},
- Pattern{Affix: "",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0xc,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x0,
+ Affix: "\x00\x01%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x6,
GroupingSize: [2]uint8{0x3,
- 0x2},
- Flags: 0x0,
+ 0x0},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 3,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
MinIntegerDigits: 0x1,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x3,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0},
- Pattern{Affix: "\x00\x01%",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x9,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x2,
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0xc,
GroupingSize: [2]uint8{0x3,
0x2},
- Flags: 0x0,
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
MinIntegerDigits: 0x1,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0},
- Pattern{Affix: "\x00\x03\u00a0%",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0xa,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x2,
+ Affix: "\x00\x01%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x9,
GroupingSize: [2]uint8{0x3,
0x2},
- Flags: 0x0,
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
MinIntegerDigits: 0x1,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0},
- Pattern{Affix: "",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x9,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x0,
- GroupingSize: [2]uint8{0x0,
- 0x0},
- Flags: 0x0,
+ Affix: "\x00\x03\u00a0%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0xa,
+ GroupingSize: [2]uint8{0x3,
+ 0x2},
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 6,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
MinIntegerDigits: 0x1,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x6,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0},
- Pattern{Affix: "",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0xd,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x0,
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x9,
GroupingSize: [2]uint8{0x0,
0x0},
- Flags: 0x4,
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 6,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
MinIntegerDigits: 0x1,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x6,
- MaxFractionDigits: 0x6,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x3},
- Pattern{Affix: "\x00\x01%",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x3,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x2,
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0xd,
GroupingSize: [2]uint8{0x0,
0x0},
- Flags: 0x0,
+ Flags: 0x4},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
MinIntegerDigits: 0x1,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0},
- Pattern{Affix: "\x03%\u00a0\x00",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x7,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x2,
- GroupingSize: [2]uint8{0x3,
+ Affix: "\x00\x01%",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x3,
+ GroupingSize: [2]uint8{0x0,
0x0},
- Flags: 0x0,
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
MinIntegerDigits: 0x1,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0},
- Pattern{Affix: "\x03%\u00a0\x00\x04%\u00a0-\x00",
- Offset: 0x0,
- NegOffset: 0x5,
- FormatWidth: 0x7,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x2,
+ Affix: "\x03%\u00a0\x00",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x7,
GroupingSize: [2]uint8{0x3,
0x0},
- Flags: 0x0,
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
MinIntegerDigits: 0x1,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0},
- Pattern{Affix: "\x01[\x01]",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x5,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x0,
- GroupingSize: [2]uint8{0x0,
+ Affix: "\x03%\u00a0\x00\x04%\u00a0-\x00",
+ Offset: 0x0,
+ NegOffset: 0x5,
+ PadRune: 0,
+ FormatWidth: 0x7,
+ GroupingSize: [2]uint8{0x3,
0x0},
- Flags: 0x0,
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
MinIntegerDigits: 0x0,
MaxIntegerDigits: 0x1,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x1},
- Pattern{Affix: "",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x1,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x0,
+ Affix: "\x01[\x01]",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x5,
GroupingSize: [2]uint8{0x0,
0x0},
- Flags: 0x0,
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x0,
MinIntegerDigits: 0x0,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
MinExponentDigits: 0x0},
- Pattern{Affix: "\x01%\x00",
- Offset: 0x0,
- NegOffset: 0x0,
- FormatWidth: 0x6,
- RoundIncrement: 0x0,
- PadRune: 0,
- DigitShift: 0x2,
- GroupingSize: [2]uint8{0x3,
+ Affix: "",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x1,
+ GroupingSize: [2]uint8{0x0,
0x0},
- Flags: 0x0,
+ Flags: 0x0},
+ Pattern{RoundingContext: RoundingContext{MaxSignificantDigits: 0,
+ MaxFractionDigits: 0,
+ Increment: 0x0,
+ IncrementScale: 0x0,
+ Mode: 0x0,
+ DigitShift: 0x2,
MinIntegerDigits: 0x1,
MaxIntegerDigits: 0x0,
MinFractionDigits: 0x0,
- MaxFractionDigits: 0x0,
MinSignificantDigits: 0x0,
- MaxSignificantDigits: 0x0,
- MinExponentDigits: 0x0}}
+ MinExponentDigits: 0x0},
+ Affix: "\x01%\x00",
+ Offset: 0x0,
+ NegOffset: 0x0,
+ PadRune: 0,
+ FormatWidth: 0x6,
+ GroupingSize: [2]uint8{0x3,
+ 0x0},
+ Flags: 0x0}}
// Total table size 7101 bytes (6KiB); checksum: 5190D0B3