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