Skip to content

Commit 1883b22

Browse files
committed
Merge pull request #180 from dexX7/mcore-strtoint64
Extract, move and test StrToInt64
2 parents a577881 + 8ca1427 commit 1883b22

10 files changed

Lines changed: 173 additions & 250 deletions

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ BITCOIN_CORE_H = \
3939
compat.h \
4040
core.h \
4141
mastercore.h \
42+
mastercore_parse_string.h \
4243
mastercore_tx.h \
4344
mastercore_dex.h \
4445
mastercore_sp.h \
@@ -131,6 +132,7 @@ libbitcoin_common_a_SOURCES = \
131132
chainparams.cpp \
132133
core.cpp \
133134
mastercore.cpp \
135+
mastercore_parse_string.cpp \
134136
mastercore_tx.cpp \
135137
mastercore_rpc.cpp \
136138
mastercore_dex.cpp \

src/mastercore.cpp

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -328,56 +328,6 @@ std::string FormatMP(unsigned int property, int64_t n, bool fSign)
328328
else return FormatIndivisibleMP(n);
329329
}
330330

331-
int64_t mastercore::strToInt64(std::string strAmount, bool divisible)
332-
{
333-
int64_t Amount = 0;
334-
335-
//check for a negative (minus sign) and invalidate if present
336-
size_t negSignPos = strAmount.find("-");
337-
if (negSignPos!=std::string::npos) return 0;
338-
339-
//convert the string into a usable int64
340-
if (divisible)
341-
{
342-
//check for existance of decimal point
343-
size_t pos = strAmount.find(".");
344-
if (pos==std::string::npos)
345-
{ //no decimal point but divisible so pad 8 zeros on right
346-
strAmount+="00000000";
347-
}
348-
else
349-
{
350-
size_t posSecond = strAmount.find(".", pos+1); //check for existence of second decimal point, if so invalidate amount
351-
if (posSecond!=std::string::npos) return 0;
352-
if ((strAmount.size()-pos)<9)
353-
{ //there are decimals either exact or not enough, pad as needed
354-
string strRightOfDecimal = strAmount.substr(pos+1);
355-
unsigned int zerosToPad = 8-strRightOfDecimal.size();
356-
if (zerosToPad>0) //do we need to pad?
357-
{
358-
for(unsigned int it = 0; it != zerosToPad; it++)
359-
{
360-
strAmount+="0";
361-
}
362-
}
363-
}
364-
else
365-
{ //there are too many decimals, truncate after 8
366-
strAmount = strAmount.substr(0,pos+9);
367-
}
368-
}
369-
strAmount.erase(std::remove(strAmount.begin(), strAmount.end(), '.'), strAmount.end());
370-
try { Amount = boost::lexical_cast<int64_t>(strAmount); } catch(const boost::bad_lexical_cast &e) { }
371-
}
372-
else
373-
{
374-
size_t pos = strAmount.find(".");
375-
string newStrAmount = strAmount.substr(0,pos);
376-
try { Amount = boost::lexical_cast<int64_t>(newStrAmount); } catch(const boost::bad_lexical_cast &e) { }
377-
}
378-
return Amount;
379-
}
380-
381331
string const CMPSPInfo::watermarkKey("watermark");
382332

383333
CCriticalSection cs_tally;

src/mastercore.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,6 @@ uint256 send_INTERNAL_1packet(const string &FromAddress, const string &ToAddress
397397
unsigned int TransactionType, int64_t additional, int *error_code = NULL);
398398

399399
bool isTestEcosystemProperty(unsigned int property);
400-
int64_t strToInt64(std::string strAmount, bool divisible);
401400

402401
CMPTally *getTally(const string & address);
403402

src/mastercore_parse_string.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#include "mastercore_parse_string.h"
2+
3+
#include <stdint.h>
4+
#include <algorithm>
5+
#include <string>
6+
7+
#include <boost/lexical_cast.hpp>
8+
9+
namespace mastercore
10+
{
11+
int64_t StrToInt64(const std::string& str, bool divisible)
12+
{
13+
// copy original, so it remains unchanged
14+
std::string strAmount (str);
15+
int64_t nAmount = 0;
16+
17+
// check for a negative (minus sign) and invalidate if present
18+
size_t negSignPos = strAmount.find("-");
19+
if (negSignPos != std::string::npos) return 0;
20+
21+
// convert the string into a usable int64
22+
if (divisible) {
23+
// check for existance of decimal point
24+
size_t pos = strAmount.find(".");
25+
if (pos == std::string::npos) {
26+
// no decimal point but divisible so pad 8 zeros on right
27+
strAmount += "00000000";
28+
} else {
29+
// check for existence of second decimal point, if so invalidate amount
30+
size_t posSecond = strAmount.find(".", pos + 1);
31+
if (posSecond != std::string::npos) return 0;
32+
33+
if ((strAmount.size() - pos) < 9) {
34+
// there are decimals either exact or not enough, pad as needed
35+
std::string strRightOfDecimal = strAmount.substr(pos + 1);
36+
unsigned int zerosToPad = 8 - strRightOfDecimal.size();
37+
38+
// do we need to pad?
39+
if (zerosToPad > 0)
40+
{
41+
for (unsigned int it = 0; it != zerosToPad; it++) {
42+
strAmount += "0";
43+
}
44+
}
45+
} else {
46+
// there are too many decimals, truncate after 8
47+
strAmount = strAmount.substr(0, pos + 9);
48+
}
49+
}
50+
strAmount.erase(std::remove(strAmount.begin(), strAmount.end(), '.'), strAmount.end());
51+
try {
52+
nAmount = boost::lexical_cast<int64_t>(strAmount);
53+
} catch (const boost::bad_lexical_cast &e) {}
54+
} else {
55+
size_t pos = strAmount.find(".");
56+
std::string newStrAmount = strAmount.substr(0, pos);
57+
try {
58+
nAmount = boost::lexical_cast<int64_t>(newStrAmount);
59+
} catch (const boost::bad_lexical_cast &e) {}
60+
}
61+
62+
return nAmount;
63+
}
64+
} // namespace mastercore

src/mastercore_parse_string.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef _MASTERCOIN_PARSE_STRING
2+
#define _MASTERCOIN_PARSE_STRING
3+
4+
#include <stdint.h>
5+
#include <string>
6+
7+
namespace mastercore
8+
{
9+
// Converts strings to 64 bit wide interger.
10+
// Divisible and indivisible amounts are accepted.
11+
// 1 indivisible unit equals 0.00000001 divisible units.
12+
// If input string is not a accepted number, 0 is returned.
13+
// Divisible amounts are truncated after 8 decimal places.
14+
// Characters after decimal mark are ignored for indivisible
15+
// amounts.
16+
// Any minus sign invalidates.
17+
int64_t StrToInt64(const std::string& str, bool divisible);
18+
}
19+
20+
#endif // _MASTERCOIN_PARSE_STRRING

src/mastercore_rpc.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ using namespace json_spirit;
3535
using namespace mastercore;
3636

3737
#include "mastercore_dex.h"
38+
#include "mastercore_parse_string.h"
3839
#include "mastercore_tx.h"
3940
#include "mastercore_sp.h"
4041
#include "mastercore_errors.h"
@@ -221,13 +222,13 @@ if (fHelp || params.size() < 4 || params.size() > 6)
221222

222223
string strAmount = params[3].get_str();
223224
int64_t Amount = 0, additional = 0;
224-
Amount = strToInt64(strAmount, divisible);
225+
Amount = StrToInt64(strAmount, divisible);
225226

226227
if (0 >= Amount)
227228
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
228229

229230
std::string strAdditional = (params.size() > 5) ? (params[5].get_str()): "0";
230-
additional = strToInt64(strAdditional, true);
231+
additional = StrToInt64(strAdditional, true);
231232

232233
int n = params.size();
233234
printf("#: %d, additional= %ld\n", n, additional);
@@ -284,7 +285,7 @@ if (fHelp || params.size() < 3 || params.size() > 4)
284285

285286
string strAmount = params[2].get_str();
286287
int64_t Amount = 0;
287-
Amount = strToInt64(strAmount, divisible);
288+
Amount = StrToInt64(strAmount, divisible);
288289

289290
if (0 >= Amount)
290291
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
@@ -328,7 +329,7 @@ if (fHelp || params.size() < 2 || params.size() > 5)
328329
int64_t referenceAmount = 0;
329330

330331
if (params.size() > 4)
331-
referenceAmount = strToInt64(params[4].get_str(), true);
332+
referenceAmount = StrToInt64(params[4].get_str(), true);
332333

333334
//some sanity checking of the data supplied?
334335
uint256 newTX;
@@ -1092,11 +1093,11 @@ Value trade_MP(const Array& params, bool fHelp) {
10921093

10931094
std::string strAmountSale = params[1].get_str();
10941095
int64_t Amount_Sale = 0;
1095-
Amount_Sale = strToInt64(strAmountSale, divisible_sale);
1096+
Amount_Sale = StrToInt64(strAmountSale, divisible_sale);
10961097

10971098
std::string strAmountWant = params[3].get_str();
10981099
int64_t Amount_Want = 0;
1099-
Amount_Want = strToInt64(strAmountWant, divisible_want);
1100+
Amount_Want = StrToInt64(strAmountWant, divisible_want);
11001101

11011102
if (0 >= Amount_Sale)
11021103
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount (Sale)");

src/qt/sendmpdialog.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ using namespace leveldb;
5656
// end potentially overzealous using
5757

5858
#include "mastercore_dex.h"
59+
#include "mastercore_parse_string.h"
5960
#include "mastercore_tx.h"
6061
#include "mastercore_sp.h"
6162

@@ -292,7 +293,7 @@ void SendMPDialog::sendMPTransaction()
292293
}
293294

294295
// use strToInt64 function to get the amount, using divisibility of the property
295-
int64_t sendAmount = strToInt64(strAmount, divisible);
296+
int64_t sendAmount = StrToInt64(strAmount, divisible);
296297
if (0>=sendAmount)
297298
{
298299
QMessageBox::critical( this, "Unable to send transaction",

src/test/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ test_bitcoin_SOURCES = \
4747
getarg_tests.cpp \
4848
key_tests.cpp \
4949
main_tests.cpp \
50+
mastercore_strtoint64_tests.cpp \
5051
miner_tests.cpp \
5152
mruset_tests.cpp \
5253
multisig_tests.cpp \
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#include "mastercore_parse_string.h"
2+
3+
#include <string>
4+
5+
#include <boost/test/unit_test.hpp>
6+
7+
using namespace mastercore;
8+
9+
BOOST_AUTO_TEST_SUITE(mastercore_strtoint64_tests)
10+
11+
BOOST_AUTO_TEST_CASE(mastercore_strtoint64_invidisible)
12+
{
13+
// zero amount
14+
BOOST_CHECK(StrToInt64("0", false) == 0);
15+
// big num
16+
BOOST_CHECK(StrToInt64("4000000000000000", false) == 4000000000000000);
17+
// max int64
18+
BOOST_CHECK(StrToInt64("9223372036854775807", false) == 9223372036854775807);
19+
}
20+
21+
BOOST_AUTO_TEST_CASE(mastercore_strtoint64_invidisible_truncate)
22+
{
23+
// ignore any char after decimal mark
24+
BOOST_CHECK(StrToInt64("8.76543210123456878901", false) == 8);
25+
BOOST_CHECK(StrToInt64("8.765432101.2345687890", false) == 8);
26+
BOOST_CHECK(StrToInt64("2345.AbCdEhf71z1.23", false) == 2345);
27+
}
28+
29+
BOOST_AUTO_TEST_CASE(mastercore_strtoint64_invidisible_invalid)
30+
{
31+
// invalid, number is negative
32+
BOOST_CHECK(StrToInt64("-4", false) == 0);
33+
// invalid, number is over max int64
34+
BOOST_CHECK(StrToInt64("9223372036854775808", false) == 0);
35+
// invalid, minus sign in string
36+
BOOST_CHECK(StrToInt64("2345.AbCdEFG71z88-1.23", false) == 0);
37+
}
38+
39+
BOOST_AUTO_TEST_CASE(mastercore_strtoint64_divisible)
40+
{
41+
// range 0 to max int64
42+
BOOST_CHECK(StrToInt64("0.000", true) == 0);
43+
BOOST_CHECK(StrToInt64("92233720368.54775807", true) == 9223372036854775807);
44+
// check padding
45+
BOOST_CHECK(StrToInt64("0.00000004", true) == 4);
46+
BOOST_CHECK(StrToInt64("0.0000004", true) == 40);
47+
BOOST_CHECK(StrToInt64("0.0004", true) == 40000);
48+
BOOST_CHECK(StrToInt64("0.4", true) == 40000000);
49+
BOOST_CHECK(StrToInt64("4.0", true) == 400000000);
50+
// truncate after 8 digits
51+
BOOST_CHECK(StrToInt64("40.00000000000099", true) == 4000000000);
52+
BOOST_CHECK(StrToInt64("92233720368.54775807000", true) == 9223372036854775807);
53+
}
54+
55+
BOOST_AUTO_TEST_CASE(mastercore_strtoint64_divisible_truncate)
56+
{
57+
// truncate after 8 digits
58+
BOOST_CHECK(StrToInt64("40.00000000000099", true) == 4000000000);
59+
BOOST_CHECK(StrToInt64("92233720368.54775807000", true) == 9223372036854775807);
60+
BOOST_CHECK(StrToInt64("92233720368.54775807000", true) == 9223372036854775807);
61+
}
62+
63+
BOOST_AUTO_TEST_CASE(mastercore_strtoint64_divisible_invalid)
64+
{
65+
// invalid, number is over max int64
66+
BOOST_CHECK(StrToInt64("92233720368.54775808", true) == 0);
67+
// invalid, more than one decimal mark in string
68+
BOOST_CHECK(StrToInt64("1234..12345678", true) == 0);
69+
// invalid, alpha chars in string
70+
BOOST_CHECK(StrToInt64("1234.12345A", true) == 0);
71+
// invalid, number is negative
72+
BOOST_CHECK(StrToInt64("-4.0", true) == 0);
73+
// invalid, minus sign in string
74+
BOOST_CHECK(StrToInt64("4.1234-5678", true) == 0);
75+
}
76+
77+
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)