1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/i18n/number_formatting.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10
11 #include "base/format_macros.h"
12 #include "base/i18n/message_formatter.h"
13 #include "base/i18n/unicodestring.h"
14 #include "base/lazy_instance.h"
15 #include "base/logging.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"
21
22 namespace base {
23
24 namespace {
25
26 // A simple wrapper around icu::NumberFormat that allows for resetting it
27 // (as LazyInstance does not).
28 struct NumberFormatWrapper {
NumberFormatWrapperbase::__anon698712ac0111::NumberFormatWrapper29 NumberFormatWrapper() {
30 Reset();
31 }
32
Resetbase::__anon698712ac0111::NumberFormatWrapper33 void Reset() {
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
37 // than by ICU.
38 UErrorCode status = U_ZERO_ERROR;
39 number_format.reset(icu::NumberFormat::createInstance(status));
40 DCHECK(U_SUCCESS(status));
41 }
42
43 std::unique_ptr<icu::NumberFormat> number_format;
44 };
45
46 LazyInstance<NumberFormatWrapper>::DestructorAtExit g_number_format_int =
47 LAZY_INSTANCE_INITIALIZER;
48 LazyInstance<NumberFormatWrapper>::DestructorAtExit g_number_format_float =
49 LAZY_INSTANCE_INITIALIZER;
50
51 } // namespace
52
FormatNumber(int64_t number)53 string16 FormatNumber(int64_t number) {
54 icu::NumberFormat* number_format =
55 g_number_format_int.Get().number_format.get();
56
57 if (!number_format) {
58 // As a fallback, just return the raw number in a string.
59 return ASCIIToUTF16(StringPrintf("%" PRId64, number));
60 }
61 icu::UnicodeString ustr;
62 number_format->format(number, ustr);
63
64 return i18n::UnicodeStringToString16(ustr);
65 }
66
FormatDouble(double number,int fractional_digits)67 string16 FormatDouble(double number, int fractional_digits) {
68 icu::NumberFormat* number_format =
69 g_number_format_float.Get().number_format.get();
70
71 if (!number_format) {
72 // As a fallback, just return the raw number in a string.
73 return ASCIIToUTF16(StringPrintf("%f", number));
74 }
75 number_format->setMaximumFractionDigits(fractional_digits);
76 number_format->setMinimumFractionDigits(fractional_digits);
77 icu::UnicodeString ustr;
78 number_format->format(number, ustr);
79
80 return i18n::UnicodeStringToString16(ustr);
81 }
82
FormatPercent(int number)83 string16 FormatPercent(int number) {
84 return i18n::MessageFormatter::FormatWithNumberedArgs(
85 ASCIIToUTF16("{0,number,percent}"), static_cast<double>(number) / 100.0);
86 }
87
88 namespace testing {
89
ResetFormatters()90 void ResetFormatters() {
91 g_number_format_int.Get().Reset();
92 g_number_format_float.Get().Reset();
93 }
94
95 } // namespace testing
96
97 } // namespace base
98