1 //===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //===----------------------------------------------------------------------===/
8 // This file implements the StringSwitch template, which mimics a switch()
9 // statement whose cases are string literals.
11 //===----------------------------------------------------------------------===/
12 #ifndef LLVM_ADT_STRINGSWITCH_H
13 #define LLVM_ADT_STRINGSWITCH_H
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Support/Compiler.h"
22 /// A switch()-like statement whose cases are string literals.
24 /// The StringSwitch class is a simple form of a switch() statement that
25 /// determines whether the given string matches one of the given string
26 /// literals. The template type parameter \p T is the type of the value that
27 /// will be returned from the string-switch expression. For example,
28 /// the following code switches on the name of a color in \c argv[i]:
31 /// Color color = StringSwitch<Color>(argv[i])
33 /// .Case("orange", Orange)
34 /// .Case("yellow", Yellow)
35 /// .Case("green", Green)
36 /// .Case("blue", Blue)
37 /// .Case("indigo", Indigo)
38 /// .Cases("violet", "purple", Violet)
39 /// .Default(UnknownColor);
41 template<typename T, typename R = T>
43 /// The string we are matching.
46 /// The pointer to the result of this switch statement, once known,
51 explicit StringSwitch(StringRef S)
52 : Str(S), Result() { }
54 // StringSwitch is not copyable.
55 StringSwitch(const StringSwitch &) = delete;
57 // StringSwitch is not assignable due to 'Str' being 'const'.
58 void operator=(const StringSwitch &) = delete;
59 void operator=(StringSwitch &&other) = delete;
61 StringSwitch(StringSwitch &&other)
62 : Str(other.Str), Result(std::move(other.Result)) { }
64 ~StringSwitch() = default;
66 // Case-sensitive case matchers
67 StringSwitch &Case(StringLiteral S, T Value) {
68 if (!Result && Str == S) {
69 Result = std::move(Value);
74 StringSwitch& EndsWith(StringLiteral S, T Value) {
75 if (!Result && Str.endswith(S)) {
76 Result = std::move(Value);
81 StringSwitch& StartsWith(StringLiteral S, T Value) {
82 if (!Result && Str.startswith(S)) {
83 Result = std::move(Value);
88 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, T Value) {
89 return Case(S0, Value).Case(S1, Value);
92 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
94 return Case(S0, Value).Cases(S1, S2, Value);
97 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
98 StringLiteral S3, T Value) {
99 return Case(S0, Value).Cases(S1, S2, S3, Value);
102 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
103 StringLiteral S3, StringLiteral S4, T Value) {
104 return Case(S0, Value).Cases(S1, S2, S3, S4, Value);
107 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
108 StringLiteral S3, StringLiteral S4, StringLiteral S5,
110 return Case(S0, Value).Cases(S1, S2, S3, S4, S5, Value);
113 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
114 StringLiteral S3, StringLiteral S4, StringLiteral S5,
115 StringLiteral S6, T Value) {
116 return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, Value);
119 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
120 StringLiteral S3, StringLiteral S4, StringLiteral S5,
121 StringLiteral S6, StringLiteral S7, T Value) {
122 return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, Value);
125 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
126 StringLiteral S3, StringLiteral S4, StringLiteral S5,
127 StringLiteral S6, StringLiteral S7, StringLiteral S8,
129 return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, Value);
132 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
133 StringLiteral S3, StringLiteral S4, StringLiteral S5,
134 StringLiteral S6, StringLiteral S7, StringLiteral S8,
135 StringLiteral S9, T Value) {
136 return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, S9, Value);
139 // Case-insensitive case matchers.
140 StringSwitch &CaseLower(StringLiteral S, T Value) {
141 if (!Result && Str.equals_lower(S))
142 Result = std::move(Value);
147 StringSwitch &EndsWithLower(StringLiteral S, T Value) {
148 if (!Result && Str.endswith_lower(S))
154 StringSwitch &StartsWithLower(StringLiteral S, T Value) {
155 if (!Result && Str.startswith_lower(S))
156 Result = std::move(Value);
161 StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, T Value) {
162 return CaseLower(S0, Value).CaseLower(S1, Value);
165 StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
167 return CaseLower(S0, Value).CasesLower(S1, S2, Value);
170 StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
171 StringLiteral S3, T Value) {
172 return CaseLower(S0, Value).CasesLower(S1, S2, S3, Value);
175 StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
176 StringLiteral S3, StringLiteral S4, T Value) {
177 return CaseLower(S0, Value).CasesLower(S1, S2, S3, S4, Value);
183 return std::move(*Result);
189 assert(Result && "Fell off the end of a string-switch");
190 return std::move(*Result);
194 } // end namespace llvm
196 #endif // LLVM_ADT_STRINGSWITCH_H