forked from lthn/blockchain
added decimal point support to currency::parse_amount() + minor refactoring
This commit is contained in:
parent
9150c31666
commit
b6e84b460e
6 changed files with 121 additions and 60 deletions
|
|
@ -793,8 +793,7 @@ namespace currency
|
|||
}
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// TODO: reverse order of arguments
|
||||
bool parse_amount(uint64_t& amount, const std::string& str_amount_)
|
||||
bool parse_amount(const std::string& str_amount_, uint64_t& amount, const size_t decimal_point /* = CURRENCY_DISPLAY_DECIMAL_POINT */)
|
||||
{
|
||||
std::string str_amount = str_amount_;
|
||||
boost::algorithm::trim(str_amount);
|
||||
|
|
@ -804,12 +803,12 @@ namespace currency
|
|||
if (std::string::npos != point_index)
|
||||
{
|
||||
fraction_size = str_amount.size() - point_index - 1;
|
||||
while (CURRENCY_DISPLAY_DECIMAL_POINT < fraction_size && '0' == str_amount.back())
|
||||
while (decimal_point < fraction_size && '0' == str_amount.back())
|
||||
{
|
||||
str_amount.erase(str_amount.size() - 1, 1);
|
||||
--fraction_size;
|
||||
}
|
||||
if (CURRENCY_DISPLAY_DECIMAL_POINT < fraction_size)
|
||||
if (decimal_point < fraction_size)
|
||||
return false;
|
||||
str_amount.erase(point_index, 1);
|
||||
}
|
||||
|
|
@ -821,9 +820,9 @@ namespace currency
|
|||
if (str_amount.empty())
|
||||
return false;
|
||||
|
||||
if (fraction_size < CURRENCY_DISPLAY_DECIMAL_POINT)
|
||||
if (fraction_size < decimal_point)
|
||||
{
|
||||
str_amount.append(CURRENCY_DISPLAY_DECIMAL_POINT - fraction_size, '0');
|
||||
str_amount.append(decimal_point - fraction_size, '0');
|
||||
}
|
||||
|
||||
return string_tools::get_xtype_from_string(amount, str_amount);
|
||||
|
|
|
|||
|
|
@ -402,7 +402,7 @@ namespace currency
|
|||
uint64_t get_outs_money_amount(const transaction& tx, const currency::account_keys& acc_keys_for_hidden_amounts = currency::null_acc_keys);
|
||||
bool check_inputs_types_supported(const transaction& tx);
|
||||
bool check_outs_valid(const transaction& tx);
|
||||
bool parse_amount(uint64_t& amount, const std::string& str_amount);
|
||||
bool parse_amount(const std::string& str_amount, uint64_t& amount, const size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT);
|
||||
bool parse_tracking_seed(const std::string& tracking_seed, account_public_address& address, crypto::secret_key& view_sec_key, uint64_t& creation_timestamp);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2592,7 +2592,7 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args)
|
|||
}
|
||||
|
||||
uint64_t amount = 0;
|
||||
r = currency::parse_amount(amount, args[2]);
|
||||
r = currency::parse_amount(args[2], amount);
|
||||
if (!r || amount == 0)
|
||||
{
|
||||
fail_msg_writer() << "incorrect amount: " << args[2];
|
||||
|
|
@ -3127,7 +3127,7 @@ int main(int argc, char* argv[])
|
|||
uint64_t max_amount = 0;
|
||||
CHECK_AND_ASSERT_MES(epee::string_tools::string_to_num_fast(params[0], outs_min) && outs_min > 0 && outs_min < 256, EXIT_FAILURE, "incorrect param: " << params[0]);
|
||||
CHECK_AND_ASSERT_MES(epee::string_tools::string_to_num_fast(params[1], outs_max) && outs_max > 0 && outs_max < 256, EXIT_FAILURE, "incorrect param: " << params[1]);
|
||||
CHECK_AND_ASSERT_MES(currency::parse_amount(max_amount, params[2]), EXIT_FAILURE, "incorrect param: " << params[2]);
|
||||
CHECK_AND_ASSERT_MES(currency::parse_amount(params[2], max_amount), EXIT_FAILURE, "incorrect param: " << params[2]);
|
||||
wal.set_defragmentation_tx_settings(true, outs_min, outs_max, max_amount);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1539,7 +1539,7 @@ std::string wallets_manager::transfer(uint64_t wallet_id, const view::transfer_p
|
|||
}
|
||||
|
||||
|
||||
if(!currency::parse_amount(dsts.back().amount, d.amount))
|
||||
if(!currency::parse_amount(d.amount, dsts.back().amount))
|
||||
{
|
||||
return API_RETURN_CODE_BAD_ARG_WRONG_AMOUNT;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2022 Zano Project
|
||||
// Copyright (c) 2022-2024 Zano Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
@ -10,23 +10,23 @@ using namespace currency;
|
|||
|
||||
namespace
|
||||
{
|
||||
void do_pos_test(uint64_t expected, const std::string& str)
|
||||
void do_pos_test(uint64_t expected, const std::string& str, size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT)
|
||||
{
|
||||
uint64_t val;
|
||||
std::string number_str = str;
|
||||
std::replace(number_str.begin(), number_str.end(), '_', '.');
|
||||
number_str.erase(std::remove(number_str.begin(), number_str.end(), '~'), number_str.end());
|
||||
ASSERT_TRUE(parse_amount(val, number_str));
|
||||
ASSERT_TRUE(parse_amount(number_str, val, decimal_point));
|
||||
ASSERT_EQ(expected, val);
|
||||
}
|
||||
|
||||
void do_neg_test(const std::string& str)
|
||||
void do_neg_test(const std::string& str, size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT)
|
||||
{
|
||||
uint64_t val;
|
||||
std::string number_str = str;
|
||||
std::replace(number_str.begin(), number_str.end(), '_', '.');
|
||||
number_str.erase(std::remove(number_str.begin(), number_str.end(), '~'), number_str.end());
|
||||
ASSERT_FALSE(parse_amount(val, number_str));
|
||||
ASSERT_FALSE(parse_amount(number_str, val, decimal_point));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,6 +48,23 @@ namespace
|
|||
do_neg_test(#str); \
|
||||
}
|
||||
|
||||
#define TEST_pos_dp(expected, str, decimal_point) \
|
||||
TEST(parse_amount, handles_pos_ ## str ## _dp ## decimal_point) \
|
||||
{ \
|
||||
do_pos_test(UINT64_C(expected), #str, decimal_point); \
|
||||
}
|
||||
|
||||
#define TEST_neg_dp(str, decimal_point) \
|
||||
TEST(parse_amount, handles_neg_ ## str ## _dp ## decimal_point) \
|
||||
{ \
|
||||
do_neg_test(#str, decimal_point); \
|
||||
}
|
||||
|
||||
#define TEST_neg_n_dp(str, name, decimal_point) \
|
||||
TEST(parse_amount, handles_neg_ ## name ## _dp ## decimal_point) \
|
||||
{ \
|
||||
do_neg_test(#str, decimal_point); \
|
||||
}
|
||||
|
||||
TEST_pos(0, 0);
|
||||
TEST_pos(0, 00);
|
||||
|
|
@ -96,6 +113,44 @@ TEST_pos(18446744073700000000, 18446744_0737000000000);
|
|||
TEST_pos(18446744073700000000, 18446744_07370000000000000000000);
|
||||
TEST_pos(18446744073709551615, 18446744_073709551615);
|
||||
|
||||
// non-standard decimal point
|
||||
TEST_pos_dp(0, 0_0, 3);
|
||||
TEST_pos_dp(0, 00_0, 3);
|
||||
TEST_pos_dp(0, 00_00, 3);
|
||||
TEST_pos_dp(0, 00000000_00, 3);
|
||||
TEST_pos_dp(0, 00_000000000, 3);
|
||||
TEST_pos_dp(0, 00_00000000000000000000000000000000, 3);
|
||||
|
||||
TEST_pos_dp( 65535, 65535, 0);
|
||||
TEST_pos_dp( 6553500, 65535, 2);
|
||||
TEST_pos_dp( 65535000000, 65535, 6);
|
||||
TEST_pos_dp( 18000000000000000000, 18, 18);
|
||||
TEST_pos_dp( 1, 0_1, 1);
|
||||
TEST_pos_dp( 10, 0_1, 2);
|
||||
TEST_pos_dp( 100, 0_1, 3);
|
||||
TEST_pos_dp( 10000000000000000000, 0_1, 20);
|
||||
TEST_pos_dp( 1, 0_001, 3);
|
||||
TEST_pos_dp( 123, 0_123, 3);
|
||||
TEST_pos_dp( 1230, 0_123, 4);
|
||||
TEST_pos_dp( 12300, 0_123, 5);
|
||||
TEST_pos_dp( 123000, 0_123, 6);
|
||||
|
||||
TEST_pos_dp(18446744073709551615, 18446744073709551615, 0);
|
||||
TEST_pos_dp(18446744073709551615, 18446744073709551615_0, 0);
|
||||
|
||||
TEST_pos_dp(18446744073709551615, 1844674407370955161_5, 1);
|
||||
TEST_pos_dp(18446744073709551615, 1844674407370955161_50, 1);
|
||||
|
||||
TEST_pos_dp(18446744073709551615, 18446744073709551_615, 3);
|
||||
TEST_pos_dp(18446744073709551615, 18446744073709551_615000, 3);
|
||||
|
||||
TEST_pos_dp(18446744073709551615, 1_8446744073709551615, 19);
|
||||
TEST_pos_dp(18446744073709551615, 1_844674407370955161500, 19);
|
||||
|
||||
TEST_pos_dp(18446744073709551615, 0_18446744073709551615, 20);
|
||||
TEST_pos_dp(18446744073709551615, 0_1844674407370955161500, 20);
|
||||
|
||||
|
||||
// Invalid numbers
|
||||
TEST_neg_n(~, empty_string);
|
||||
TEST_neg_n(-0, minus_0);
|
||||
|
|
@ -109,10 +164,17 @@ TEST_neg(0_0000000000001);
|
|||
TEST_neg(0_0000000000009);
|
||||
TEST_neg(18446744_0737000000001);
|
||||
|
||||
TEST_neg_dp(00_184467440737095516150001, 20);
|
||||
TEST_neg_dp(00_184467440737095516151, 20);
|
||||
TEST_neg_dp(1_2, 0);
|
||||
|
||||
// Overflow
|
||||
TEST_neg(184467440737_09551616);
|
||||
TEST_neg(184467440738);
|
||||
TEST_neg(18446744073709551616);
|
||||
TEST_neg_dp(18446744073709551616, 0);
|
||||
TEST_neg_dp(1844674407370955161_60, 1);
|
||||
TEST_neg_dp(0_18446744073709551616, 20);
|
||||
|
||||
// Two or more points
|
||||
TEST_neg(__);
|
||||
|
|
@ -123,6 +185,51 @@ TEST_neg(0_0_);
|
|||
TEST_neg(_0_0);
|
||||
TEST_neg(0_0_0);
|
||||
|
||||
// moved from test_format_utils.cpp
|
||||
TEST(validate_parse_amount_case, validate_parse_amount)
|
||||
{
|
||||
uint64_t res = 0;
|
||||
bool r = currency::parse_amount("0.0001", res);
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(res, 100000000);
|
||||
|
||||
r = currency::parse_amount("100.0001", res);
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(res, 100000100000000);
|
||||
|
||||
r = currency::parse_amount("000.0000", res);
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(res, 0);
|
||||
|
||||
r = currency::parse_amount("0", res);
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(res, 0);
|
||||
|
||||
|
||||
r = currency::parse_amount(" 100.0001 ", res);
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(res, 100000100000000);
|
||||
|
||||
r = currency::parse_amount(" 100.0000 ", res);
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(res, 100000000000000);
|
||||
|
||||
r = currency::parse_amount(" 100. 0000 ", res);
|
||||
ASSERT_FALSE(r);
|
||||
|
||||
r = currency::parse_amount("100. 0000", res);
|
||||
ASSERT_FALSE(r);
|
||||
|
||||
r = currency::parse_amount("100 . 0000", res);
|
||||
ASSERT_FALSE(r);
|
||||
|
||||
r = currency::parse_amount("100.00 00", res);
|
||||
ASSERT_FALSE(r);
|
||||
|
||||
r = currency::parse_amount("1 00.00 00", res);
|
||||
ASSERT_FALSE(r);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
|||
|
|
@ -125,48 +125,3 @@ void force_random(forced_to_pod_t& o)
|
|||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
TEST(validate_parse_amount_case, validate_parse_amount)
|
||||
{
|
||||
uint64_t res = 0;
|
||||
bool r = currency::parse_amount(res, "0.0001");
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(res, 100000000);
|
||||
|
||||
r = currency::parse_amount(res, "100.0001");
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(res, 100000100000000);
|
||||
|
||||
r = currency::parse_amount(res, "000.0000");
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(res, 0);
|
||||
|
||||
r = currency::parse_amount(res, "0");
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(res, 0);
|
||||
|
||||
|
||||
r = currency::parse_amount(res, " 100.0001 ");
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(res, 100000100000000);
|
||||
|
||||
r = currency::parse_amount(res, " 100.0000 ");
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(res, 100000000000000);
|
||||
|
||||
r = currency::parse_amount(res, " 100. 0000 ");
|
||||
ASSERT_FALSE(r);
|
||||
|
||||
r = currency::parse_amount(res, "100. 0000");
|
||||
ASSERT_FALSE(r);
|
||||
|
||||
r = currency::parse_amount(res, "100 . 0000");
|
||||
ASSERT_FALSE(r);
|
||||
|
||||
r = currency::parse_amount(res, "100.00 00");
|
||||
ASSERT_FALSE(r);
|
||||
|
||||
r = currency::parse_amount(res, "1 00.00 00");
|
||||
ASSERT_FALSE(r);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue