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) 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; enum {START, PLUSMINUS, HEX_PREFIX, DIGIT, DIGITS} state = START;
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) { for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
switch (state) { switch (state) {
@ -403,45 +399,39 @@ bool MathLib::isBin(const std::string& s)
bool MathLib::isInt(const std::string & s) bool MathLib::isInt(const std::string & s)
{ {
// perform prechecks: // check for two known types: hexadecimal and octal
// ------------------
// 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
if (isHex(s) || isOct(s)) { if (isHex(s) || isOct(s)) {
return true; return true;
} }
// check sign enum {START, PLUSMINUS, DIGIT, SUFFIX} state = START;
if (s[n] == '-' || s[n] == '+') ++n; for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
switch (state) {
// starts with digit case START:
bool bStartsWithDigit=false; if (*it == '+' || *it == '-')
while (std::isdigit(s[n])) { state = PLUSMINUS;
bStartsWithDigit=true; else if (isdigit(*it))
++n; 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;
}
} }
return state == DIGIT;
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());
} }
std::string MathLib::add(const std::string & first, const std::string & second) std::string MathLib::add(const std::string & first, const std::string & second)

View File

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