number_formatting.cc 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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. #include "base/i18n/number_formatting.h"
  5. #include <stddef.h>
  6. #include <memory>
  7. #include "base/check.h"
  8. #include "base/format_macros.h"
  9. #include "base/i18n/message_formatter.h"
  10. #include "base/i18n/unicodestring.h"
  11. #include "base/lazy_instance.h"
  12. #include "base/strings/string_util.h"
  13. #include "base/strings/stringprintf.h"
  14. #include "base/strings/utf_string_conversions.h"
  15. #include "third_party/icu/source/common/unicode/ustring.h"
  16. #include "third_party/icu/source/i18n/unicode/numfmt.h"
  17. namespace base {
  18. namespace {
  19. // A simple wrapper around icu::NumberFormat that allows for resetting it
  20. // (as LazyInstance does not).
  21. struct NumberFormatWrapper {
  22. NumberFormatWrapper() {
  23. Reset();
  24. }
  25. void Reset() {
  26. // There's no ICU call to destroy a NumberFormat object other than
  27. // operator delete, so use the default Delete, which calls operator delete.
  28. // This can cause problems if a different allocator is used by this file
  29. // than by ICU.
  30. UErrorCode status = U_ZERO_ERROR;
  31. number_format.reset(icu::NumberFormat::createInstance(status));
  32. DCHECK(U_SUCCESS(status));
  33. }
  34. std::unique_ptr<icu::NumberFormat> number_format;
  35. };
  36. LazyInstance<NumberFormatWrapper>::DestructorAtExit g_number_format_int =
  37. LAZY_INSTANCE_INITIALIZER;
  38. LazyInstance<NumberFormatWrapper>::DestructorAtExit g_number_format_float =
  39. LAZY_INSTANCE_INITIALIZER;
  40. } // namespace
  41. std::u16string FormatNumber(int64_t number) {
  42. icu::NumberFormat* number_format =
  43. g_number_format_int.Get().number_format.get();
  44. if (!number_format) {
  45. // As a fallback, just return the raw number in a string.
  46. return ASCIIToUTF16(StringPrintf("%" PRId64, number));
  47. }
  48. icu::UnicodeString ustr;
  49. number_format->format(number, ustr);
  50. return i18n::UnicodeStringToString16(ustr);
  51. }
  52. std::u16string FormatDouble(double number, int fractional_digits) {
  53. icu::NumberFormat* number_format =
  54. g_number_format_float.Get().number_format.get();
  55. if (!number_format) {
  56. // As a fallback, just return the raw number in a string.
  57. return ASCIIToUTF16(StringPrintf("%f", number));
  58. }
  59. number_format->setMaximumFractionDigits(fractional_digits);
  60. number_format->setMinimumFractionDigits(fractional_digits);
  61. icu::UnicodeString ustr;
  62. number_format->format(number, ustr);
  63. return i18n::UnicodeStringToString16(ustr);
  64. }
  65. std::u16string FormatPercent(int number) {
  66. return i18n::MessageFormatter::FormatWithNumberedArgs(
  67. u"{0,number,percent}", static_cast<double>(number) / 100.0);
  68. }
  69. void ResetFormattersForTesting() {
  70. g_number_format_int.Get().Reset();
  71. g_number_format_float.Get().Reset();
  72. }
  73. } // namespace base