number_formatting.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/logging.h"
9#include "base/lazy_instance.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/stringprintf.h"
12#include "base/string_util.h"
13#include "base/utf_string_conversions.h"
14#include "third_party/icu/public/common/unicode/ustring.h"
15#include "third_party/icu/public/i18n/unicode/numfmt.h"
16
17namespace base {
18
19namespace {
20
21// A simple wrapper around icu::NumberFormat that allows for resetting it
22// (as LazyInstance does not).
23struct 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
41LazyInstance<NumberFormatWrapper> g_number_format_int =
42    LAZY_INSTANCE_INITIALIZER;
43LazyInstance<NumberFormatWrapper> g_number_format_float =
44    LAZY_INSTANCE_INITIALIZER;
45
46}  // namespace
47
48string16 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
62string16 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
78namespace testing {
79
80void 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