diff options
author | joeybloggs <Dean.Karn@gmail.com> | 2016-08-12 19:15:42 +0300 |
---|---|---|
committer | joeybloggs <Dean.Karn@gmail.com> | 2016-08-12 19:15:42 +0300 |
commit | 7639a439740dfc3cdda4ae188bf3baf7cc2ff7a3 (patch) | |
tree | 7c43c1081bb3e25696701bd8e13ab0efee92cec4 /cmd | |
parent | df0d272ef2250baaad947ff65501398623365e61 (diff) |
Add FmtNumber function + logic.
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/generate_resources.go | 240 | ||||
-rw-r--r-- | cmd/translator.tmpl | 74 |
2 files changed, 164 insertions, 150 deletions
diff --git a/cmd/generate_resources.go b/cmd/generate_resources.go index 14bbd36d..49a3d78b 100644 --- a/cmd/generate_resources.go +++ b/cmd/generate_resources.go @@ -31,17 +31,20 @@ var ( "t": "t := locales.T(n, v)\n", } - translators = make(map[string]*translator) - baseTranslators = make(map[string]*translator) - globalCurrenciesMap = make(map[string]struct{}) // ["USD"] = "$" currency code, just all currencies for mapping to enum - globCurrencyIdxMap = make(map[string]int) // ["USD"] = 0 - globalCurrencies = make([]string, 0, 100) // array of currency codes index maps to enum - tmpl *template.Template - nModRegex = regexp.MustCompile("(n%[0-9]+)") - iModRegex = regexp.MustCompile("(i%[0-9]+)") - wModRegex = regexp.MustCompile("(w%[0-9]+)") - fModRegex = regexp.MustCompile("(f%[0-9]+)") - tModRegex = regexp.MustCompile("(t%[0-9]+)") + translators = make(map[string]*translator) + baseTranslators = make(map[string]*translator) + globalCurrenciesMap = make(map[string]struct{}) // ["USD"] = "$" currency code, just all currencies for mapping to enum + globCurrencyIdxMap = make(map[string]int) // ["USD"] = 0 + globalCurrencies = make([]string, 0, 100) // array of currency codes index maps to enum + tmpl *template.Template + nModRegex = regexp.MustCompile("(n%[0-9]+)") + iModRegex = regexp.MustCompile("(i%[0-9]+)") + wModRegex = regexp.MustCompile("(w%[0-9]+)") + fModRegex = regexp.MustCompile("(f%[0-9]+)") + tModRegex = regexp.MustCompile("(t%[0-9]+)") + groupLenRegex = regexp.MustCompile(",([0-9#]+)\\.") + requiredNumRegex = regexp.MustCompile("([0-9]+)\\.") + requiredDecimalRegex = regexp.MustCompile("\\.([0-9]+)") ) type translator struct { @@ -58,6 +61,13 @@ type translator struct { Percent string PerMille string Currencies string + // FmtNumberFunc string + FmtNumberExists bool + FmtNumberGroupLen int + FmtNumberMinDecimalLen int + + // calculation only fields + DecimalNumberFormat string } func main() { @@ -234,6 +244,14 @@ func postProcess(cldr *cldr.CLDR) { // Currency // number values + + if len(trans.DecimalNumberFormat) == 0 { + + if found { + trans.DecimalNumberFormat = base.DecimalNumberFormat + } + } + ldml := cldr.RawLDML(trans.Locale) currencies := make([][]byte, len(globalCurrencies), len(globalCurrencies)) @@ -243,27 +261,32 @@ func postProcess(cldr *cldr.CLDR) { } // some just have no data... - if ldml.Numbers != nil && ldml.Numbers.Currencies != nil { + if ldml.Numbers != nil { - for _, currency := range ldml.Numbers.Currencies.Currency { + if ldml.Numbers.Currencies != nil { + for _, currency := range ldml.Numbers.Currencies.Currency { - if len(currency.Symbol) == 0 { - continue - } + if len(currency.Symbol) == 0 { + continue + } - if len(currency.Symbol[0].Data()) == 0 { - continue - } + if len(currency.Symbol[0].Data()) == 0 { + continue + } - if len(currency.Type) == 0 { - continue - } + if len(currency.Type) == 0 { + continue + } - currencies[globCurrencyIdxMap[currency.Type]] = []byte(currency.Symbol[0].Data()) + currencies[globCurrencyIdxMap[currency.Type]] = []byte(currency.Symbol[0].Data()) + } } } trans.Currencies = fmt.Sprintf("%#v", currencies) + + parseDecimalNumberFormat(trans) + // trans.FmtNumberFunc = parseDecimalNumberFormat(trans.DecimalNumberFormat, trans.BaseLocale) } } @@ -295,24 +318,27 @@ func preProcess(cldr *cldr.CLDR) { ldml := cldr.RawLDML(l) // some just have no data... - if ldml.Numbers != nil && len(ldml.Numbers.Symbols) > 0 { + if ldml.Numbers != nil { - symbol := ldml.Numbers.Symbols[0] + if len(ldml.Numbers.Symbols) > 0 { - if len(symbol.Decimal) > 0 { - trans.Decimal = fmt.Sprintf("%#v", []byte(symbol.Decimal[0].Data())) - } - if len(symbol.Group) > 0 { - trans.Group = fmt.Sprintf("%#v", []byte(symbol.Group[0].Data())) - } - if len(symbol.MinusSign) > 0 { - trans.Minus = fmt.Sprintf("%#v", []byte(symbol.MinusSign[0].Data())) - } - if len(symbol.PercentSign) > 0 { - trans.Percent = fmt.Sprintf("%#v", []byte(symbol.PercentSign[0].Data())) - } - if len(symbol.PerMille) > 0 { - trans.PerMille = fmt.Sprintf("%#v", []byte(symbol.PerMille[0].Data())) + symbol := ldml.Numbers.Symbols[0] + + if len(symbol.Decimal) > 0 { + trans.Decimal = fmt.Sprintf("%#v", []byte(symbol.Decimal[0].Data())) + } + if len(symbol.Group) > 0 { + trans.Group = fmt.Sprintf("%#v", []byte(symbol.Group[0].Data())) + } + if len(symbol.MinusSign) > 0 { + trans.Minus = fmt.Sprintf("%#v", []byte(symbol.MinusSign[0].Data())) + } + if len(symbol.PercentSign) > 0 { + trans.Percent = fmt.Sprintf("%#v", []byte(symbol.PercentSign[0].Data())) + } + if len(symbol.PerMille) > 0 { + trans.PerMille = fmt.Sprintf("%#v", []byte(symbol.PerMille[0].Data())) + } } if ldml.Numbers.Currencies != nil { @@ -327,6 +353,16 @@ func preProcess(cldr *cldr.CLDR) { } } + if len(ldml.Numbers.DecimalFormats) > 0 && len(ldml.Numbers.DecimalFormats[0].DecimalFormatLength) > 0 { + + for _, dfl := range ldml.Numbers.DecimalFormats[0].DecimalFormatLength { + if len(dfl.Type) == 0 { + trans.DecimalNumberFormat = dfl.DecimalFormat[0].Pattern[0].Data() + break + } + } + } + // var decimalFormat, currencyFormat, currencyAccountingFormat, percentageFormat string // if len(ldml.Numbers.DecimalFormats) > 0 && len(ldml.Numbers.DecimalFormats[0].DecimalFormatLength) > 0 { @@ -365,122 +401,26 @@ func preProcess(cldr *cldr.CLDR) { } } -// func parseNumbers(decimal, group, minus, percent, permille, decimalFormat, currencyFormat, currencyAccountingFormat, percentageFormat string) { - -// if includeDecimalDigits { - -// nfMutex.RLock() - -// if format, exists := numberFormats[pattern]; exists { -// nfMutex.RUnlock() -// return format -// } - -// nfMutex.RUnlock() - -// } else { - -// nfndMutex.RLock() - -// if format, exists := numberFormatsNoDecimals[pattern]; exists { -// nfndMutex.RUnlock() -// return format -// } - -// nfndMutex.RUnlock() -// } - -// format := new(numberFormat) -// patterns := strings.Split(pattern, ";") - -// matches := prefixSuffixRegex.FindAllStringSubmatch(patterns[0], -1) -// if len(matches) > 0 { -// if len(matches[0]) > 1 { -// format.positivePrefix = matches[0][1] -// } -// if len(matches[0]) > 2 { -// format.positiveSuffix = matches[0][2] -// } -// } - -// // default values for negative prefix & suffix -// format.negativePrefix = string(n.Symbols.Negative) + string(format.positivePrefix) -// format.negativeSuffix = format.positiveSuffix - -// // see if they are in the pattern -// if len(patterns) > 1 { -// matches = prefixSuffixRegex.FindAllStringSubmatch(patterns[1], -1) - -// if len(matches) > 0 { -// if len(matches[0]) > 1 { -// format.negativePrefix = matches[0][1] -// } -// if len(matches[0]) > 2 { -// format.negativeSuffix = matches[0][2] -// } -// } -// } - -// pat := patterns[0] +func parseDecimalNumberFormat(trans *translator) (results string) { -// if strings.Index(pat, "%") != -1 { -// format.multiplier = 100 -// } else if strings.Index(pat, "‰") != -1 { -// format.multiplier = 1000 -// } else { -// format.multiplier = 1 -// } - -// pos := strings.Index(pat, ".") - -// if pos != -1 { -// pos2 := strings.LastIndex(pat, "0") -// if pos2 > pos { -// format.minDecimalDigits = pos2 - pos -// } - -// pos3 := strings.LastIndex(pat, "#") -// if pos3 >= pos2 { -// format.maxDecimalDigits = pos3 - pos -// } else { -// format.maxDecimalDigits = format.minDecimalDigits -// } + if len(trans.DecimalNumberFormat) == 0 { + return + } -// pat = pat[0:pos] -// } + trans.FmtNumberExists = true -// p := strings.Replace(pat, ",", "", -1) -// pos = strings.Index(p, "0") -// if pos != -1 { -// format.minIntegerDigits = strings.LastIndex(p, "0") - pos + 1 -// } - -// p = strings.Replace(pat, "#", "0", -1) -// pos = strings.LastIndex(pat, ",") -// if pos != -1 { -// format.groupSizeFinal = strings.LastIndex(p, "0") - pos -// pos2 := strings.LastIndex(p[0:pos], ",") -// if pos2 != -1 { -// format.groupSizeMain = pos - pos2 - 1 -// } else { -// format.groupSizeMain = format.groupSizeFinal -// } -// } + match := groupLenRegex.FindString(trans.DecimalNumberFormat) + if len(match) > 0 { + trans.FmtNumberGroupLen = len(match) - 2 + } -// if includeDecimalDigits { -// nfMutex.Lock() -// numberFormats[pattern] = format -// nfMutex.Unlock() -// return format -// } + match = requiredDecimalRegex.FindString(trans.DecimalNumberFormat) + if len(match) > 0 { + trans.FmtNumberMinDecimalLen = len(match) - 1 + } -// format.maxDecimalDigits = 0 -// format.minDecimalDigits = 0 -// nfndMutex.Lock() -// numberFormatsNoDecimals[pattern] = format -// nfndMutex.Unlock() -// return format -// } + return +} type sortRank struct { Rank uint8 diff --git a/cmd/translator.tmpl b/cmd/translator.tmpl index 699e4673..b4c31b78 100644 --- a/cmd/translator.tmpl +++ b/cmd/translator.tmpl @@ -64,4 +64,78 @@ func({{ .BaseLocale }} *{{ .Locale }}) RangePluralRule(num1 float64, v1 uint64,n {{ .RangeFunc }} } +// FmtNumber returns 'num' with digits/precision of 'v' for '{{ .Locale }}' and handles both Whole and Real numbers based on 'v' +// returned as a []byte just in case the caller wishes to add more and can help +// avoid allocations; otherwise just cast as string. +func({{ .BaseLocale }} *{{ .Locale }}) FmtNumber(num float64, v uint64) []byte { + + s := strconv.FormatFloat(num, 'f', int(v), 64) + {{ if eq .FmtNumberExists true }} + {{ if gt .FmtNumberGroupLen 0 }} + l := len(s) + len({{ .BaseLocale }}.decimal) + len({{ .BaseLocale }}.group) * len(s[:len(s)-int(v)-1]) / {{ .FmtNumberGroupLen }} + count := 0 + inWhole := v == 0 + {{ else }} + l := len(s) + len({{ .BaseLocale }}.decimal) + {{ end }} + b := make([]byte, 0, l) + + for i := len(s) - 1; i >= 0; i-- { + + if s[i] == '.' { + + for j := len({{ .BaseLocale }}.decimal) - 1; j >= 0; j-- { + b = append(b, {{ .BaseLocale }}.decimal[j]) + } + + {{ if gt .FmtNumberGroupLen 0 }} + inWhole = true + {{ end }} + continue + } + + {{ if gt .FmtNumberGroupLen 0 }} + if inWhole { + + if count == {{ .FmtNumberGroupLen }} { + + for j := len({{ .BaseLocale }}.group) - 1; j >= 0; j-- { + b = append(b, {{ .BaseLocale }}.group[j]) + } + + count = 1 + } else { + count++ + } + } + + {{ end }} + + b = append(b, s[i]) + } + + // reverse + for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 { + b[i], b[j] = b[j], b[i] + } + + {{ if gt .FmtNumberMinDecimalLen 0 }} + if int(v) < {{ .FmtNumberMinDecimalLen }} { + + if v == 0 { + b = append(b, {{ .BaseLocale }}.decimal...) + } + + for i := 0; i < {{ .FmtNumberMinDecimalLen }}-int(v); i++ { + b = append(b, '0') + } + } + {{ end }} + + return b + {{ else }} + return []byte(s) + {{ end }} +} + {{ end }}
\ No newline at end of file |