diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index a6fb9608c..a8b047a0a 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -126,10 +126,88 @@ bool MathLib::isPositive(const std::string &s) return !MathLib::isNegative(s); } -bool MathLib::isOct(const std::string& str) +/*! \brief Does the string represent an octal number? + * In case leading or trailing white space is provided, the function + * returns false. + * Additional information can be found here: + * http://gcc.gnu.org/onlinedocs/gcc/Binary-constants.html + * + * \param[in] s The string to check. In case the string is empty, the function returns false. + * \return Return true in case a octal number is provided and false otherwise. + **/ +bool MathLib::isOct(const std::string& s) { - const bool sign = str[0]=='-' || str[0]=='+'; - return (str[sign?1:0] == '0' && (str.size() == 1 || isOctalDigit(str[sign?2:1])) && !isFloat(str)); + enum {START, PLUSMINUS, OCTAL_PREFIX, DIGITS, UNSIGNED_SUFFIX, SUFFIX_U, SUFFIX_UL, SUFFIX_ULL, SUFFIX_L, SUFFIX_LU, SUFFIX_LL, SUFFIX_LLU} 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 = OCTAL_PREFIX; + else + return false; + break; + case PLUSMINUS: + if (*it == '0') + state = OCTAL_PREFIX; + else + return false; + break; + + case OCTAL_PREFIX: + if (isOctalDigit(*it)) + state = DIGITS; + else + return false; + break; + case DIGITS: + if (isOctalDigit(*it)) + state = DIGITS; + else if (*it == 'u' || *it == 'U') + state = SUFFIX_U; + else if (*it == 'l' || *it == 'L') + state = SUFFIX_L; + else + return false; + 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; + default: + return false; + } + } + 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::isHex(const std::string& str) diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index 0ed5a38c1..9439c9dd6 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -34,6 +34,7 @@ private: TEST_CASE(convert); TEST_CASE(isint); TEST_CASE(isbin); + TEST_CASE(isoct); TEST_CASE(isnegative); TEST_CASE(ispositive); TEST_CASE(isfloat); @@ -367,6 +368,67 @@ private: ASSERT_EQUALS(false, MathLib::isNegative("+1.0E-2")); } + void isoct() { + // octal number format: [+|-]0[0-7][suffix] + // positive testing + ASSERT_EQUALS(true, MathLib::isOct("010")); + ASSERT_EQUALS(true, MathLib::isOct("+010")); + ASSERT_EQUALS(true, MathLib::isOct("-010")); + ASSERT_EQUALS(true, MathLib::isOct("0175")); + ASSERT_EQUALS(true, MathLib::isOct("+0175")); + ASSERT_EQUALS(true, MathLib::isOct("-0175")); + ASSERT_EQUALS(true, MathLib::isOct("00")); + ASSERT_EQUALS(true, MathLib::isOct("02")); + ASSERT_EQUALS(true, MathLib::isOct("+042")); + ASSERT_EQUALS(true, MathLib::isOct("-042")); + ASSERT_EQUALS(true, MathLib::isOct("+042U")); + ASSERT_EQUALS(true, MathLib::isOct("-042U")); + ASSERT_EQUALS(true, MathLib::isOct("+042L")); + ASSERT_EQUALS(true, MathLib::isOct("-042L")); + ASSERT_EQUALS(true, MathLib::isOct("+042LU")); + ASSERT_EQUALS(true, MathLib::isOct("-042LU")); + ASSERT_EQUALS(true, MathLib::isOct("+042UL")); + ASSERT_EQUALS(true, MathLib::isOct("-042UL")); + ASSERT_EQUALS(true, MathLib::isOct("+042ULL")); + ASSERT_EQUALS(true, MathLib::isOct("-042ULL")); + ASSERT_EQUALS(true, MathLib::isOct("+042LLU")); + ASSERT_EQUALS(true, MathLib::isOct("-042LLU")); + + // test empty string + ASSERT_EQUALS(false, MathLib::isOct("")); + + // negative testing + ASSERT_EQUALS(false, MathLib::isOct("0")); + ASSERT_EQUALS(false, MathLib::isOct("-0x175")); + ASSERT_EQUALS(false, MathLib::isOct("-0_garbage_")); + ASSERT_EQUALS(false, MathLib::isOct(" ")); + ASSERT_EQUALS(false, MathLib::isOct(" ")); + ASSERT_EQUALS(false, MathLib::isOct("02.")); + ASSERT_EQUALS(false, MathLib::isOct("02E2")); + ASSERT_EQUALS(false, MathLib::isOct("+042x")); + ASSERT_EQUALS(false, MathLib::isOct("-042x")); + ASSERT_EQUALS(false, MathLib::isOct("+042Ux")); + ASSERT_EQUALS(false, MathLib::isOct("-042Ux")); + ASSERT_EQUALS(false, MathLib::isOct("+042Lx")); + ASSERT_EQUALS(false, MathLib::isOct("-042Lx")); + ASSERT_EQUALS(false, MathLib::isOct("+042ULx")); + ASSERT_EQUALS(false, MathLib::isOct("-042ULx")); + ASSERT_EQUALS(false, MathLib::isOct("+042LLx")); + ASSERT_EQUALS(false, MathLib::isOct("-042LLx")); + ASSERT_EQUALS(false, MathLib::isOct("+042ULLx")); + ASSERT_EQUALS(false, MathLib::isOct("-042ULLx")); + ASSERT_EQUALS(false, MathLib::isOct("+042LLUx")); + ASSERT_EQUALS(false, MathLib::isOct("-042LLUx")); + ASSERT_EQUALS(false, MathLib::isOct("+042LUL")); + ASSERT_EQUALS(false, MathLib::isOct("-042LUL")); + // white space in front + ASSERT_EQUALS(false, MathLib::isOct(" -042ULL")); + // trailing white space + ASSERT_EQUALS(false, MathLib::isOct("-042ULL ")); + // front and trailing white space + ASSERT_EQUALS(false, MathLib::isOct(" -042ULL ")); + } + void ispositive() const { ASSERT_EQUALS(false, MathLib::isPositive("-1")); ASSERT_EQUALS(false, MathLib::isPositive("-1."));