Merge pull request #261 from orbitcowboy/master
MathLib:isHex(): fix detection of missing suffixes (U,L).
This commit is contained in:
commit
8c7cf090c4
120
lib/mathlib.cpp
120
lib/mathlib.cpp
|
@ -213,7 +213,7 @@ bool MathLib::isPositive(const std::string &s)
|
||||||
**/
|
**/
|
||||||
bool MathLib::isOct(const std::string& s)
|
bool MathLib::isOct(const std::string& s)
|
||||||
{
|
{
|
||||||
enum {START, PLUSMINUS, OCTAL_PREFIX, DIGITS, UNSIGNED_SUFFIX, SUFFIX_U, SUFFIX_UL, SUFFIX_ULL, SUFFIX_L, SUFFIX_LU, SUFFIX_LL, SUFFIX_LLU} state = START;
|
enum {START, PLUSMINUS, OCTAL_PREFIX, 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) {
|
||||||
case START:
|
case START:
|
||||||
|
@ -230,7 +230,6 @@ bool MathLib::isOct(const std::string& s)
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OCTAL_PREFIX:
|
case OCTAL_PREFIX:
|
||||||
if (isOctalDigit(*it))
|
if (isOctalDigit(*it))
|
||||||
state = DIGITS;
|
state = DIGITS;
|
||||||
|
@ -240,7 +239,71 @@ bool MathLib::isOct(const std::string& s)
|
||||||
case DIGITS:
|
case DIGITS:
|
||||||
if (isOctalDigit(*it))
|
if (isOctalDigit(*it))
|
||||||
state = DIGITS;
|
state = DIGITS;
|
||||||
else if (*it == 'u' || *it == 'U')
|
else
|
||||||
|
return isValidSuffix(it,s.end());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state == DIGITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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 (isxdigit(*it))
|
||||||
|
state = DIGITS;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case DIGITS:
|
||||||
|
if (isxdigit(*it))
|
||||||
|
state = DIGITS;
|
||||||
|
else
|
||||||
|
return isValidSuffix(it,s.end());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state == DIGITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MathLib::isValidSuffix(std::string::const_iterator it, std::string::const_iterator end)
|
||||||
|
{
|
||||||
|
enum {START, SUFFIX_U, SUFFIX_UL, SUFFIX_ULL, SUFFIX_L, SUFFIX_LU, SUFFIX_LL, SUFFIX_LLU} state = START;
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
switch (state) {
|
||||||
|
case START:
|
||||||
|
if (*it == 'u' || *it == 'U')
|
||||||
state = SUFFIX_U;
|
state = SUFFIX_U;
|
||||||
else if (*it == 'l' || *it == 'L')
|
else if (*it == 'l' || *it == 'L')
|
||||||
state = SUFFIX_L;
|
state = SUFFIX_L;
|
||||||
|
@ -280,18 +343,11 @@ bool MathLib::isOct(const std::string& s)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (state == DIGITS)
|
return (state == SUFFIX_U) || (state == SUFFIX_L)
|
||||||
|| (state == SUFFIX_U) || (state == SUFFIX_L)
|
|
||||||
|| (state == SUFFIX_UL) || (state == SUFFIX_LU) || (state == SUFFIX_LL)
|
|| (state == SUFFIX_UL) || (state == SUFFIX_LU) || (state == SUFFIX_LL)
|
||||||
|| (state == SUFFIX_ULL) || (state == SUFFIX_LLU);
|
|| (state == SUFFIX_ULL) || (state == SUFFIX_LLU);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MathLib::isHex(const std::string& str)
|
|
||||||
{
|
|
||||||
const bool sign = str[0]=='-' || str[0]=='+';
|
|
||||||
return (str.compare(sign?1:0, 2, "0x") == 0 || str.compare(sign?1:0, 2, "0X") == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \brief Does the string represent a binary number?
|
/*! \brief Does the string represent a binary number?
|
||||||
* In case leading or trailing white space is provided, the function
|
* In case leading or trailing white space is provided, the function
|
||||||
* returns false.
|
* returns false.
|
||||||
|
@ -303,7 +359,7 @@ bool MathLib::isHex(const std::string& str)
|
||||||
**/
|
**/
|
||||||
bool MathLib::isBin(const std::string& s)
|
bool MathLib::isBin(const std::string& s)
|
||||||
{
|
{
|
||||||
enum {START, PLUSMINUS, GNU_BIN_PREFIX, DIGIT, DIGITS, SUFFIX_U, SUFFIX_UL, SUFFIX_ULL, SUFFIX_L, SUFFIX_LU, SUFFIX_LL, SUFFIX_LLU} state = START;
|
enum {START, PLUSMINUS, GNU_BIN_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) {
|
||||||
case START:
|
case START:
|
||||||
|
@ -335,50 +391,14 @@ bool MathLib::isBin(const std::string& s)
|
||||||
case DIGITS:
|
case DIGITS:
|
||||||
if (*it == '0' || *it == '1')
|
if (*it == '0' || *it == '1')
|
||||||
state = DIGITS;
|
state = DIGITS;
|
||||||
else if (*it == 'u' || *it == 'U')
|
|
||||||
state = SUFFIX_U;
|
|
||||||
else if (*it == 'l' || *it == 'L')
|
|
||||||
state = SUFFIX_L;
|
|
||||||
else
|
else
|
||||||
return false;
|
return isValidSuffix(it,s.end());
|
||||||
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;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (state == DIGITS)
|
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::isInt(const std::string & s)
|
bool MathLib::isInt(const std::string & s)
|
||||||
|
|
|
@ -50,6 +50,8 @@ public:
|
||||||
static bool isOct(const std::string& str);
|
static bool isOct(const std::string& str);
|
||||||
static bool isBin(const std::string& str);
|
static bool isBin(const std::string& str);
|
||||||
|
|
||||||
|
static bool isValidSuffix(std::string::const_iterator it, std::string::const_iterator end);
|
||||||
|
|
||||||
static std::string add(const std::string & first, const std::string & second);
|
static std::string add(const std::string & first, const std::string & second);
|
||||||
static std::string subtract(const std::string & first, const std::string & second);
|
static std::string subtract(const std::string & first, const std::string & second);
|
||||||
static std::string multiply(const std::string & first, const std::string & second);
|
static std::string multiply(const std::string & first, const std::string & second);
|
||||||
|
|
|
@ -35,6 +35,7 @@ private:
|
||||||
TEST_CASE(isint);
|
TEST_CASE(isint);
|
||||||
TEST_CASE(isbin);
|
TEST_CASE(isbin);
|
||||||
TEST_CASE(isoct);
|
TEST_CASE(isoct);
|
||||||
|
TEST_CASE(ishex);
|
||||||
TEST_CASE(isnegative);
|
TEST_CASE(isnegative);
|
||||||
TEST_CASE(ispositive);
|
TEST_CASE(ispositive);
|
||||||
TEST_CASE(isfloat);
|
TEST_CASE(isfloat);
|
||||||
|
@ -433,6 +434,65 @@ private:
|
||||||
ASSERT_EQUALS(false, MathLib::isOct(" -042ULL "));
|
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 {
|
void ispositive() const {
|
||||||
ASSERT_EQUALS(false, MathLib::isPositive("-1"));
|
ASSERT_EQUALS(false, MathLib::isPositive("-1"));
|
||||||
ASSERT_EQUALS(false, MathLib::isPositive("-1."));
|
ASSERT_EQUALS(false, MathLib::isPositive("-1."));
|
||||||
|
|
Loading…
Reference in New Issue