Convert MathLib::toLongNumber() from template member function to toLongNumber() and toULongNumber() to avoid various problems compiling with Visual Studio

This commit is contained in:
Alexander Mai 2014-04-14 20:30:38 +02:00
parent bd242c07eb
commit ac24635056
3 changed files with 121 additions and 58 deletions

View File

@ -25,6 +25,101 @@
#include <cctype>
#include <limits>
MathLib::biguint MathLib::toULongNumber(const std::string & str) {
// hexadecimal numbers:
if (isHex(str)) {
if (str[0] == '-') {
biguint ret = 0;
std::istringstream istr(str);
istr >> std::hex >> ret;
return ret;
} else {
unsigned long long ret = 0;
std::istringstream istr(str);
istr >> std::hex >> ret;
return (biguint)ret;
}
}
// octal numbers:
if (isOct(str)) {
biguint ret = 0;
std::istringstream istr(str);
istr >> std::oct >> ret;
return ret;
}
// binary numbers:
if (isBin(str)) {
biguint ret = 0;
for (std::string::size_type i = str[0] == '0'?2:3; i < str.length(); i++) {
ret <<= 1;
if (str[i] == '1')
ret |= 1;
}
/* if (str[0] == '-')
ret = -ret; */
return ret;
}
if (isFloat(str)) {
return static_cast<biguint>(std::atof(str.c_str()));
}
biguint ret = 0;
std::istringstream istr(str);
istr >> ret;
return ret;
}
MathLib::bigint MathLib::toLongNumber(const std::string & str) {
// hexadecimal numbers:
if (isHex(str)) {
if (str[0] == '-') {
bigint ret = 0;
std::istringstream istr(str);
istr >> std::hex >> ret;
return ret;
} else {
unsigned long long ret = 0;
std::istringstream istr(str);
istr >> std::hex >> ret;
return (bigint)ret;
}
}
// octal numbers:
if (isOct(str)) {
bigint ret = 0;
std::istringstream istr(str);
istr >> std::oct >> ret;
return ret;
}
// binary numbers:
if (isBin(str)) {
bigint ret = 0;
for (std::string::size_type i = str[0] == '0'?2:3; i < str.length(); i++) {
ret <<= 1;
if (str[i] == '1')
ret |= 1;
}
if (str[0] == '-')
ret = -ret;
return ret;
}
if (isFloat(str)) {
return static_cast<bigint>(std::atof(str.c_str()));
}
bigint ret = 0;
std::istringstream istr(str);
istr >> ret;
return ret;
}
double MathLib::toDoubleNumber(const std::string &str)
{
if (isHex(str))

View File

@ -24,7 +24,6 @@
#include <cstdlib>
#include <string>
#include <sstream>
#include <type_traits>
#include "config.h"
/// @addtogroup Core
@ -37,54 +36,8 @@ public:
typedef long long bigint;
typedef unsigned long long biguint;
template < class T = bigint >
static T toLongNumber(const std::string & str) {
// hexadecimal numbers:
if (isHex(str)) {
if (str[0] == '-') {
T ret = 0;
std::istringstream istr(str);
istr >> std::hex >> ret;
return ret;
} else {
unsigned long long ret = 0;
std::istringstream istr(str);
istr >> std::hex >> ret;
return (T)ret;
}
}
// octal numbers:
if (isOct(str)) {
T ret = 0;
std::istringstream istr(str);
istr >> std::oct >> ret;
return ret;
}
// binary numbers:
if (isBin(str)) {
T ret = 0;
for (std::string::size_type i = str[0] == '0'?2:3; i < str.length(); i++) {
ret <<= 1;
if (str[i] == '1')
ret |= 1;
}
if (std::is_signed<T>()) {
if (str[0] == '-')
ret = -ret;
}
return ret;
}
if (isFloat(str))
return static_cast<T>(std::atof(str.c_str()));
T ret = 0;
std::istringstream istr(str);
istr >> ret;
return ret;
}
static bigint toLongNumber(const std::string & str);
static biguint toULongNumber(const std::string & str);
template<class T> static std::string toString(T value) {
std::ostringstream result;

View File

@ -800,20 +800,35 @@ static bool isLowerEqualThanMulDiv(const Token* lower)
return isLowerThanMulDiv(lower) || Token::Match(lower, "[*/%]");
}
template <typename T>
std::string typeCorrectShift(const char cop, const Token* left, const Token* right)
static std::string ShiftInt(const char cop, const Token* left, const Token* right)
{
const T leftInt=MathLib::toLongNumber<T>(left->str());
const T rightInt=MathLib::toLongNumber<T>(right->str());
if (cop == '&' || cop == '|' || cop == '^')
return MathLib::calculate(left->str(), right->str(), cop);
else if (cop == '<') {
const MathLib::bigint leftInt=MathLib::toLongNumber(left->str());
const MathLib::bigint rightInt=MathLib::toLongNumber(right->str());
if (cop == '<') {
if (left->previous()->str() != "<<" && rightInt > 0) // Ensure that its not a shift operator as used for streams
return MathLib::toString(leftInt << rightInt);
} else if (rightInt > 0)
} else if (rightInt > 0) {
return MathLib::toString(leftInt >> rightInt);
}
return "";
}
static std::string ShiftUInt(const char cop, const Token* left, const Token* right)
{
if (cop == '&' || cop == '|' || cop == '^')
return MathLib::calculate(left->str(), right->str(), cop);
const MathLib::biguint leftInt=MathLib::toULongNumber(left->str());
const MathLib::biguint rightInt=MathLib::toULongNumber(right->str());
if (cop == '<') {
if (left->previous()->str() != "<<") // Ensure that its not a shift operator as used for streams
return MathLib::toString(leftInt << rightInt);
} else {
return MathLib::toString(leftInt >> rightInt);
}
return "";
}
@ -846,9 +861,9 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
const char cop = op->str()[0];
std::string result;
if (tok->str().find_first_of("uU") != std::string::npos)
result = typeCorrectShift<MathLib::biguint>(cop, tok, tok->tokAt(2));
result = ShiftUInt(cop, tok, tok->tokAt(2));
else
result = typeCorrectShift<MathLib::bigint>(cop, tok, tok->tokAt(2));
result = ShiftInt(cop, tok, tok->tokAt(2));
if (!result.empty()) {
ret = true;
tok->str(result);