mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-15 22:32:37 -03:00
816e15ee81
9d0379cea6
consensus: use <cstdint> over <stdint.h> in amount.h (fanquake)863e52fe63
consensus: make COIN & MAX_MONEY constexpr (fanquake)d09071da5b
[MOVEONLY] consensus: move amount.h into consensus (fanquake) Pull request description: A first step (of a few) towards some source code reorganization, as well as making libbitcoinconsensus slightly more self contained. Related to #15732. ACKs for top commit: MarcoFalke: concept ACK9d0379cea6
🏝 Tree-SHA512: 97fc79262dcb8c00996852a288fee69ddf8398ae2c95700bba5b326f1f38ffcfaf8fa66e29d0cb446d9b3f4e608a96525fae0c2ad9cd531ad98ad2a4a687cd6a
88 lines
2.3 KiB
C++
88 lines
2.3 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-2020 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include <util/moneystr.h>
|
|
|
|
#include <consensus/amount.h>
|
|
#include <tinyformat.h>
|
|
#include <util/strencodings.h>
|
|
#include <util/string.h>
|
|
|
|
#include <optional>
|
|
|
|
std::string FormatMoney(const CAmount n)
|
|
{
|
|
// Note: not using straight sprintf here because we do NOT want
|
|
// localized number formatting.
|
|
static_assert(COIN > 1);
|
|
int64_t quotient = n / COIN;
|
|
int64_t remainder = n % COIN;
|
|
if (n < 0) {
|
|
quotient = -quotient;
|
|
remainder = -remainder;
|
|
}
|
|
std::string str = strprintf("%d.%08d", quotient, remainder);
|
|
|
|
// Right-trim excess zeros before the decimal point:
|
|
int nTrim = 0;
|
|
for (int i = str.size()-1; (str[i] == '0' && IsDigit(str[i-2])); --i)
|
|
++nTrim;
|
|
if (nTrim)
|
|
str.erase(str.size()-nTrim, nTrim);
|
|
|
|
if (n < 0)
|
|
str.insert((unsigned int)0, 1, '-');
|
|
return str;
|
|
}
|
|
|
|
|
|
std::optional<CAmount> ParseMoney(const std::string& money_string)
|
|
{
|
|
if (!ValidAsCString(money_string)) {
|
|
return std::nullopt;
|
|
}
|
|
const std::string str = TrimString(money_string);
|
|
if (str.empty()) {
|
|
return std::nullopt;
|
|
}
|
|
|
|
std::string strWhole;
|
|
int64_t nUnits = 0;
|
|
const char* p = str.c_str();
|
|
for (; *p; p++)
|
|
{
|
|
if (*p == '.')
|
|
{
|
|
p++;
|
|
int64_t nMult = COIN / 10;
|
|
while (IsDigit(*p) && (nMult > 0))
|
|
{
|
|
nUnits += nMult * (*p++ - '0');
|
|
nMult /= 10;
|
|
}
|
|
break;
|
|
}
|
|
if (IsSpace(*p))
|
|
return std::nullopt;
|
|
if (!IsDigit(*p))
|
|
return std::nullopt;
|
|
strWhole.insert(strWhole.end(), *p);
|
|
}
|
|
if (*p) {
|
|
return std::nullopt;
|
|
}
|
|
if (strWhole.size() > 10) // guard against 63 bit overflow
|
|
return std::nullopt;
|
|
if (nUnits < 0 || nUnits > COIN)
|
|
return std::nullopt;
|
|
int64_t nWhole = LocaleIndependentAtoi<int64_t>(strWhole);
|
|
CAmount value = nWhole * COIN + nUnits;
|
|
|
|
if (!MoneyRange(value)) {
|
|
return std::nullopt;
|
|
}
|
|
|
|
return value;
|
|
}
|