diff --git a/lib/utils.h b/lib/utils.h index c8e7e6816..e70b7de35 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -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 suffixes{"", "u8", "u", "U", "L"}; for (const std::string & p: suffixes) { if (isPrefixStringCharLiteral(str, q, p)) diff --git a/test/testutils.cpp b/test/testutils.cpp index 230b220f4..bdc12b217 100644 --- a/test/testutils.cpp +++ b/test/testutils.cpp @@ -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)