Skip to content

Commit af0cf9b

Browse files
committed
Merge pull request cppcheck-opensource#258 from orbitcowboy/master
MathLib::isBin(): fix missing detection of U and L suffix combinations. ...
2 parents 3721165 + 5b4ece4 commit af0cf9b

2 files changed

Lines changed: 127 additions & 3 deletions

File tree

lib/mathlib.cpp

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,93 @@ bool MathLib::isHex(const std::string& str)
214214
return (str.compare(sign?1:0, 2, "0x") == 0 || str.compare(sign?1:0, 2, "0X") == 0);
215215
}
216216

217-
bool MathLib::isBin(const std::string& str)
217+
/*! \brief Does the string represent a binary number?
218+
* In case leading or trailing white space is provided, the function
219+
* returns false.
220+
* Additional information can be found here:
221+
* http://gcc.gnu.org/onlinedocs/gcc/Binary-constants.html
222+
*
223+
* \param[in] s The string to check. In case the string is empty, the function returns false.
224+
* \return Return true in case a binary number is provided and false otherwise.
225+
**/
226+
bool MathLib::isBin(const std::string& s)
218227
{
219-
const bool sign = str[0]=='-' || str[0]=='+';
220-
return ((str.compare(sign?1:0, 2, "0b") == 0 || str.compare(sign?1:0, 2, "0B") == 0) && str.find_first_not_of("10bB", 1) == std::string::npos);
228+
enum {START, PLUSMINUS, GNU_BIN_PREFIX, DIGIT, DIGITS, SUFFIX_U, SUFFIX_UL, SUFFIX_ULL, SUFFIX_L, SUFFIX_LU, SUFFIX_LL, SUFFIX_LLU} state = START;
229+
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
230+
switch (state) {
231+
case START:
232+
if (*it == '+' || *it == '-')
233+
state = PLUSMINUS;
234+
else if (*it == '0')
235+
state = GNU_BIN_PREFIX;
236+
else
237+
return false;
238+
break;
239+
case PLUSMINUS:
240+
if (*it == '0')
241+
state = GNU_BIN_PREFIX;
242+
else
243+
return false;
244+
break;
245+
case GNU_BIN_PREFIX:
246+
if (*it == 'b' || *it == 'B')
247+
state = DIGIT;
248+
else
249+
return false;
250+
break;
251+
case DIGIT:
252+
if (*it == '0' || *it == '1')
253+
state = DIGITS;
254+
else
255+
return false;
256+
break;
257+
case DIGITS:
258+
if (*it == '0' || *it == '1')
259+
state = DIGITS;
260+
else if (*it == 'u' || *it == 'U')
261+
state = SUFFIX_U;
262+
else if (*it == 'l' || *it == 'L')
263+
state = SUFFIX_L;
264+
else
265+
return false;
266+
break;
267+
case SUFFIX_U:
268+
if (*it == 'l' || *it == 'L')
269+
state = SUFFIX_UL; // UL
270+
else
271+
return false;
272+
break;
273+
case SUFFIX_UL:
274+
if (*it == 'l' || *it == 'L')
275+
state = SUFFIX_ULL; // ULL
276+
else
277+
return false;
278+
break;
279+
case SUFFIX_L:
280+
if (*it == 'u' || *it == 'U')
281+
state = SUFFIX_LU; // LU
282+
else if (*it == 'l' || *it == 'L')
283+
state = SUFFIX_LL; // LL
284+
else
285+
return false;
286+
break;
287+
case SUFFIX_LU:
288+
return false;
289+
break;
290+
case SUFFIX_LL:
291+
if (*it == 'u' || *it == 'U')
292+
state = SUFFIX_LLU; // LLU
293+
else
294+
return false;
295+
break;
296+
default:
297+
return false;
298+
}
299+
}
300+
return (state == DIGITS)
301+
|| (state == SUFFIX_U) || (state == SUFFIX_L)
302+
|| (state == SUFFIX_UL) || (state == SUFFIX_LU) || (state == SUFFIX_LL)
303+
|| (state == SUFFIX_ULL) || (state == SUFFIX_LLU);
221304
}
222305

223306
bool MathLib::isInt(const std::string & s)

test/testmathlib.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class TestMathLib : public TestFixture {
3333
TEST_CASE(calculate1);
3434
TEST_CASE(convert);
3535
TEST_CASE(isint);
36+
TEST_CASE(isbin);
3637
TEST_CASE(isnegative);
3738
TEST_CASE(ispositive);
3839
TEST_CASE(isfloat);
@@ -316,6 +317,46 @@ class TestMathLib : public TestFixture {
316317
ASSERT_EQUALS(false, MathLib::isInt(".E2"));
317318
}
318319

320+
void isbin() {
321+
// positive testing
322+
ASSERT_EQUALS(true, MathLib::isBin("0b0"));
323+
ASSERT_EQUALS(true, MathLib::isBin("0b1"));
324+
ASSERT_EQUALS(true, MathLib::isBin("+0b1"));
325+
ASSERT_EQUALS(true, MathLib::isBin("-0b1"));
326+
ASSERT_EQUALS(true, MathLib::isBin("0b11010111"));
327+
ASSERT_EQUALS(true, MathLib::isBin("-0b11010111"));
328+
ASSERT_EQUALS(true, MathLib::isBin("0B11010111"));
329+
ASSERT_EQUALS(true, MathLib::isBin("0b11010111u"));
330+
ASSERT_EQUALS(true, MathLib::isBin("0b11010111ul"));
331+
ASSERT_EQUALS(true, MathLib::isBin("0b11010111ull"));
332+
ASSERT_EQUALS(true, MathLib::isBin("0b11010111l"));
333+
ASSERT_EQUALS(true, MathLib::isBin("0b11010111ll"));
334+
ASSERT_EQUALS(true, MathLib::isBin("0b11010111llu"));
335+
ASSERT_EQUALS(true, MathLib::isBin("0b11010111l"));
336+
ASSERT_EQUALS(true, MathLib::isBin("0b11010111lu"));
337+
ASSERT_EQUALS(false, MathLib::isBin("0b11010111lul")); // Suffix LUL not allowed
338+
339+
// negative testing
340+
ASSERT_EQUALS(false, MathLib::isBin("100101bx"));
341+
ASSERT_EQUALS(false, MathLib::isBin("0"));
342+
ASSERT_EQUALS(false, MathLib::isBin("0B"));
343+
ASSERT_EQUALS(false, MathLib::isBin("0C"));
344+
ASSERT_EQUALS(false, MathLib::isBin("+0B"));
345+
ASSERT_EQUALS(false, MathLib::isBin("-0B"));
346+
ASSERT_EQUALS(false, MathLib::isBin("-0Bx"));
347+
ASSERT_EQUALS(false, MathLib::isBin("0b11010111x"));
348+
ASSERT_EQUALS(false, MathLib::isBin("0b11010111ux"));
349+
ASSERT_EQUALS(false, MathLib::isBin("0b11010111lx"));
350+
ASSERT_EQUALS(false, MathLib::isBin("0b11010111lux"));
351+
ASSERT_EQUALS(false, MathLib::isBin("0b11010111ulx"));
352+
ASSERT_EQUALS(false, MathLib::isBin("0b11010111lulx"));
353+
ASSERT_EQUALS(false, MathLib::isBin("0b11010111ullx"));
354+
ASSERT_EQUALS(false, MathLib::isBin("0b11010111lll"));
355+
356+
// test empty string
357+
ASSERT_EQUALS(false, MathLib::isBin(""));
358+
}
359+
319360
void isnegative() const {
320361
ASSERT_EQUALS(true , MathLib::isNegative("-1"));
321362
ASSERT_EQUALS(true , MathLib::isNegative("-1."));

0 commit comments

Comments
 (0)