LCOV - code coverage report
Current view: top level - src/util - moneystr.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 96.0 % 50 48
Test Date: 2024-12-04 04:00:22 Functions: 100.0 % 2 2
Branches: 88.1 % 42 37

             Branch data     Line data    Source code
       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                 :             : using util::ContainsNoNUL;
      17                 :             : using util::TrimString;
      18                 :             : 
      19                 :     1432931 : std::string FormatMoney(const CAmount n)
      20                 :             : {
      21                 :             :     // Note: not using straight sprintf here because we do NOT want
      22                 :             :     // localized number formatting.
      23                 :     1432931 :     static_assert(COIN > 1);
      24                 :     1432931 :     int64_t quotient = n / COIN;
      25                 :     1432931 :     int64_t remainder = n % COIN;
      26         [ +  + ]:     1432931 :     if (n < 0) {
      27                 :      394995 :         quotient = -quotient;
      28                 :      394995 :         remainder = -remainder;
      29                 :             :     }
      30                 :     1432931 :     std::string str = strprintf("%d.%08d", quotient, remainder);
      31                 :             : 
      32                 :             :     // Right-trim excess zeros before the decimal point:
      33                 :     1432931 :     int nTrim = 0;
      34   [ +  +  +  + ]:     1712064 :     for (int i = str.size()-1; (str[i] == '0' && IsDigit(str[i-2])); --i)
      35                 :      279133 :         ++nTrim;
      36         [ +  + ]:     1432931 :     if (nTrim)
      37         [ +  - ]:      169321 :         str.erase(str.size()-nTrim, nTrim);
      38                 :             : 
      39         [ +  + ]:     1432931 :     if (n < 0)
      40         [ +  - ]:      394995 :         str.insert(uint32_t{0}, 1, '-');
      41                 :     1432931 :     return str;
      42                 :           0 : }
      43                 :             : 
      44                 :             : 
      45                 :         489 : std::optional<CAmount> ParseMoney(const std::string& money_string)
      46                 :             : {
      47         [ +  + ]:         978 :     if (!ContainsNoNUL(money_string)) {
      48                 :          12 :         return std::nullopt;
      49                 :             :     }
      50                 :         477 :     const std::string str = TrimString(money_string);
      51         [ +  + ]:         477 :     if (str.empty()) {
      52                 :           3 :         return std::nullopt;
      53                 :             :     }
      54                 :             : 
      55                 :         474 :     std::string strWhole;
      56                 :         474 :     int64_t nUnits = 0;
      57                 :         474 :     const char* p = str.c_str();
      58         [ +  + ]:     2141609 :     for (; *p; p++)
      59                 :             :     {
      60         [ +  + ]:     2141575 :         if (*p == '.')
      61                 :             :         {
      62                 :         159 :             p++;
      63                 :         159 :             int64_t nMult = COIN / 10;
      64   [ +  +  +  + ]:        1229 :             while (IsDigit(*p) && (nMult > 0))
      65                 :             :             {
      66                 :        1070 :                 nUnits += nMult * (*p++ - '0');
      67                 :        1070 :                 nMult /= 10;
      68                 :             :             }
      69                 :             :             break;
      70                 :             :         }
      71         [ +  + ]:     2141416 :         if (IsSpace(*p))
      72                 :          11 :             return std::nullopt;
      73         [ +  + ]:     2141405 :         if (!IsDigit(*p))
      74                 :         270 :             return std::nullopt;
      75         [ +  - ]:     2141135 :         strWhole.insert(strWhole.end(), *p);
      76                 :             :     }
      77         [ +  + ]:         193 :     if (*p) {
      78                 :          27 :         return std::nullopt;
      79                 :             :     }
      80         [ +  + ]:         166 :     if (strWhole.size() > 10) // guard against 63 bit overflow
      81                 :          76 :         return std::nullopt;
      82         [ -  + ]:          90 :     if (nUnits < 0 || nUnits > COIN)
      83                 :           0 :         return std::nullopt;
      84         [ +  - ]:          90 :     int64_t nWhole = LocaleIndependentAtoi<int64_t>(strWhole);
      85                 :          90 :     CAmount value = nWhole * COIN + nUnits;
      86                 :             : 
      87         [ +  + ]:          90 :     if (!MoneyRange(value)) {
      88                 :          21 :         return std::nullopt;
      89                 :             :     }
      90                 :             : 
      91                 :          69 :     return value;
      92                 :         951 : }
        

Generated by: LCOV version 2.0-1