fixed handling of incomplete char/string literals in `isPrefixStringCharLiteral()` - also optimized it a bit (#4541)

* fixed handling of incomplete char/string literals in `isPrefixStringCharLiteral()` - also optimized it a bit / added tests for `isStringLiteral()` and `isCharLiteral()`

* utils.h: early out in `isStringCharLiteral()` to avoid the loop
This commit is contained in:
Oliver Stöneberg 2022-10-09 11:19:19 +02:00 committed by GitHub
parent c5a226470a
commit d1bfae989e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 129 additions and 3 deletions

View File

@ -89,15 +89,31 @@ bool endsWith(const std::string& str, const char (&end)[N])
inline static bool isPrefixStringCharLiteral(const std::string &str, char q, const std::string& p)
{
// str must be at least the prefix plus the start and end quote
if (str.length() < p.length() + 2)
return false;
// check for end quote
if (!endsWith(str, q))
return false;
if ((str.length() + 1) > p.length() && (str.compare(0, p.size() + 1, p + q) == 0))
return true;
return false;
// check for start quote
if (str[p.size()] != q)
return false;
// check for prefix
if (str.compare(0, p.size(), p) != 0)
return false;
return true;
}
inline static bool isStringCharLiteral(const std::string &str, char q)
{
// early out to avoid the loop
if (!endsWith(str, q))
return false;
static const std::array<std::string, 5> suffixes{"", "u8", "u", "U", "L"};
for (const std::string & p: suffixes) {
if (isPrefixStringCharLiteral(str, q, p))

View File

@ -30,6 +30,8 @@ private:
void run() override {
TEST_CASE(isValidGlobPattern);
TEST_CASE(matchglob);
TEST_CASE(isStringLiteral);
TEST_CASE(isCharLiteral);
}
void isValidGlobPattern() const {
@ -68,6 +70,114 @@ private:
ASSERT_EQUALS(true, ::matchglob("?y?", "xyz"));
ASSERT_EQUALS(true, ::matchglob("?/?/?", "x/y/z"));
}
void isStringLiteral() const {
// empty
ASSERT_EQUALS(false, ::isStringLiteral(""));
// no literals
ASSERT_EQUALS(false, ::isStringLiteral("u8"));
ASSERT_EQUALS(false, ::isStringLiteral("u"));
ASSERT_EQUALS(false, ::isStringLiteral("U"));
ASSERT_EQUALS(false, ::isStringLiteral("L"));
// incomplete string literals
ASSERT_EQUALS(false, ::isStringLiteral("\""));
ASSERT_EQUALS(false, ::isStringLiteral("u8\""));
ASSERT_EQUALS(false, ::isStringLiteral("u\""));
ASSERT_EQUALS(false, ::isStringLiteral("U\""));
ASSERT_EQUALS(false, ::isStringLiteral("L\""));
// valid string literals
ASSERT_EQUALS(true, ::isStringLiteral("\"\""));
ASSERT_EQUALS(true, ::isStringLiteral("u8\"\""));
ASSERT_EQUALS(true, ::isStringLiteral("u\"\""));
ASSERT_EQUALS(true, ::isStringLiteral("U\"\""));
ASSERT_EQUALS(true, ::isStringLiteral("L\"\""));
ASSERT_EQUALS(true, ::isStringLiteral("\"t\""));
ASSERT_EQUALS(true, ::isStringLiteral("u8\"t\""));
ASSERT_EQUALS(true, ::isStringLiteral("u\"t\""));
ASSERT_EQUALS(true, ::isStringLiteral("U\"t\""));
ASSERT_EQUALS(true, ::isStringLiteral("L\"t\""));
ASSERT_EQUALS(true, ::isStringLiteral("\"test\""));
ASSERT_EQUALS(true, ::isStringLiteral("u8\"test\""));
ASSERT_EQUALS(true, ::isStringLiteral("u\"test\""));
ASSERT_EQUALS(true, ::isStringLiteral("U\"test\""));
ASSERT_EQUALS(true, ::isStringLiteral("L\"test\""));
// incomplete char literals
ASSERT_EQUALS(false, ::isStringLiteral("'"));
ASSERT_EQUALS(false, ::isStringLiteral("u8'"));
ASSERT_EQUALS(false, ::isStringLiteral("u'"));
ASSERT_EQUALS(false, ::isStringLiteral("U'"));
ASSERT_EQUALS(false, ::isStringLiteral("L'"));
// valid char literals
ASSERT_EQUALS(false, ::isStringLiteral("'t'"));
ASSERT_EQUALS(false, ::isStringLiteral("u8't'"));
ASSERT_EQUALS(false, ::isStringLiteral("u't'"));
ASSERT_EQUALS(false, ::isStringLiteral("U't'"));
ASSERT_EQUALS(false, ::isStringLiteral("L't'"));
ASSERT_EQUALS(false, ::isStringLiteral("'test'"));
ASSERT_EQUALS(false, ::isStringLiteral("u8'test'"));
ASSERT_EQUALS(false, ::isStringLiteral("u'test'"));
ASSERT_EQUALS(false, ::isStringLiteral("U'test'"));
ASSERT_EQUALS(false, ::isStringLiteral("L'test'"));
}
void isCharLiteral() const {
// empty
ASSERT_EQUALS(false, ::isCharLiteral(""));
// no literals
ASSERT_EQUALS(false, ::isCharLiteral("u8"));
ASSERT_EQUALS(false, ::isCharLiteral("u"));
ASSERT_EQUALS(false, ::isCharLiteral("U"));
ASSERT_EQUALS(false, ::isCharLiteral("L"));
// incomplete string literals
ASSERT_EQUALS(false, ::isCharLiteral("\""));
ASSERT_EQUALS(false, ::isCharLiteral("u8\""));
ASSERT_EQUALS(false, ::isCharLiteral("u\""));
ASSERT_EQUALS(false, ::isCharLiteral("U\""));
ASSERT_EQUALS(false, ::isCharLiteral("L\""));
// valid string literals
ASSERT_EQUALS(false, ::isCharLiteral("\"\""));
ASSERT_EQUALS(false, ::isCharLiteral("u8\"\""));
ASSERT_EQUALS(false, ::isCharLiteral("u\"\""));
ASSERT_EQUALS(false, ::isCharLiteral("U\"\""));
ASSERT_EQUALS(false, ::isCharLiteral("L\"\""));
ASSERT_EQUALS(false, ::isCharLiteral("\"t\""));
ASSERT_EQUALS(false, ::isCharLiteral("u8\"t\""));
ASSERT_EQUALS(false, ::isCharLiteral("u\"t\""));
ASSERT_EQUALS(false, ::isCharLiteral("U\"t\""));
ASSERT_EQUALS(false, ::isCharLiteral("L\"t\""));
ASSERT_EQUALS(false, ::isCharLiteral("\"test\""));
ASSERT_EQUALS(false, ::isCharLiteral("u8\"test\""));
ASSERT_EQUALS(false, ::isCharLiteral("u\"test\""));
ASSERT_EQUALS(false, ::isCharLiteral("U\"test\""));
ASSERT_EQUALS(false, ::isCharLiteral("L\"test\""));
// incomplete char literals
ASSERT_EQUALS(false, ::isCharLiteral("'"));
ASSERT_EQUALS(false, ::isCharLiteral("u8'"));
ASSERT_EQUALS(false, ::isCharLiteral("u'"));
ASSERT_EQUALS(false, ::isCharLiteral("U'"));
ASSERT_EQUALS(false, ::isCharLiteral("L'"));
// valid char literals
ASSERT_EQUALS(true, ::isCharLiteral("'t'"));
ASSERT_EQUALS(true, ::isCharLiteral("u8't'"));
ASSERT_EQUALS(true, ::isCharLiteral("u't'"));
ASSERT_EQUALS(true, ::isCharLiteral("U't'"));
ASSERT_EQUALS(true, ::isCharLiteral("L't'"));
ASSERT_EQUALS(true, ::isCharLiteral("'test'"));
ASSERT_EQUALS(true, ::isCharLiteral("u8'test'"));
ASSERT_EQUALS(true, ::isCharLiteral("u'test'"));
ASSERT_EQUALS(true, ::isCharLiteral("U'test'"));
ASSERT_EQUALS(true, ::isCharLiteral("L'test'"));
}
};
REGISTER_TEST(TestUtils)