summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/text/number/format.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/text/number/format.go')
-rw-r--r--vendor/golang.org/x/text/number/format.go122
1 files changed, 122 insertions, 0 deletions
diff --git a/vendor/golang.org/x/text/number/format.go b/vendor/golang.org/x/text/number/format.go
new file mode 100644
index 0000000..1c3d41b
--- /dev/null
+++ b/vendor/golang.org/x/text/number/format.go
@@ -0,0 +1,122 @@
+// 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"
+ "strings"
+
+ "golang.org/x/text/feature/plural"
+ "golang.org/x/text/internal/format"
+ "golang.org/x/text/internal/number"
+ "golang.org/x/text/language"
+)
+
+// A FormatFunc formates a number.
+type FormatFunc func(x interface{}, opts ...Option) Formatter
+
+// NewFormat creates a FormatFunc based on another FormatFunc and new options.
+// Use NewFormat to cash the creation of formatters.
+func NewFormat(format FormatFunc, opts ...Option) FormatFunc {
+ o := *format(nil).options
+ n := len(o.options)
+ o.options = append(o.options[:n:n], opts...)
+ return func(x interface{}, opts ...Option) Formatter {
+ return newFormatter(&o, opts, x)
+ }
+}
+
+type options struct {
+ verbs string
+ initFunc initFunc
+ options []Option
+ pluralFunc func(t language.Tag, scale int) (f plural.Form, n int)
+}
+
+type optionFlag uint16
+
+const (
+ hasScale optionFlag = 1 << iota
+ hasPrecision
+ noSeparator
+ exact
+)
+
+type initFunc func(f *number.Formatter, t language.Tag)
+
+func newFormatter(o *options, opts []Option, value interface{}) Formatter {
+ if len(opts) > 0 {
+ n := *o
+ n.options = opts
+ o = &n
+ }
+ return Formatter{o, value}
+}
+
+func newOptions(verbs string, f initFunc) *options {
+ return &options{verbs: verbs, initFunc: f}
+}
+
+type Formatter struct {
+ *options
+ value interface{}
+}
+
+// Format implements format.Formatter. It is for internal use only for now.
+func (f Formatter) Format(state format.State, verb rune) {
+ // TODO: consider implementing fmt.Formatter instead and using the following
+ // piece of code. This allows numbers to be rendered mostly as expected
+ // when using fmt. But it may get weird with the spellout options and we
+ // may need more of format.State over time.
+ // lang := language.Und
+ // if s, ok := state.(format.State); ok {
+ // lang = s.Language()
+ // }
+
+ lang := state.Language()
+ if !strings.Contains(f.verbs, string(verb)) {
+ fmt.Fprintf(state, "%%!%s(%T=%v)", string(verb), f.value, f.value)
+ return
+ }
+ var p number.Formatter
+ f.initFunc(&p, lang)
+ for _, o := range f.options.options {
+ o(lang, &p)
+ }
+ if w, ok := state.Width(); ok {
+ p.FormatWidth = uint16(w)
+ }
+ if prec, ok := state.Precision(); ok {
+ switch verb {
+ case 'd':
+ p.SetScale(0)
+ case 'f':
+ p.SetScale(prec)
+ case 'e':
+ p.SetPrecision(prec + 1)
+ case 'g':
+ p.SetPrecision(prec)
+ }
+ }
+ var d number.Decimal
+ d.Convert(p.RoundingContext, f.value)
+ state.Write(p.Format(nil, &d))
+}
+
+// Digits returns information about which logical digits will be presented to
+// the user. This information is relevant, for instance, to determine plural
+// forms.
+func (f Formatter) Digits(buf []byte, tag language.Tag, scale int) number.Digits {
+ var p number.Formatter
+ f.initFunc(&p, tag)
+ if scale >= 0 {
+ // TODO: this only works well for decimal numbers, which is generally
+ // fine.
+ p.SetScale(scale)
+ }
+ var d number.Decimal
+ d.Convert(p.RoundingContext, f.value)
+ return number.FormatDigits(&d, p.RoundingContext)
+}