Bitcoin ABC 0.30.7
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
13std::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
37bool ParseMoney(const std::string &money_string, Amount &nRet) {
38 if (!ContainsNoNUL(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
constexpr bool IsDigit(char c)
Tests if the given character is a decimal digit.
Definition: strencodings.h:98
constexpr bool IsSpace(char c) noexcept
Tests if the given character is a whitespace character.
Definition: strencodings.h:114
std::string TrimString(std::string_view str, std::string_view pattern=" \f\n\r\t\v")
Definition: string.h:38
bool ContainsNoNUL(std::string_view str) noexcept
Check if a string does not contain any embedded NUL (\0) characters.
Definition: string.h:90
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
int64_t atoi64(const std::string &str)
assert(!tx.IsCoinBase())