1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/i18n/number_formatting.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <memory>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/format_macros.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/i18n/message_formatter.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/i18n/unicodestring.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/lazy_instance.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
19*6777b538SAndroid Build Coastguard Worker #include "third_party/icu/source/common/unicode/ustring.h"
20*6777b538SAndroid Build Coastguard Worker #include "third_party/icu/source/i18n/unicode/numfmt.h"
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard Worker namespace base {
23*6777b538SAndroid Build Coastguard Worker
24*6777b538SAndroid Build Coastguard Worker namespace {
25*6777b538SAndroid Build Coastguard Worker
26*6777b538SAndroid Build Coastguard Worker // A simple wrapper around icu::NumberFormat that allows for resetting it
27*6777b538SAndroid Build Coastguard Worker // (as LazyInstance does not).
28*6777b538SAndroid Build Coastguard Worker struct NumberFormatWrapper {
NumberFormatWrapperbase::__anon9e25f3910111::NumberFormatWrapper29*6777b538SAndroid Build Coastguard Worker NumberFormatWrapper() {
30*6777b538SAndroid Build Coastguard Worker Reset();
31*6777b538SAndroid Build Coastguard Worker }
32*6777b538SAndroid Build Coastguard Worker
Resetbase::__anon9e25f3910111::NumberFormatWrapper33*6777b538SAndroid Build Coastguard Worker void Reset() {
34*6777b538SAndroid Build Coastguard Worker // There's no ICU call to destroy a NumberFormat object other than
35*6777b538SAndroid Build Coastguard Worker // operator delete, so use the default Delete, which calls operator delete.
36*6777b538SAndroid Build Coastguard Worker // This can cause problems if a different allocator is used by this file
37*6777b538SAndroid Build Coastguard Worker // than by ICU.
38*6777b538SAndroid Build Coastguard Worker UErrorCode status = U_ZERO_ERROR;
39*6777b538SAndroid Build Coastguard Worker number_format.reset(icu::NumberFormat::createInstance(status));
40*6777b538SAndroid Build Coastguard Worker DCHECK(U_SUCCESS(status));
41*6777b538SAndroid Build Coastguard Worker }
42*6777b538SAndroid Build Coastguard Worker
43*6777b538SAndroid Build Coastguard Worker std::unique_ptr<icu::NumberFormat> number_format;
44*6777b538SAndroid Build Coastguard Worker };
45*6777b538SAndroid Build Coastguard Worker
46*6777b538SAndroid Build Coastguard Worker LazyInstance<NumberFormatWrapper>::DestructorAtExit g_number_format_int =
47*6777b538SAndroid Build Coastguard Worker LAZY_INSTANCE_INITIALIZER;
48*6777b538SAndroid Build Coastguard Worker LazyInstance<NumberFormatWrapper>::DestructorAtExit g_number_format_float =
49*6777b538SAndroid Build Coastguard Worker LAZY_INSTANCE_INITIALIZER;
50*6777b538SAndroid Build Coastguard Worker
51*6777b538SAndroid Build Coastguard Worker } // namespace
52*6777b538SAndroid Build Coastguard Worker
FormatNumber(int64_t number)53*6777b538SAndroid Build Coastguard Worker std::u16string FormatNumber(int64_t number) {
54*6777b538SAndroid Build Coastguard Worker icu::NumberFormat* number_format =
55*6777b538SAndroid Build Coastguard Worker g_number_format_int.Get().number_format.get();
56*6777b538SAndroid Build Coastguard Worker
57*6777b538SAndroid Build Coastguard Worker if (!number_format) {
58*6777b538SAndroid Build Coastguard Worker // As a fallback, just return the raw number in a string.
59*6777b538SAndroid Build Coastguard Worker return ASCIIToUTF16(StringPrintf("%" PRId64, number));
60*6777b538SAndroid Build Coastguard Worker }
61*6777b538SAndroid Build Coastguard Worker icu::UnicodeString ustr;
62*6777b538SAndroid Build Coastguard Worker number_format->format(number, ustr);
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker return i18n::UnicodeStringToString16(ustr);
65*6777b538SAndroid Build Coastguard Worker }
66*6777b538SAndroid Build Coastguard Worker
FormatDouble(double number,int fractional_digits)67*6777b538SAndroid Build Coastguard Worker std::u16string FormatDouble(double number, int fractional_digits) {
68*6777b538SAndroid Build Coastguard Worker return FormatDouble(number, fractional_digits, fractional_digits);
69*6777b538SAndroid Build Coastguard Worker }
70*6777b538SAndroid Build Coastguard Worker
FormatDouble(double number,int min_fractional_digits,int max_fractional_digits)71*6777b538SAndroid Build Coastguard Worker std::u16string FormatDouble(double number,
72*6777b538SAndroid Build Coastguard Worker int min_fractional_digits,
73*6777b538SAndroid Build Coastguard Worker int max_fractional_digits) {
74*6777b538SAndroid Build Coastguard Worker icu::NumberFormat* number_format =
75*6777b538SAndroid Build Coastguard Worker g_number_format_float.Get().number_format.get();
76*6777b538SAndroid Build Coastguard Worker
77*6777b538SAndroid Build Coastguard Worker if (!number_format) {
78*6777b538SAndroid Build Coastguard Worker // As a fallback, just return the raw number in a string.
79*6777b538SAndroid Build Coastguard Worker return ASCIIToUTF16(StringPrintf("%f", number));
80*6777b538SAndroid Build Coastguard Worker }
81*6777b538SAndroid Build Coastguard Worker number_format->setMaximumFractionDigits(max_fractional_digits);
82*6777b538SAndroid Build Coastguard Worker number_format->setMinimumFractionDigits(min_fractional_digits);
83*6777b538SAndroid Build Coastguard Worker icu::UnicodeString ustr;
84*6777b538SAndroid Build Coastguard Worker number_format->format(number, ustr);
85*6777b538SAndroid Build Coastguard Worker
86*6777b538SAndroid Build Coastguard Worker return i18n::UnicodeStringToString16(ustr);
87*6777b538SAndroid Build Coastguard Worker }
88*6777b538SAndroid Build Coastguard Worker
FormatPercent(int number)89*6777b538SAndroid Build Coastguard Worker std::u16string FormatPercent(int number) {
90*6777b538SAndroid Build Coastguard Worker return i18n::MessageFormatter::FormatWithNumberedArgs(
91*6777b538SAndroid Build Coastguard Worker u"{0,number,percent}", static_cast<double>(number) / 100.0);
92*6777b538SAndroid Build Coastguard Worker }
93*6777b538SAndroid Build Coastguard Worker
ResetFormattersForTesting()94*6777b538SAndroid Build Coastguard Worker void ResetFormattersForTesting() {
95*6777b538SAndroid Build Coastguard Worker g_number_format_int.Get().Reset();
96*6777b538SAndroid Build Coastguard Worker g_number_format_float.Get().Reset();
97*6777b538SAndroid Build Coastguard Worker }
98*6777b538SAndroid Build Coastguard Worker
99*6777b538SAndroid Build Coastguard Worker } // namespace base
100