Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(300)

Unified Diff: components/payments/currency_formatter.cc

Issue 2621033003: [Payments] Currency formatter for order amounts. (Closed)
Patch Set: Initial Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/payments/currency_formatter.cc
diff --git a/components/payments/currency_formatter.cc b/components/payments/currency_formatter.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ef51b1d2f1c74d42f934010735a78c615eaf960c
--- /dev/null
+++ b/components/payments/currency_formatter.cc
@@ -0,0 +1,91 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/payments/currency_formatter.h"
+
+#include <memory>
+
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "third_party/icu/source/common/unicode/unistr.h"
+#include "third_party/icu/source/common/unicode/utypes.h"
+#include "third_party/icu/source/i18n/unicode/numfmt.h"
+
+namespace payments {
+
+namespace {
+
+// Max currency code length. Length of currency code can be at most 2048.
+const static size_t kMaxCurrencyCodeLength = 2048;
+
+} // namespace
+
+const std::string FormatAmountForCurrency(const std::string& amount,
+ const std::string& currency_code,
+ const icu::Locale& locale) {
+ // Lightweight validation first, checking for basic parameter validity.
+ if (currency_code.empty() || currency_code.size() > kMaxCurrencyCodeLength) {
+ LOG(ERROR) << "Invalid currency code length: " << currency_code;
+ return amount;
+ }
+ double amount_double = 0.0;
please use gerrit instead 2017/01/11 18:29:30 Do you think it may be better to not parse the "am
Mathieu 2017/01/11 22:22:25 I would think base::StringToDouble does the right
+ if (!base::StringToDouble(amount, &amount_double)) {
+ LOG(ERROR) << "Could not convert currency amount to double: " << amount;
+ return amount;
+ }
+
+ UErrorCode ignored = U_ZERO_ERROR;
+ std::unique_ptr<icu::NumberFormat> fmt(
+ icu::NumberFormat::createCurrencyInstance(locale, ignored));
please use gerrit instead 2017/01/11 18:29:30 Why ignore the error?
Mathieu 2017/01/11 22:22:25 a null result is ultimately returned when there is
+ if (!fmt) {
+ icu::UnicodeString name;
+ std::string locale_name;
+ locale.getDisplayName(name).toUTF8String(locale_name);
+ LOG(ERROR) << "Failed to initialize the currency formatter for "
+ << locale_name;
+ return amount;
+ }
+
+ icu::UnicodeString u_currency_code(currency_code.c_str(),
+ currency_code.length());
+ UErrorCode error_code = U_ZERO_ERROR;
+ fmt->setCurrency(u_currency_code.getBuffer(), error_code);
+ if (U_FAILURE(error_code)) {
+ LOG(ERROR) << "Could not set currency on amount formatter: "
please use gerrit instead 2017/01/11 18:29:30 Will print an error for non-ISO currency codes? An
Mathieu 2017/01/11 22:22:26 I've changed currency code handling. This function
+ << currency_code;
+ return amount;
+ }
+
+ icu::UnicodeString output;
+ fmt->format(amount_double, output);
+
+ if (!output.isEmpty()) {
please use gerrit instead 2017/01/11 18:29:30 If the output is empty, you should probably return
Mathieu 2017/01/11 22:22:25 Done. fair enough!
+ // Explicitely removes the currency code (truncated to its 3-letter and
please use gerrit instead 2017/01/11 18:29:30 Explicitly
Mathieu 2017/01/11 22:22:26 Done.
+ // 2-letter versions) from the output, because the payments implementation
+ // explicitely displays it alongside this result.
+ //
+ // 3+ letters: If currency code is "ABCDEF" or "BTX", this code will
+ // transform
+ // "ABC55.00"/"BTX55.00" to "55.00".
+ // 2 letters: If currency code is "CAD", this code will transform "CA$55.00"
+ // to "$55.00" (en_US) or "55,00 $ CA" to "55,00 $" (fr_FR).
+ u_currency_code.truncate(3);
+ output.findAndReplace(u_currency_code, "");
+ u_currency_code.truncate(2);
+ output.findAndReplace(u_currency_code, "");
+ // Trims any unicode whitespace (including non-breaking space).
please use gerrit instead 2017/01/11 18:29:30 base::TrimeWhitespace?
Mathieu 2017/01/11 22:22:26 Does not handle unicode non-breaking space trimmin
+ if (u_isUWhiteSpace(output[0])) {
+ output.remove(0, 1);
+ }
+ if (u_isUWhiteSpace(output[output.length() - 1])) {
+ output.remove(output.length() - 1, 1);
+ }
+ }
+
+ std::string output_str;
+ output.toUTF8String(output_str);
+ return output_str;
+}
+
+} // namespace payments

Powered by Google App Engine
This is Rietveld 408576698