• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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