1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/i18n/number_formatting.h"
11 #include "base/check.h"
12 #include "base/format_macros.h"
13 #include "base/i18n/message_formatter.h"
14 #include "base/i18n/unicodestring.h"
15 #include "base/lazy_instance.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "third_party/icu/source/common/unicode/ustring.h"
20 #include "third_party/icu/source/i18n/unicode/numfmt.h"
26 // A simple wrapper around icu::NumberFormat that allows for resetting it
27 // (as LazyInstance does not).
28 struct NumberFormatWrapper {
29 NumberFormatWrapper() {
34 // There's no ICU call to destroy a NumberFormat object other than
35 // operator delete, so use the default Delete, which calls operator delete.
36 // This can cause problems if a different allocator is used by this file
38 UErrorCode status = U_ZERO_ERROR;
39 number_format.reset(icu::NumberFormat::createInstance(status));
40 DCHECK(U_SUCCESS(status));
43 std::unique_ptr<icu::NumberFormat> number_format;
46 LazyInstance<NumberFormatWrapper>::DestructorAtExit g_number_format_int =
47 LAZY_INSTANCE_INITIALIZER;
48 LazyInstance<NumberFormatWrapper>::DestructorAtExit g_number_format_float =
49 LAZY_INSTANCE_INITIALIZER;
53 std::u16string FormatNumber(int64_t number) {
54 icu::NumberFormat* number_format =
55 g_number_format_int.Get().number_format.get();
58 // As a fallback, just return the raw number in a string.
59 return ASCIIToUTF16(StringPrintf("%" PRId64, number));
61 icu::UnicodeString ustr;
62 number_format->format(number, ustr);
64 return i18n::UnicodeStringToString16(ustr);
67 std::u16string FormatDouble(double number, int fractional_digits) {
68 return FormatDouble(number, fractional_digits, fractional_digits);
71 std::u16string FormatDouble(double number,
72 int min_fractional_digits,
73 int max_fractional_digits) {
74 icu::NumberFormat* number_format =
75 g_number_format_float.Get().number_format.get();
78 // As a fallback, just return the raw number in a string.
79 return ASCIIToUTF16(StringPrintf("%f", number));
81 number_format->setMaximumFractionDigits(max_fractional_digits);
82 number_format->setMinimumFractionDigits(min_fractional_digits);
83 icu::UnicodeString ustr;
84 number_format->format(number, ustr);
86 return i18n::UnicodeStringToString16(ustr);
89 std::u16string FormatPercent(int number) {
90 return i18n::MessageFormatter::FormatWithNumberedArgs(
91 u"{0,number,percent}", static_cast<double>(number) / 100.0);
94 void ResetFormattersForTesting() {
95 g_number_format_int.Get().Reset();
96 g_number_format_float.Get().Reset();