internal/number: implement more formatting

- simplified API
   - use MinExpDigits to determine whether to use
     scientific or decimal.
   - test added to verify that this is correct.
- reuse percent pattern for permille:
  - use DigitShift instead of Multiplier
- added support for padding
- copy Pattern, instead of using pointer, to allow
  tinkering
- small fix for quoting.

Change-Id: Ib83ab28f2cad57e90d73bb30b346ab7845a56333
Reviewed-on: https://go-review.googlesource.com/46157
Run-TryBot: Marcel van Lohuizen <mpvl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/internal/number/decimal.go b/internal/number/decimal.go
index a323ae7..eedc76f 100644
--- a/internal/number/decimal.go
+++ b/internal/number/decimal.go
@@ -275,29 +275,29 @@
 		d.clear()
 		f.Convert(d, r)
 	case float32:
-		d.convertFloat64(r, float64(f), 32)
+		d.ConvertFloat(r, float64(f), 32)
 	case float64:
-		d.convertFloat64(r, f, 64)
+		d.ConvertFloat(r, f, 64)
 	case int:
-		d.convertInt(r, signed, uint64(f))
+		d.ConvertInt(r, signed, uint64(f))
 	case int8:
-		d.convertInt(r, signed, uint64(f))
+		d.ConvertInt(r, signed, uint64(f))
 	case int16:
-		d.convertInt(r, signed, uint64(f))
+		d.ConvertInt(r, signed, uint64(f))
 	case int32:
-		d.convertInt(r, signed, uint64(f))
+		d.ConvertInt(r, signed, uint64(f))
 	case int64:
-		d.convertInt(r, signed, uint64(f))
+		d.ConvertInt(r, signed, uint64(f))
 	case uint:
-		d.convertInt(r, unsigned, uint64(f))
+		d.ConvertInt(r, unsigned, uint64(f))
 	case uint8:
-		d.convertInt(r, unsigned, uint64(f))
+		d.ConvertInt(r, unsigned, uint64(f))
 	case uint16:
-		d.convertInt(r, unsigned, uint64(f))
+		d.ConvertInt(r, unsigned, uint64(f))
 	case uint32:
-		d.convertInt(r, unsigned, uint64(f))
+		d.ConvertInt(r, unsigned, uint64(f))
 	case uint64:
-		d.convertInt(r, unsigned, f)
+		d.ConvertInt(r, unsigned, f)
 
 		// TODO:
 		// case string: if produced by strconv, allows for easy arbitrary pos.
@@ -310,13 +310,14 @@
 	}
 }
 
-func (d *Decimal) convertInt(r *RoundingContext, signed bool, x uint64) {
+// 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.convertFloat64(r, float64(int64(x)), 64)
+			d.ConvertFloat(r, float64(int64(x)), 64)
 		} else {
-			d.convertFloat64(r, float64(x), 64)
+			d.ConvertFloat(r, float64(x), 64)
 		}
 		return
 	}
@@ -329,7 +330,8 @@
 	d.Exp = int32(len(d.Digits))
 }
 
-func (d *Decimal) convertFloat64(r *RoundingContext, x float64, size int) {
+// 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
diff --git a/internal/number/format.go b/internal/number/format.go
index 84903fa..9ceaf04 100755
--- a/internal/number/format.go
+++ b/internal/number/format.go
@@ -6,41 +6,128 @@
 
 import (
 	"strconv"
+	"unicode/utf8"
 
 	"golang.org/x/text/language"
 )
 
 // TODO:
-// - public (but internal) API for creating formatters
 // - split out the logic that computes the visible digits from the rest of the
 //   formatting code (needed for plural).
 // - grouping of fractions
-// - reuse percent pattern for permille
-// - padding
 
 // Formatter contains all the information needed to render a number.
 type Formatter struct {
-	*Pattern
+	Pattern
 	Info
 	RoundingContext
-	f func(dst []byte, f *Formatter, d *Decimal) []byte
 }
 
-func lookupFormat(t language.Tag, tagToIndex []uint8) *Pattern {
+func (f *Formatter) init(t language.Tag, index []uint8) {
+	f.Info = InfoFromTag(t)
 	for ; ; t = t.Parent() {
 		if ci, ok := language.CompactIndex(t); ok {
-			return &formats[tagToIndex[ci]]
+			f.Pattern = formats[index[ci]]
+			break
 		}
 	}
 }
 
-func (f *Formatter) Format(dst []byte, d *Decimal) []byte {
-	return f.f(dst, f, d)
+// InitPattern initializes a Formatter for the given Pattern.
+func (f *Formatter) InitPattern(t language.Tag, pat *Pattern) {
+	f.Info = InfoFromTag(t)
+	f.Pattern = *pat
 }
 
-func appendDecimal(dst []byte, f *Formatter, d *Decimal) []byte {
+// 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
+		return dst, 0, len(dst)
 	}
 	n := d.normalize()
 	if maxSig := int(f.MaxSignificantDigits); maxSig > 0 {
@@ -48,6 +135,7 @@
 	}
 	digits := n.Digits
 	exp := n.Exp
+	exp += int32(f.Pattern.DigitShift)
 
 	// Split in integer and fraction part.
 	var intDigits, fracDigits []byte
@@ -148,12 +236,14 @@
 	if len(dst) == savedLen {
 		dst = f.AppendDigit(dst, 0)
 	}
-	return appendAffix(dst, f, suffix, neg)
+	return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
 }
 
-func appendScientific(dst []byte, f *Formatter, d *Decimal) []byte {
+// 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
+		return dst, 0, 0
 	}
 	// Significant digits are transformed by parser for scientific notation and
 	// do not need to be handled here.
@@ -244,14 +334,14 @@
 		dst = append(dst, f.Symbol(SymPlusSign)...)
 	}
 	buf := [12]byte{}
-	b := strconv.AppendUint(buf[:0], uint64(exp), 10)
+	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)
+	return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
 }
 
 func (f *Formatter) getAffixes(neg bool) (affix, suffix string) {
@@ -307,7 +397,15 @@
 			escaping = true
 		case r == '\'':
 			quoting = !quoting
-		case !quoting && (r == '-' || r == '+'):
+		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 {
diff --git a/internal/number/format_test.go b/internal/number/format_test.go
index 355a33a..850ad82 100755
--- a/internal/number/format_test.go
+++ b/internal/number/format_test.go
@@ -7,7 +7,6 @@
 import (
 	"fmt"
 	"log"
-	"strings"
 	"testing"
 
 	"golang.org/x/text/language"
@@ -287,22 +286,139 @@
 			"12345":   "12.34E03",
 			"123.456": "123.4E00",
 		},
+	}, {
+		pattern: "@@E0",
+		test: pairs{
+			"0":    "0.0E0",
+			"99":   "9.9E1",
+			"0.99": "9.9E-1",
+		},
+	}, {
+		pattern: "@###E00",
+		test: pairs{
+			"0":     "0E00",
+			"1":     "1E00",
+			"11":    "1.1E01",
+			"111":   "1.11E02",
+			"1111":  "1.111E03",
+			"11111": "1.111E04",
+			"0.1":   "1E-01",
+			"0.11":  "1.1E-01",
+			"0.001": "1E-03",
+		},
+	}, {
+		pattern: "*x###",
+		test: pairs{
+			"0":    "xx0",
+			"10":   "x10",
+			"100":  "100",
+			"1000": "1000",
+		},
+	}, {
+		pattern: "###*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.0E00",
+			"10":    "**1.0E01",
+			"11":    "**1.1E01",
+			"111":   "*1.11E02",
+			"1111":  "1.111E03",
+			"11111": "1.111E04",
+			"11110": "1.111E04",
+			"11100": "*1.11E04",
+			"11000": "**1.1E04",
+			"10000": "**1.0E04",
+		},
+	}, {
+		pattern: "*xpre#suf",
+		test: pairs{
+			"0":  "pre0suf",
+			"10": "pre10suf",
+		},
+	}, {
+		pattern: "*∞ pre #### suf",
+		test: pairs{
+			"0":    "∞∞∞ pre 0 suf",
+			"10":   "∞∞ pre 10 suf",
+			"100":  "∞ pre 100 suf",
+			"1000": " pre 1000 suf",
+		},
+	}, {
+		pattern: "pre *∞#### suf",
+		test: pairs{
+			"0":    "pre ∞∞∞0 suf",
+			"10":   "pre ∞∞10 suf",
+			"100":  "pre ∞100 suf",
+			"1000": "pre 1000 suf",
+		},
+	}, {
+		pattern: "pre ####*∞ suf",
+		test: pairs{
+			"0":    "pre 0∞∞∞ suf",
+			"10":   "pre 10∞∞ suf",
+			"100":  "pre 100∞ suf",
+			"1000": "pre 1000 suf",
+		},
+	}, {
+		pattern: "pre #### 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: "**####;**-######x",
+		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:
-	// 	"@@E0",
-	// 	"@###E00",
-	// 	"0.0%",
-	// 	"0.0‰",
 	// 	"#,##0.00¤",
 	// 	"#,##0.00 ¤;(#,##0.00 ¤)",
-	// 	// padding
-	// 	"*x#",
-	// 	"#*x",
-	// 	"*xpre#suf",
-	// 	"pre*x#suf",
-	// 	"pre#*xsuf",
-	// 	"pre#suf*x",
+
 	for _, tc := range testCases {
 		pat := tc.pat
 		if pat == nil {
@@ -311,15 +427,8 @@
 				log.Fatal(err)
 			}
 		}
-		f := &Formatter{
-			pat,
-			InfoFromTag(language.English),
-			RoundingContext{},
-			appendDecimal,
-		}
-		if strings.IndexByte(tc.pattern, 'E') != -1 {
-			f.f = appendScientific
-		}
+		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) {
@@ -347,12 +456,36 @@
 	}
 	for _, tc := range testCases {
 		t.Run(fmt.Sprint(tc.tag, "/", tc.num), func(t *testing.T) {
-			f := &Formatter{
-				lookupFormat(tc.tag, tagToDecimal),
-				InfoFromTag(tc.tag),
-				RoundingContext{},
-				appendDecimal,
+			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 %q; want %q", 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.23E5"},
+		{f.InitEngineering, "123456.78", "123E3"},
+
+		{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 {
diff --git a/internal/number/pattern.go b/internal/number/pattern.go
index 5610c60..8d7f9a6 100644
--- a/internal/number/pattern.go
+++ b/internal/number/pattern.go
@@ -46,11 +46,11 @@
 	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
@@ -247,26 +247,41 @@
 		'#', '@', '.', '*', ',', ';':
 		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)...)
diff --git a/internal/number/pattern_test.go b/internal/number/pattern_test.go
index 6adeaf7..97ff64d 100644
--- a/internal/number/pattern_test.go
+++ b/internal/number/pattern_test.go
@@ -114,6 +114,11 @@
 		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{
 		FormatWidth:       3,
@@ -230,7 +235,7 @@
 	"0.0%",
 	&Pattern{
 		Affix:             "\x00\x01%",
-		Multiplier:        100,
+		DigitShift:        2,
 		FormatWidth:       4,
 		MinIntegerDigits:  1,
 		MinFractionDigits: 1,
@@ -240,7 +245,7 @@
 	"0.0‰",
 	&Pattern{
 		Affix:             "\x00\x03‰",
-		Multiplier:        1000,
+		DigitShift:        3,
 		FormatWidth:       4,
 		MinIntegerDigits:  1,
 		MinFractionDigits: 1,
@@ -260,7 +265,7 @@
 	"#,##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,
@@ -314,6 +319,19 @@
 		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,
 }, {
diff --git a/internal/number/tables.go b/internal/number/tables.go
index 10baa0a..defe95d 100644
--- a/internal/number/tables.go
+++ b/internal/number/tables.go
@@ -846,10 +846,10 @@
 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 +863,10 @@
 	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 +880,10 @@
 	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 +897,10 @@
 	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 +914,10 @@
 	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 +931,10 @@
 	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 +948,10 @@
 	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 +965,10 @@
 	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 +982,10 @@
 	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,10 +999,10 @@
 	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,
@@ -1016,10 +1016,10 @@
 	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,10 +1033,10 @@
 	Pattern{Affix: "\x03%\u00a0\x00",
 		Offset:         0x0,
 		NegOffset:      0x0,
-		Multiplier:     0x64,
+		FormatWidth:    0x7,
 		RoundIncrement: 0x0,
 		PadRune:        0,
-		FormatWidth:    0x7,
+		DigitShift:     0x2,
 		GroupingSize: [2]uint8{0x3,
 			0x0},
 		Flags:                0x0,
@@ -1050,10 +1050,10 @@
 	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 +1067,10 @@
 	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 +1084,10 @@
 	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,10 +1101,10 @@
 	Pattern{Affix: "\x01%\x00",
 		Offset:         0x0,
 		NegOffset:      0x0,
-		Multiplier:     0x64,
+		FormatWidth:    0x6,
 		RoundIncrement: 0x0,
 		PadRune:        0,
-		FormatWidth:    0x6,
+		DigitShift:     0x2,
 		GroupingSize: [2]uint8{0x3,
 			0x0},
 		Flags:                0x0,