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 <tinyformat.h>
9 #include <util/strencodings.h>
10 #include <util/string.h>
11 
FormatMoney(const CAmount & n)12 std::string FormatMoney(const CAmount& n)
13 {
14     // Note: not using straight sprintf here because we do NOT want
15     // localized number formatting.
16     int64_t n_abs = (n > 0 ? n : -n);
17     int64_t quotient = n_abs/COIN;
18     int64_t remainder = n_abs%COIN;
19     std::string str = strprintf("%d.%08d", quotient, remainder);
20 
21     // Right-trim excess zeros before the decimal point:
22     int nTrim = 0;
23     for (int i = str.size()-1; (str[i] == '0' && IsDigit(str[i-2])); --i)
24         ++nTrim;
25     if (nTrim)
26         str.erase(str.size()-nTrim, nTrim);
27 
28     if (n < 0)
29         str.insert((unsigned int)0, 1, '-');
30     return str;
31 }
32 
33 
ParseMoney(const std::string & money_string,CAmount & nRet)34 bool ParseMoney(const std::string& money_string, CAmount& nRet)
35 {
36     if (!ValidAsCString(money_string)) {
37         return false;
38     }
39     const std::string str = TrimString(money_string);
40     if (str.empty()) {
41         return false;
42     }
43 
44     std::string strWhole;
45     int64_t nUnits = 0;
46     const char* p = str.c_str();
47     for (; *p; p++)
48     {
49         if (*p == '.')
50         {
51             p++;
52             int64_t nMult = COIN / 10;
53             while (IsDigit(*p) && (nMult > 0))
54             {
55                 nUnits += nMult * (*p++ - '0');
56                 nMult /= 10;
57             }
58             break;
59         }
60         if (IsSpace(*p))
61             return false;
62         if (!IsDigit(*p))
63             return false;
64         strWhole.insert(strWhole.end(), *p);
65     }
66     if (*p) {
67         return false;
68     }
69     if (strWhole.size() > 10) // guard against 63 bit overflow
70         return false;
71     if (nUnits < 0 || nUnits > COIN)
72         return false;
73     int64_t nWhole = atoi64(strWhole);
74     CAmount nValue = nWhole*COIN + nUnits;
75 
76     nRet = nValue;
77     return true;
78 }
79