Home | History | Annotate | Download | only in i18n
      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 "base/format_macros.h"
      8 #include "base/lazy_instance.h"
      9 #include "base/logging.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/strings/string_util.h"
     12 #include "base/strings/stringprintf.h"
     13 #include "base/strings/utf_string_conversions.h"
     14 #include "third_party/icu/source/common/unicode/ustring.h"
     15 #include "third_party/icu/source/i18n/unicode/numfmt.h"
     16 
     17 namespace base {
     18 
     19 namespace {
     20 
     21 // A simple wrapper around icu::NumberFormat that allows for resetting it
     22 // (as LazyInstance does not).
     23 struct NumberFormatWrapper {
     24   NumberFormatWrapper() {
     25     Reset();
     26   }
     27 
     28   void Reset() {
     29     // There's no ICU call to destroy a NumberFormat object other than
     30     // operator delete, so use the default Delete, which calls operator delete.
     31     // This can cause problems if a different allocator is used by this file
     32     // than by ICU.
     33     UErrorCode status = U_ZERO_ERROR;
     34     number_format.reset(icu::NumberFormat::createInstance(status));
     35     DCHECK(U_SUCCESS(status));
     36   }
     37 
     38   scoped_ptr<icu::NumberFormat> number_format;
     39 };
     40 
     41 LazyInstance<NumberFormatWrapper> g_number_format_int =
     42     LAZY_INSTANCE_INITIALIZER;
     43 LazyInstance<NumberFormatWrapper> g_number_format_float =
     44     LAZY_INSTANCE_INITIALIZER;
     45 
     46 }  // namespace
     47 
     48 string16 FormatNumber(int64 number) {
     49   icu::NumberFormat* number_format =
     50       g_number_format_int.Get().number_format.get();
     51 
     52   if (!number_format) {
     53     // As a fallback, just return the raw number in a string.
     54     return UTF8ToUTF16(StringPrintf("%" PRId64, number));
     55   }
     56   icu::UnicodeString ustr;
     57   number_format->format(number, ustr);
     58 
     59   return string16(ustr.getBuffer(), static_cast<size_t>(ustr.length()));
     60 }
     61 
     62 string16 FormatDouble(double number, int fractional_digits) {
     63   icu::NumberFormat* number_format =
     64       g_number_format_float.Get().number_format.get();
     65 
     66   if (!number_format) {
     67     // As a fallback, just return the raw number in a string.
     68     return UTF8ToUTF16(StringPrintf("%f", number));
     69   }
     70   number_format->setMaximumFractionDigits(fractional_digits);
     71   number_format->setMinimumFractionDigits(fractional_digits);
     72   icu::UnicodeString ustr;
     73   number_format->format(number, ustr);
     74 
     75   return string16(ustr.getBuffer(), static_cast<size_t>(ustr.length()));
     76 }
     77 
     78 namespace testing {
     79 
     80 void ResetFormatters() {
     81   g_number_format_int.Get().Reset();
     82   g_number_format_float.Get().Reset();
     83 }
     84 
     85 }  // namespace testing
     86 
     87 }  // namespace base
     88