MathLib:IsNullValue(): using a Finite State Machine to determine a string value contains a numeric NULL value. The NULL value can be Integer, Binary, Hex, Octal. The corresponding unit test cases are also included.
This commit is contained in:
parent
1fafc7f4dc
commit
9c08885caf
102
lib/mathlib.cpp
102
lib/mathlib.cpp
|
@ -598,13 +598,107 @@ bool MathLib::isLessEqual(const std::string &first, const std::string &second)
|
|||
return toDoubleNumber(first) <= toDoubleNumber(second);
|
||||
}
|
||||
|
||||
bool MathLib::isNullValue(const std::string &str)
|
||||
bool MathLib::isNullValue(const std::string &s)
|
||||
{
|
||||
for (size_t i = 0; i < str.size(); i++) {
|
||||
if (std::isdigit(static_cast<unsigned char>(str[i])) && str[i] != '0') // May not contain digits other than 0
|
||||
enum {START, PLUSMINUS, LEADING_ZERO, BIN_OR_HEX_PREFIX, DOT, TRAILING_ZERO, TRAILING_F, ZERO, E, E_PLUSMINUS, E_DIGIT} 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 = LEADING_ZERO;
|
||||
else if (*it == '.')
|
||||
state = DOT;
|
||||
else
|
||||
return isValidSuffix(it, s.end());
|
||||
break;
|
||||
case PLUSMINUS:
|
||||
if (*it == '0')
|
||||
state = LEADING_ZERO;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
case LEADING_ZERO:
|
||||
if (*it == '0')
|
||||
state = LEADING_ZERO;
|
||||
else if (*it == 'b' || *it == 'B')
|
||||
state = BIN_OR_HEX_PREFIX;
|
||||
else if (*it == 'x' || *it == 'X')
|
||||
state = BIN_OR_HEX_PREFIX;
|
||||
else if (*it == '.')
|
||||
state = DOT;
|
||||
else if (*it == 'e' || *it == 'E')
|
||||
state = E;
|
||||
else
|
||||
return isValidSuffix(it, s.end());
|
||||
break;
|
||||
case BIN_OR_HEX_PREFIX:
|
||||
if (*it == '0')
|
||||
state = ZERO;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
case ZERO:
|
||||
if (*it == '0')
|
||||
state = ZERO;
|
||||
else
|
||||
return isValidSuffix(it, s.end());
|
||||
break;
|
||||
case DOT:
|
||||
if (*it == '0')
|
||||
state = TRAILING_ZERO;
|
||||
else if (*it == 'f' || *it == 'F')
|
||||
state = TRAILING_F;
|
||||
else if (*it == 'e' || *it == 'E')
|
||||
state = E;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
case E:
|
||||
if (*it == '+' || *it == '-')
|
||||
state = E_PLUSMINUS;
|
||||
else if (isdigit(*it))
|
||||
state = E_DIGIT;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
case E_PLUSMINUS:
|
||||
if (isdigit(*it))
|
||||
state = E_DIGIT;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
case E_DIGIT:
|
||||
if (isdigit(*it))
|
||||
state = E_DIGIT;
|
||||
else if (*it == 'f' || *it == 'F')
|
||||
state = TRAILING_F;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
case TRAILING_ZERO:
|
||||
if (*it == '0')
|
||||
state = TRAILING_ZERO;
|
||||
else if (*it == 'f' || *it == 'F')
|
||||
state = TRAILING_F;
|
||||
else if (*it == 'e' || *it == 'E')
|
||||
state = E;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !str.empty() && (std::isdigit(static_cast<unsigned char>(str[0])) || str[0] == '-' || str[0] == '+'); // Has to be a number
|
||||
return state == LEADING_ZERO || state == ZERO || state == DOT || state == E_DIGIT || state == TRAILING_ZERO || state == TRAILING_F;
|
||||
/*
|
||||
for (size_t i = 0; i < str.size(); i++) {
|
||||
if (std::isdigit(static_cast<unsigned char>(str[i])) && str[i] != '0') // May not contain digits other than 0
|
||||
return false;
|
||||
}
|
||||
return !str.empty() && (std::isdigit(static_cast<unsigned char>(str[0])) || str[0] == '-' || str[0] == '+'); // Has to be a number
|
||||
*/
|
||||
}
|
||||
|
||||
bool MathLib::isOctalDigit(char c)
|
||||
|
|
|
@ -45,7 +45,8 @@ private:
|
|||
TEST_CASE(calculate);
|
||||
TEST_CASE(calculate1);
|
||||
TEST_CASE(convert);
|
||||
TEST_CASE(naninf)
|
||||
TEST_CASE(naninf);
|
||||
TEST_CASE(isNullValue);
|
||||
}
|
||||
|
||||
void isGreater() const {
|
||||
|
@ -601,6 +602,169 @@ private:
|
|||
ASSERT_EQUALS("inf.0", MathLib::divide("3.0", "0.0")); // inf
|
||||
ASSERT_EQUALS("-inf.0", MathLib::divide("-3.0", "0.0")); // -inf (#5142)
|
||||
}
|
||||
|
||||
void isNullValue() const {
|
||||
// inter zero value
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0"));
|
||||
// inter zero value (octal)
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("00"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+00"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-00"));
|
||||
// inter zero value (hex)
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0x0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0x0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0x0"));
|
||||
// unsigned integer zero value
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0U"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0U"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0U"));
|
||||
// long integer zero value
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0L"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0L"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0L"));
|
||||
// unsigned long integer zero value
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0UL"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0UL"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0UL"));
|
||||
// unsigned long integer zero value
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0LU"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0LU"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0LU"));
|
||||
// long long integer zero value
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0LL"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0LL"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0LL"));
|
||||
// long long unsigend zero value
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0LLU"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0LLU"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0LLU"));
|
||||
// unsigned long long zero value
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0ULL"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0ULL"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0ULL"));
|
||||
// floating pointer zero value (no trailing zero after dot)
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0."));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0."));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0."));
|
||||
// floating pointer zero value (1 trailing zero after dot)
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0.0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0.0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0.0"));
|
||||
// floating pointer zero value (3 trailing zeros after dot)
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0.000"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0.000"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0.000"));
|
||||
// floating pointer zero value (no trailing zero after dot)
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("00."));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+00."));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-00."));
|
||||
// floating pointer zero value (1 trailing zero after dot)
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("00.0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+00.0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-00.0"));
|
||||
// floating pointer zero value (3 trailing zero after dot)
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("00.000"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+00.000"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-00.000"));
|
||||
// floating pointer zero value (3 trailing zero after dot)
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue(".000"));
|
||||
// integer scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0E0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0E0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0E0"));
|
||||
// integer scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0E1"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0E1"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0E1"));
|
||||
// integer scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0E42"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0E42"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0E42"));
|
||||
// integer scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0E429999"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0E429999"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0E429999"));
|
||||
// integer scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0E+1"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0E+1"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0E+1"));
|
||||
// integer scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0E+42"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0E+42"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0E+42"));
|
||||
// integer scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0E+429999"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0E+429999"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0E+429999"));
|
||||
// integer scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0E-1"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0E-1"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0E-1"));
|
||||
// integer scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0E-42"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0E-42"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0E-42"));
|
||||
// integer scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0E-429999"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0E-429999"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0E-429999"));
|
||||
// floating point scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0.E0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0.E0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0.E0"));
|
||||
// floating point scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0.E-0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0.E-0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0.E+0"));
|
||||
// floating point scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0.E+0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0.E+0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0.E+0"));
|
||||
// floating point scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0.00E-0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0.00E-0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0.00E-0"));
|
||||
// floating point scientific notation
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("00000.00E-000000000"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+00000.00E-000000000"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-00000.00E-000000000"));
|
||||
// floating point scientific notation (suffix f)
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0.f"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0.f"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0.f"));
|
||||
// floating point scientific notation (suffix f)
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("0.0f"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+0.0f"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-0.0f"));
|
||||
// floating point scientific notation (suffix f)
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("00.0f"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+00.0f"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-00.0f"));
|
||||
// floating point scientific notation (suffix f)
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("00.00f"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+00.00f"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-00.00f"));
|
||||
// floating point scientific notation (suffix f)
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("00.00E+1f"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("+00.00E+1f"));
|
||||
ASSERT_EQUALS(true, MathLib::isNullValue("-00.00E+1f"));
|
||||
|
||||
// negative testing
|
||||
ASSERT_EQUALS(false, MathLib::isNullValue("0.1"));
|
||||
ASSERT_EQUALS(false, MathLib::isNullValue("1.0"));
|
||||
ASSERT_EQUALS(false, MathLib::isNullValue("0.01"));
|
||||
ASSERT_EQUALS(false, MathLib::isNullValue("-00.01e-12"));
|
||||
ASSERT_EQUALS(false, MathLib::isNullValue("-00.01e+12"));
|
||||
ASSERT_EQUALS(false, MathLib::isNullValue(""));
|
||||
ASSERT_EQUALS(false, MathLib::isNullValue("x"));
|
||||
ASSERT_EQUALS(false, MathLib::isNullValue("garbage"));
|
||||
// suffix LUL is not allowed
|
||||
ASSERT_EQUALS(false, MathLib::isNullValue("0LUL"));
|
||||
ASSERT_EQUALS(false, MathLib::isNullValue("+0LUL"));
|
||||
ASSERT_EQUALS(false, MathLib::isNullValue("-0LUL"));
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestMathLib)
|
||||
|
|
Loading…
Reference in New Issue