Tidy up MathLib::isInt() - using a state machine approach

This commit is contained in:
Alexander Mai 2014-04-10 22:46:55 +02:00
parent b10fce304e
commit ab2f8bfba3
2 changed files with 35 additions and 41 deletions

View File

@ -251,10 +251,6 @@ bool MathLib::isOct(const std::string& s)
bool MathLib::isHex(const std::string& s)
{
// return false, in case an empty string is provided
if (s.empty())
return false;
enum {START, PLUSMINUS, HEX_PREFIX, DIGIT, DIGITS} state = START;
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
switch (state) {
@ -403,45 +399,39 @@ bool MathLib::isBin(const std::string& s)
bool MathLib::isInt(const std::string & s)
{
// perform prechecks:
// ------------------
// first check, if a point is found, it is an floating point value
const std::string charsToIndicateAFloat=".eE";
if (s.find_last_of(charsToIndicateAFloat) != std::string::npos)
return false;
// remember position
unsigned long n = 0;
// eat up whitespace
while (std::isspace(s[n])) ++n;
// determine type
// check for two known types: hexadecimal and octal
if (isHex(s) || isOct(s)) {
return true;
}
// check sign
if (s[n] == '-' || s[n] == '+') ++n;
// starts with digit
bool bStartsWithDigit=false;
while (std::isdigit(s[n])) {
bStartsWithDigit=true;
++n;
enum {START, PLUSMINUS, DIGIT, SUFFIX} 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 (isdigit(*it))
state = DIGIT;
else
return false;
break;
case PLUSMINUS:
if (isdigit(*it))
state = DIGIT;
else
return false;
break;
case DIGIT:
if (isdigit(*it))
state = DIGIT;
else
return isValidSuffix(it,s.end());
break;
case SUFFIX:
break;
}
}
while (std::tolower(s[n]) == 'u' || std::tolower(s[n]) == 'l') ++n; // unsigned or long (long)
if (!bStartsWithDigit)
return false;
// eat up whitespace
while (std::isspace(s[n]))
++n;
// if everything goes good, we are at the end of the string and no digits/character
// is here --> return true, but if something was found e.g. 12E+12AA return false
return (n >= s.length());
return state == DIGIT;
}
std::string MathLib::add(const std::string & first, const std::string & second)

View File

@ -29,9 +29,6 @@ public:
private:
void run() {
TEST_CASE(calculate);
TEST_CASE(calculate1);
TEST_CASE(convert);
TEST_CASE(isint);
TEST_CASE(isbin);
TEST_CASE(isoct);
@ -45,6 +42,9 @@ private:
TEST_CASE(isNotEqual)
TEST_CASE(isLess)
TEST_CASE(isLessEqual)
TEST_CASE(calculate);
TEST_CASE(calculate1);
TEST_CASE(convert);
TEST_CASE(naninf)
}
@ -440,6 +440,7 @@ private:
ASSERT_EQUALS(false, MathLib::isOct("-042ULL "));
// front and trailing white space
ASSERT_EQUALS(false, MathLib::isOct(" -042ULL "));
ASSERT_EQUALS(false, MathLib::isOct("+042LUL+0"));
}
void ishex() const {
@ -496,6 +497,9 @@ private:
ASSERT_EQUALS(false, MathLib::isHex("-0x0ULLz"));
ASSERT_EQUALS(false, MathLib::isHex("+0x0LLUz"));
ASSERT_EQUALS(false, MathLib::isHex("-0x0LLUz"));
ASSERT_EQUALS(false, MathLib::isHex("0x0+0"));
ASSERT_EQUALS(false, MathLib::isHex("e2"));
ASSERT_EQUALS(false, MathLib::isHex("+E2"));
// test empty string
ASSERT_EQUALS(false, MathLib::isHex(""));