Bitcoin Core  27.99.0
P2P Digital Currency
moneystr.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2022 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 #include <cstdint>
14 #include <optional>
15 
16 std::string FormatMoney(const CAmount n)
17 {
18  // Note: not using straight sprintf here because we do NOT want
19  // localized number formatting.
20  static_assert(COIN > 1);
21  int64_t quotient = n / COIN;
22  int64_t remainder = n % COIN;
23  if (n < 0) {
24  quotient = -quotient;
25  remainder = -remainder;
26  }
27  std::string str = strprintf("%d.%08d", quotient, remainder);
28 
29  // Right-trim excess zeros before the decimal point:
30  int nTrim = 0;
31  for (int i = str.size()-1; (str[i] == '0' && IsDigit(str[i-2])); --i)
32  ++nTrim;
33  if (nTrim)
34  str.erase(str.size()-nTrim, nTrim);
35 
36  if (n < 0)
37  str.insert(uint32_t{0}, 1, '-');
38  return str;
39 }
40 
41 
42 std::optional<CAmount> ParseMoney(const std::string& money_string)
43 {
44  if (!ContainsNoNUL(money_string)) {
45  return std::nullopt;
46  }
47  const std::string str = TrimString(money_string);
48  if (str.empty()) {
49  return std::nullopt;
50  }
51 
52  std::string strWhole;
53  int64_t nUnits = 0;
54  const char* p = str.c_str();
55  for (; *p; p++)
56  {
57  if (*p == '.')
58  {
59  p++;
60  int64_t nMult = COIN / 10;
61  while (IsDigit(*p) && (nMult > 0))
62  {
63  nUnits += nMult * (*p++ - '0');
64  nMult /= 10;
65  }
66  break;
67  }
68  if (IsSpace(*p))
69  return std::nullopt;
70  if (!IsDigit(*p))
71  return std::nullopt;
72  strWhole.insert(strWhole.end(), *p);
73  }
74  if (*p) {
75  return std::nullopt;
76  }
77  if (strWhole.size() > 10) // guard against 63 bit overflow
78  return std::nullopt;
79  if (nUnits < 0 || nUnits > COIN)
80  return std::nullopt;
81  int64_t nWhole = LocaleIndependentAtoi<int64_t>(strWhole);
82  CAmount value = nWhole * COIN + nUnits;
83 
84  if (!MoneyRange(value)) {
85  return std::nullopt;
86  }
87 
88  return value;
89 }
bool MoneyRange(const CAmount &nValue)
Definition: amount.h:27
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
static constexpr CAmount COIN
The amount of satoshis in one BTC.
Definition: amount.h:15
std::string FormatMoney(const CAmount n)
Money parsing/formatting utilities.
Definition: moneystr.cpp:16
std::optional< CAmount > ParseMoney(const std::string &money_string)
Parse an amount denoted in full coins.
Definition: moneystr.cpp:42
constexpr bool IsDigit(char c)
Tests if the given character is a decimal digit.
Definition: strencodings.h:152
constexpr bool IsSpace(char c) noexcept
Tests if the given character is a whitespace character.
Definition: strencodings.h:168
std::string TrimString(std::string_view str, std::string_view pattern=" \f\n\r\t\v")
Definition: string.h:41
bool ContainsNoNUL(std::string_view str) noexcept
Check if a string does not contain any embedded NUL (\0) characters.
Definition: string.h:98
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1162