MathLib:isHex(): fix detection of missing suffixes (U,L).

This commit is contained in:
orbitcowboy 2014-03-11 20:02:04 +01:00
parent 0360840753
commit ed793793db
3 changed files with 155 additions and 3 deletions

View File

@ -210,10 +210,95 @@ bool MathLib::isOct(const std::string& s)
|| (state == SUFFIX_ULL) || (state == SUFFIX_LLU);
}
bool MathLib::isHex(const std::string& str)
bool MathLib::isHex(const std::string& s)
{
const bool sign = str[0]=='-' || str[0]=='+';
return (str.compare(sign?1:0, 2, "0x") == 0 || str.compare(sign?1:0, 2, "0X") == 0);
// return false, in case an empty string is provided
if (s.empty())
return false;
enum {START, PLUSMINUS, HEX_PREFIX, DIGIT, DIGITS, SUFFIX_U, SUFFIX_UL, SUFFIX_ULL, SUFFIX_L, SUFFIX_LU, SUFFIX_LL, SUFFIX_LLU} state = START;
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
switch (state) {
case START:
if (*it == '+' || *it == '-')
state = PLUSMINUS;
else if (*it == '0')
state = HEX_PREFIX;
else
return false;
break;
case PLUSMINUS:
if (*it == '0')
state = HEX_PREFIX;
else
return false;
break;
case HEX_PREFIX:
if (*it == 'x' || *it == 'X')
state = DIGIT;
else
return false;
break;
case DIGIT:
if (isHexDigit(*it))
state = DIGITS;
else
return false;
break;
case DIGITS:
if (isHexDigit(*it))
state = DIGITS;
else if (*it == 'u' || *it == 'U')
state = SUFFIX_U;
else if (*it == 'l' || *it == 'L')
state = SUFFIX_L;
else
return false;
break;
case SUFFIX_U:
if (*it == 'l' || *it == 'L')
state = SUFFIX_UL; // UL
else
return false;
break;
case SUFFIX_UL:
if (*it == 'l' || *it == 'L')
state = SUFFIX_ULL; // ULL
else
return false;
break;
case SUFFIX_L:
if (*it == 'u' || *it == 'U')
state = SUFFIX_LU; // LU
else if (*it == 'l' || *it == 'L')
state = SUFFIX_LL; // LL
else
return false;
break;
case SUFFIX_LU:
return false;
break;
case SUFFIX_LL:
if (*it == 'u' || *it == 'U')
state = SUFFIX_LLU; // LLU
else
return false;
break;
default:
return false;
}
}
return (state == DIGITS)
|| (state == SUFFIX_U) || (state == SUFFIX_L)
|| (state == SUFFIX_UL) || (state == SUFFIX_LU) || (state == SUFFIX_LL)
|| (state == SUFFIX_ULL) || (state == SUFFIX_LLU);
}
bool MathLib::isHexDigit(char c)
{
return (c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6' || c == '7' || c == '8' || c == '9'
|| c == 'A' || c == 'B' || c == 'C' || c == 'D' || c == 'E' || c == 'F'
|| c == 'a' || c == 'b' || c == 'c' || c == 'd' || c == 'e' || c == 'f');
}
/*! \brief Does the string represent a binary number?

View File

@ -74,6 +74,13 @@ public:
* @return true if given character is octal digit.
*/
static bool isOctalDigit(char c);
/**
* Return true if given character is 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F.
* @param c The character to check
* @return true if given character is hex digit.
*/
static bool isHexDigit(char c);
};
template<> CPPCHECKLIB std::string MathLib::toString(double value); // Declare specialization to avoid linker problems

View File

@ -35,6 +35,7 @@ private:
TEST_CASE(isint);
TEST_CASE(isbin);
TEST_CASE(isoct);
TEST_CASE(ishex);
TEST_CASE(isnegative);
TEST_CASE(ispositive);
TEST_CASE(isfloat);
@ -429,6 +430,65 @@ private:
ASSERT_EQUALS(false, MathLib::isOct(" -042ULL "));
}
void ishex() {
// hex number syntax: [sign]0x[hexnumbers][suffix]
// positive testing
ASSERT_EQUALS(true, MathLib::isHex("0xa"));
ASSERT_EQUALS(true, MathLib::isHex("0x2AF3"));
ASSERT_EQUALS(true, MathLib::isHex("-0xa"));
ASSERT_EQUALS(true, MathLib::isHex("-0x2AF3"));
ASSERT_EQUALS(true, MathLib::isHex("+0xa"));
ASSERT_EQUALS(true, MathLib::isHex("+0x2AF3"));
ASSERT_EQUALS(true, MathLib::isHex("0x0"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0U"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0U"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0L"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0L"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0LU"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0LU"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0UL"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0UL"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0LL"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0LL"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0ULL"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0ULL"));
ASSERT_EQUALS(true, MathLib::isHex("+0x0LLU"));
ASSERT_EQUALS(true, MathLib::isHex("-0x0LLU"));
// negative testing
ASSERT_EQUALS(false, MathLib::isHex("+0x"));
ASSERT_EQUALS(false, MathLib::isHex("-0x"));
ASSERT_EQUALS(false, MathLib::isHex("0x"));
ASSERT_EQUALS(false, MathLib::isHex("0xx"));
ASSERT_EQUALS(false, MathLib::isHex("-0175"));
ASSERT_EQUALS(false, MathLib::isHex("-0_garbage_"));
ASSERT_EQUALS(false, MathLib::isHex(" "));
ASSERT_EQUALS(false, MathLib::isHex(" "));
ASSERT_EQUALS(false, MathLib::isHex("0"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0Z"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0Z"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0Uz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0Uz"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0Lz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0Lz"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0LUz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0LUz"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0ULz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0ULz"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0LLz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0LLz"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0ULLz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0ULLz"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0LLUz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0LLUz"));
// test empty string
ASSERT_EQUALS(false, MathLib::isHex(""));
}
void ispositive() const {
ASSERT_EQUALS(false, MathLib::isPositive("-1"));
ASSERT_EQUALS(false, MathLib::isPositive("-1."));