...
1
2
3
4
5 package number
6
7 import (
8 "fmt"
9 "strings"
10
11 "golang.org/x/text/feature/plural"
12 "golang.org/x/text/internal/format"
13 "golang.org/x/text/internal/number"
14 "golang.org/x/text/language"
15 )
16
17
18 type FormatFunc func(x interface{}, opts ...Option) Formatter
19
20
21
22 func NewFormat(format FormatFunc, opts ...Option) FormatFunc {
23 o := *format(nil).options
24 n := len(o.options)
25 o.options = append(o.options[:n:n], opts...)
26 return func(x interface{}, opts ...Option) Formatter {
27 return newFormatter(&o, opts, x)
28 }
29 }
30
31 type options struct {
32 verbs string
33 initFunc initFunc
34 options []Option
35 pluralFunc func(t language.Tag, scale int) (f plural.Form, n int)
36 }
37
38 type optionFlag uint16
39
40 const (
41 hasScale optionFlag = 1 << iota
42 hasPrecision
43 noSeparator
44 exact
45 )
46
47 type initFunc func(f *number.Formatter, t language.Tag)
48
49 func newFormatter(o *options, opts []Option, value interface{}) Formatter {
50 if len(opts) > 0 {
51 n := *o
52 n.options = opts
53 o = &n
54 }
55 return Formatter{o, value}
56 }
57
58 func newOptions(verbs string, f initFunc) *options {
59 return &options{verbs: verbs, initFunc: f}
60 }
61
62 type Formatter struct {
63 *options
64 value interface{}
65 }
66
67
68 func (f Formatter) Format(state format.State, verb rune) {
69
70
71
72
73
74
75
76
77
78 lang := state.Language()
79 if !strings.Contains(f.verbs, string(verb)) {
80 fmt.Fprintf(state, "%%!%s(%T=%v)", string(verb), f.value, f.value)
81 return
82 }
83 var p number.Formatter
84 f.initFunc(&p, lang)
85 for _, o := range f.options.options {
86 o(lang, &p)
87 }
88 if w, ok := state.Width(); ok {
89 p.FormatWidth = uint16(w)
90 }
91 if prec, ok := state.Precision(); ok {
92 switch verb {
93 case 'd':
94 p.SetScale(0)
95 case 'f':
96 p.SetScale(prec)
97 case 'e':
98 p.SetPrecision(prec + 1)
99 case 'g':
100 p.SetPrecision(prec)
101 }
102 }
103 var d number.Decimal
104 d.Convert(p.RoundingContext, f.value)
105 state.Write(p.Format(nil, &d))
106 }
107
108
109
110
111 func (f Formatter) Digits(buf []byte, tag language.Tag, scale int) number.Digits {
112 var p number.Formatter
113 f.initFunc(&p, tag)
114 if scale >= 0 {
115
116
117 p.SetScale(scale)
118 }
119 var d number.Decimal
120 d.Convert(p.RoundingContext, f.value)
121 return number.FormatDigits(&d, p.RoundingContext)
122 }
123
View as plain text