1 //===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //===----------------------------------------------------------------------===/
9 // This file implements the StringSwitch template, which mimics a switch()
10 // statement whose cases are string literals.
12 //===----------------------------------------------------------------------===/
13 #ifndef LLVM_ADT_STRINGSWITCH_H
14 #define LLVM_ADT_STRINGSWITCH_H
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/Compiler.h"
23 /// A switch()-like statement whose cases are string literals.
25 /// The StringSwitch class is a simple form of a switch() statement that
26 /// determines whether the given string matches one of the given string
27 /// literals. The template type parameter \p T is the type of the value that
28 /// will be returned from the string-switch expression. For example,
29 /// the following code switches on the name of a color in \c argv[i]:
32 /// Color color = StringSwitch<Color>(argv[i])
34 /// .Case("orange", Orange)
35 /// .Case("yellow", Yellow)
36 /// .Case("green", Green)
37 /// .Case("blue", Blue)
38 /// .Case("indigo", Indigo)
39 /// .Cases("violet", "purple", Violet)
40 /// .Default(UnknownColor);
42 template<typename T, typename R = T>
44 /// The string we are matching.
47 /// The pointer to the result of this switch statement, once known,
52 LLVM_ATTRIBUTE_ALWAYS_INLINE
53 explicit StringSwitch(StringRef S)
54 : Str(S), Result() { }
56 // StringSwitch is not copyable.
57 StringSwitch(const StringSwitch &) = delete;
59 // StringSwitch is not assignable due to 'Str' being 'const'.
60 void operator=(const StringSwitch &) = delete;
61 void operator=(StringSwitch &&other) = delete;
63 StringSwitch(StringSwitch &&other)
64 : Str(other.Str), Result(std::move(other.Result)) { }
66 ~StringSwitch() = default;
68 // Case-sensitive case matchers
69 LLVM_ATTRIBUTE_ALWAYS_INLINE
70 StringSwitch &Case(StringLiteral S, T Value) {
71 if (!Result && Str == S) {
72 Result = std::move(Value);
77 LLVM_ATTRIBUTE_ALWAYS_INLINE
78 StringSwitch& EndsWith(StringLiteral S, T Value) {
79 if (!Result && Str.endswith(S)) {
80 Result = std::move(Value);
85 LLVM_ATTRIBUTE_ALWAYS_INLINE
86 StringSwitch& StartsWith(StringLiteral S, T Value) {
87 if (!Result && Str.startswith(S)) {
88 Result = std::move(Value);
93 LLVM_ATTRIBUTE_ALWAYS_INLINE
94 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, T Value) {
95 return Case(S0, Value).Case(S1, Value);
98 LLVM_ATTRIBUTE_ALWAYS_INLINE
99 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
101 return Case(S0, Value).Cases(S1, S2, Value);
104 LLVM_ATTRIBUTE_ALWAYS_INLINE
105 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
106 StringLiteral S3, T Value) {
107 return Case(S0, Value).Cases(S1, S2, S3, Value);
110 LLVM_ATTRIBUTE_ALWAYS_INLINE
111 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
112 StringLiteral S3, StringLiteral S4, T Value) {
113 return Case(S0, Value).Cases(S1, S2, S3, S4, Value);
116 LLVM_ATTRIBUTE_ALWAYS_INLINE
117 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
118 StringLiteral S3, StringLiteral S4, StringLiteral S5,
120 return Case(S0, Value).Cases(S1, S2, S3, S4, S5, Value);
123 LLVM_ATTRIBUTE_ALWAYS_INLINE
124 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
125 StringLiteral S3, StringLiteral S4, StringLiteral S5,
126 StringLiteral S6, T Value) {
127 return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, Value);
130 LLVM_ATTRIBUTE_ALWAYS_INLINE
131 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
132 StringLiteral S3, StringLiteral S4, StringLiteral S5,
133 StringLiteral S6, StringLiteral S7, T Value) {
134 return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, Value);
137 LLVM_ATTRIBUTE_ALWAYS_INLINE
138 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
139 StringLiteral S3, StringLiteral S4, StringLiteral S5,
140 StringLiteral S6, StringLiteral S7, StringLiteral S8,
142 return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, Value);
145 LLVM_ATTRIBUTE_ALWAYS_INLINE
146 StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
147 StringLiteral S3, StringLiteral S4, StringLiteral S5,
148 StringLiteral S6, StringLiteral S7, StringLiteral S8,
149 StringLiteral S9, T Value) {
150 return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, S9, Value);
153 // Case-insensitive case matchers.
154 LLVM_ATTRIBUTE_ALWAYS_INLINE
155 StringSwitch &CaseLower(StringLiteral S, T Value) {
156 if (!Result && Str.equals_lower(S))
157 Result = std::move(Value);
162 LLVM_ATTRIBUTE_ALWAYS_INLINE
163 StringSwitch &EndsWithLower(StringLiteral S, T Value) {
164 if (!Result && Str.endswith_lower(S))
170 LLVM_ATTRIBUTE_ALWAYS_INLINE
171 StringSwitch &StartsWithLower(StringLiteral S, T Value) {
172 if (!Result && Str.startswith_lower(S))
173 Result = std::move(Value);
178 LLVM_ATTRIBUTE_ALWAYS_INLINE
179 StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, T Value) {
180 return CaseLower(S0, Value).CaseLower(S1, Value);
183 LLVM_ATTRIBUTE_ALWAYS_INLINE
184 StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
186 return CaseLower(S0, Value).CasesLower(S1, S2, Value);
189 LLVM_ATTRIBUTE_ALWAYS_INLINE
190 StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
191 StringLiteral S3, T Value) {
192 return CaseLower(S0, Value).CasesLower(S1, S2, S3, Value);
195 LLVM_ATTRIBUTE_ALWAYS_INLINE
196 StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
197 StringLiteral S3, StringLiteral S4, T Value) {
198 return CaseLower(S0, Value).CasesLower(S1, S2, S3, S4, Value);
202 LLVM_ATTRIBUTE_ALWAYS_INLINE
205 return std::move(*Result);
210 LLVM_ATTRIBUTE_ALWAYS_INLINE
212 assert(Result && "Fell off the end of a string-switch");
213 return std::move(*Result);
217 } // end namespace llvm
219 #endif // LLVM_ADT_STRINGSWITCH_H