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