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);
|
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++) {
|
enum {START, PLUSMINUS, LEADING_ZERO, BIN_OR_HEX_PREFIX, DOT, TRAILING_ZERO, TRAILING_F, ZERO, E, E_PLUSMINUS, E_DIGIT} state = START;
|
||||||
if (std::isdigit(static_cast<unsigned char>(str[i])) && str[i] != '0') // May not contain digits other than 0
|
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 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)
|
bool MathLib::isOctalDigit(char c)
|
||||||
|
|
|
@ -45,7 +45,8 @@ private:
|
||||||
TEST_CASE(calculate);
|
TEST_CASE(calculate);
|
||||||
TEST_CASE(calculate1);
|
TEST_CASE(calculate1);
|
||||||
TEST_CASE(convert);
|
TEST_CASE(convert);
|
||||||
TEST_CASE(naninf)
|
TEST_CASE(naninf);
|
||||||
|
TEST_CASE(isNullValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void isGreater() const {
|
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
|
||||||
ASSERT_EQUALS("-inf.0", MathLib::divide("-3.0", "0.0")); // -inf (#5142)
|
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)
|
REGISTER_TEST(TestMathLib)
|
||||||
|
|
Loading…
Reference in New Issue