xref: /aosp_15_r20/external/cronet/base/i18n/number_formatting.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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