Bitcoin ABC  0.26.3
P2P Digital Currency
moneystr.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2015 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <util/moneystr.h>
7 
8 #include <consensus/amount.h>
9 #include <tinyformat.h>
10 #include <util/strencodings.h>
11 #include <util/string.h>
12 
13 std::string FormatMoney(const Amount amt) {
14  // Note: not using straight sprintf here because we do NOT want localized
15  // number formatting.
16  Amount amt_abs = amt > Amount::zero() ? amt : -amt;
17  const auto currency = Currency::get();
18  std::string str =
19  strprintf("%d.%0*d", amt_abs / currency.baseunit, currency.decimals,
20  (amt_abs % currency.baseunit) / currency.subunit);
21 
22  // Right-trim excess zeros before the decimal point:
23  int nTrim = 0;
24  for (int i = str.size() - 1; (str[i] == '0' && IsDigit(str[i - 2])); --i) {
25  ++nTrim;
26  }
27  if (nTrim) {
28  str.erase(str.size() - nTrim, nTrim);
29  }
30 
31  if (amt < Amount::zero()) {
32  str.insert((unsigned int)0, 1, '-');
33  }
34  return str;
35 }
36 
37 bool ParseMoney(const std::string &money_string, Amount &nRet) {
38  if (!ValidAsCString(money_string)) {
39  return false;
40  }
41  const std::string str = TrimString(money_string);
42  if (str.empty()) {
43  return false;
44  }
45 
46  const auto &currency = Currency::get();
47  std::string strWhole;
48  Amount nUnits = Amount::zero();
49  const char *p = str.c_str();
50  for (; *p; p++) {
51  if (*p == '.') {
52  p++;
53  Amount nMult = currency.baseunit / 10;
54  while (IsDigit(*p) && (nMult > Amount::zero())) {
55  nUnits += (*p++ - '0') * nMult;
56  nMult /= 10;
57  }
58  break;
59  }
60  if (IsSpace(*p)) {
61  return false;
62  }
63  if (!IsDigit(*p)) {
64  return false;
65  }
66  strWhole.insert(strWhole.end(), *p);
67  }
68  if (*p) {
69  return false;
70  }
71 
72  // Make sure the following overflow check is meaningful. It's fine to assert
73  // because it's on no critical path, and it's very unlikely to support a 19
74  // decimal (or more) currency anyway.
75  assert(currency.decimals <= 18);
76 
77  // guard against 63 bit overflow
78  if (strWhole.size() > (size_t(18) - currency.decimals)) {
79  return false;
80  }
81  if (nUnits < Amount::zero() || nUnits > currency.baseunit) {
82  return false;
83  }
84 
85  Amount nWhole = atoi64(strWhole) * currency.baseunit;
86 
87  nRet = nWhole + Amount(nUnits);
88  return true;
89 }
std::string FormatMoney(const Amount amt)
Do not use these functions to represent or parse monetary amounts to or from JSON but use AmountFromV...
Definition: moneystr.cpp:13
bool ParseMoney(const std::string &money_string, Amount &nRet)
Parse an amount denoted in full coins.
Definition: moneystr.cpp:37
int64_t atoi64(const std::string &str)
constexpr bool IsDigit(char c)
Tests if the given character is a decimal digit.
Definition: strencodings.h:88
constexpr bool IsSpace(char c) noexcept
Tests if the given character is a whitespace character.
Definition: strencodings.h:104
bool ValidAsCString(const std::string &str) noexcept
Check if a string does not contain any embedded NUL (\0) characters.
Definition: string.h:80
std::string TrimString(const std::string &str, const std::string &pattern=" \f\n\r\t\v")
Definition: string.h:29
Definition: amount.h:19
static constexpr Amount zero() noexcept
Definition: amount.h:32
static const Currency & get()
Definition: amount.cpp:18
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
assert(!tx.IsCoinBase())