diff --git a/llvm/include/llvm/ADT/StringSwitch.h b/llvm/include/llvm/ADT/StringSwitch.h index 0ce7c57a358f2..a96535cd077fd 100644 --- a/llvm/include/llvm/ADT/StringSwitch.h +++ b/llvm/include/llvm/ADT/StringSwitch.h @@ -17,6 +17,7 @@ #include "llvm/Support/ErrorHandling.h" #include #include +#include #include namespace llvm { @@ -85,55 +86,60 @@ class StringSwitch { return *this; } + StringSwitch &Cases(std::initializer_list CaseStrings, + T Value) { + return CasesImpl(Value, CaseStrings); + } + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, T Value) { - return CasesImpl(Value, S0, S1); + return CasesImpl(Value, {S0, S1}); } StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, T Value) { - return CasesImpl(Value, S0, S1, S2); + return CasesImpl(Value, {S0, S1, S2}); } StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, T Value) { - return CasesImpl(Value, S0, S1, S2, S3); + return CasesImpl(Value, {S0, S1, S2, S3}); } StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, T Value) { - return CasesImpl(Value, S0, S1, S2, S3, S4); + return CasesImpl(Value, {S0, S1, S2, S3, S4}); } StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, T Value) { - return CasesImpl(Value, S0, S1, S2, S3, S4, S5); + return CasesImpl(Value, {S0, S1, S2, S3, S4, S5}); } StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, StringLiteral S6, T Value) { - return CasesImpl(Value, S0, S1, S2, S3, S4, S5, S6); + return CasesImpl(Value, {S0, S1, S2, S3, S4, S5, S6}); } StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, StringLiteral S6, StringLiteral S7, T Value) { - return CasesImpl(Value, S0, S1, S2, S3, S4, S5, S6, S7); + return CasesImpl(Value, {S0, S1, S2, S3, S4, S5, S6, S7}); } StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, StringLiteral S6, StringLiteral S7, StringLiteral S8, T Value) { - return CasesImpl(Value, S0, S1, S2, S3, S4, S5, S6, S7, S8); + return CasesImpl(Value, {S0, S1, S2, S3, S4, S5, S6, S7, S8}); } StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, StringLiteral S6, StringLiteral S7, StringLiteral S8, StringLiteral S9, T Value) { - return CasesImpl(Value, S0, S1, S2, S3, S4, S5, S6, S7, S8, S9); + return CasesImpl(Value, {S0, S1, S2, S3, S4, S5, S6, S7, S8, S9}); } // Case-insensitive case matchers. @@ -156,23 +162,28 @@ class StringSwitch { return *this; } + StringSwitch &CasesLower(std::initializer_list CaseStrings, + T Value) { + return CasesLowerImpl(Value, CaseStrings); + } + StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, T Value) { - return CasesLowerImpl(Value, S0, S1); + return CasesLowerImpl(Value, {S0, S1}); } StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, T Value) { - return CasesLowerImpl(Value, S0, S1, S2); + return CasesLowerImpl(Value, {S0, S1, S2}); } StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, T Value) { - return CasesLowerImpl(Value, S0, S1, S2, S3); + return CasesLowerImpl(Value, {S0, S1, S2, S3}); } StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, T Value) { - return CasesLowerImpl(Value, S0, S1, S2, S3, S4); + return CasesLowerImpl(Value, {S0, S1, S2, S3, S4}); } [[nodiscard]] R Default(T Value) { @@ -211,16 +222,21 @@ class StringSwitch { return false; } - template StringSwitch &CasesImpl(T &Value, Args... Cases) { + StringSwitch &CasesImpl(T &Value, + std::initializer_list Cases) { // Stop matching after the string is found. - (... || CaseImpl(Value, Cases)); + for (StringLiteral S : Cases) + if (CaseImpl(Value, S)) + break; return *this; } - template - StringSwitch &CasesLowerImpl(T &Value, Args... Cases) { + StringSwitch &CasesLowerImpl(T &Value, + std::initializer_list Cases) { // Stop matching after the string is found. - (... || CaseLowerImpl(Value, Cases)); + for (StringLiteral S : Cases) + if (CaseLowerImpl(Value, S)) + break; return *this; } }; diff --git a/llvm/unittests/ADT/StringSwitchTest.cpp b/llvm/unittests/ADT/StringSwitchTest.cpp index bcb1521baa287..0fbf37153593e 100644 --- a/llvm/unittests/ADT/StringSwitchTest.cpp +++ b/llvm/unittests/ADT/StringSwitchTest.cpp @@ -153,13 +153,14 @@ TEST(StringSwitchTest, EndsWithLower) { } TEST(StringSwitchTest, Cases) { - enum class OSType { Windows, Linux, Unknown }; + enum class OSType { Windows, Linux, MacOS, Unknown }; auto Translate = [](StringRef S) { return llvm::StringSwitch(S) .Cases(StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt", OSType::Windows) .Cases("linux", "unix", "*nix", "posix", OSType::Linux) + .Cases({"macos", "osx"}, OSType::MacOS) .Default(OSType::Unknown); }; @@ -172,21 +173,26 @@ TEST(StringSwitchTest, Cases) { EXPECT_EQ(OSType::Linux, Translate("*nix")); EXPECT_EQ(OSType::Linux, Translate("posix")); + EXPECT_EQ(OSType::MacOS, Translate("macos")); + EXPECT_EQ(OSType::MacOS, Translate("osx")); + // Note that the whole null-terminator embedded string is required for the // case to match. EXPECT_EQ(OSType::Unknown, Translate("wind")); EXPECT_EQ(OSType::Unknown, Translate("Windows")); + EXPECT_EQ(OSType::Unknown, Translate("MacOS")); EXPECT_EQ(OSType::Unknown, Translate("")); } TEST(StringSwitchTest, CasesLower) { - enum class OSType { Windows, Linux, Unknown }; + enum class OSType { Windows, Linux, MacOS, Unknown }; auto Translate = [](StringRef S) { return llvm::StringSwitch(S) .CasesLower(StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt", OSType::Windows) .CasesLower("linux", "unix", "*nix", "posix", OSType::Linux) + .CasesLower({"macos", "osx"}, OSType::MacOS) .Default(OSType::Unknown); }; @@ -202,6 +208,9 @@ TEST(StringSwitchTest, CasesLower) { EXPECT_EQ(OSType::Windows, Translate(llvm::StringRef("wind\0ws", 7))); EXPECT_EQ(OSType::Linux, Translate("linux")); + EXPECT_EQ(OSType::MacOS, Translate("macOS")); + EXPECT_EQ(OSType::MacOS, Translate("OSX")); + EXPECT_EQ(OSType::Unknown, Translate("wind")); EXPECT_EQ(OSType::Unknown, Translate("")); }