LLVM 22.0.0git
StringSwitch.h
Go to the documentation of this file.
1//===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/
2//
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//===----------------------------------------------------------------------===/
7///
8/// \file
9/// This file implements the StringSwitch template, which mimics a switch()
10/// statement whose cases are string literals.
11///
12//===----------------------------------------------------------------------===/
13#ifndef LLVM_ADT_STRINGSWITCH_H
14#define LLVM_ADT_STRINGSWITCH_H
15
16#include "llvm/ADT/StringRef.h"
17#include <cassert>
18#include <cstring>
19#include <optional>
20
21namespace llvm {
22
23/// A switch()-like statement whose cases are string literals.
24///
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]:
30///
31/// \code
32/// Color color = StringSwitch<Color>(argv[i])
33/// .Case("red", Red)
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);
41/// \endcode
42template<typename T, typename R = T>
44 /// The string we are matching.
45 const StringRef Str;
46
47 /// The pointer to the result of this switch statement, once known,
48 /// null before that.
49 std::optional<T> Result;
50
51public:
53 : Str(S), Result() { }
54
55 // StringSwitch is not copyable.
56 StringSwitch(const StringSwitch &) = delete;
57
58 // StringSwitch is not assignable due to 'Str' being 'const'.
59 void operator=(const StringSwitch &) = delete;
60 void operator=(StringSwitch &&other) = delete;
61
63 : Str(other.Str), Result(std::move(other.Result)) { }
64
65 ~StringSwitch() = default;
66
67 // Case-sensitive case matchers
69 CaseImpl(Value, S);
70 return *this;
71 }
72
74 if (!Result && Str.ends_with(S)) {
75 Result = std::move(Value);
76 }
77 return *this;
78 }
79
81 if (!Result && Str.starts_with(S)) {
82 Result = std::move(Value);
83 }
84 return *this;
85 }
86
88 return CasesImpl(Value, S0, S1);
89 }
90
92 T Value) {
93 return CasesImpl(Value, S0, S1, S2);
94 }
95
97 StringLiteral S3, T Value) {
98 return CasesImpl(Value, S0, S1, S2, S3);
99 }
100
103 return CasesImpl(Value, S0, S1, S2, S3, S4);
104 }
105
108 T Value) {
109 return CasesImpl(Value, S0, S1, S2, S3, S4, S5);
110 }
111
114 StringLiteral S6, T Value) {
115 return CasesImpl(Value, S0, S1, S2, S3, S4, S5, S6);
116 }
117
121 return CasesImpl(Value, S0, S1, S2, S3, S4, S5, S6, S7);
122 }
123
127 T Value) {
128 return CasesImpl(Value, S0, S1, S2, S3, S4, S5, S6, S7, S8);
129 }
130
134 StringLiteral S9, T Value) {
135 return CasesImpl(Value, S0, S1, S2, S3, S4, S5, S6, S7, S8, S9);
136 }
137
138 // Case-insensitive case matchers.
140 CaseLowerImpl(Value, S);
141 return *this;
142 }
143
145 if (!Result && Str.ends_with_insensitive(S))
146 Result = Value;
147
148 return *this;
149 }
150
152 if (!Result && Str.starts_with_insensitive(S))
153 Result = std::move(Value);
154
155 return *this;
156 }
157
159 return CasesLowerImpl(Value, S0, S1);
160 }
161
163 T Value) {
164 return CasesLowerImpl(Value, S0, S1, S2);
165 }
166
168 StringLiteral S3, T Value) {
169 return CasesLowerImpl(Value, S0, S1, S2, S3);
170 }
171
174 return CasesLowerImpl(Value, S0, S1, S2, S3, S4);
175 }
176
177 [[nodiscard]] R Default(T Value) {
178 if (Result)
179 return std::move(*Result);
180 return Value;
181 }
182
183 [[nodiscard]] operator R() {
184 assert(Result && "Fell off the end of a string-switch");
185 return std::move(*Result);
186 }
187
188private:
189 // Returns true when `Str` matches the `S` argument, and stores the result.
190 bool CaseImpl(T &Value, StringLiteral S) {
191 if (!Result && Str == S) {
192 Result = std::move(Value);
193 return true;
194 }
195 return false;
196 }
197
198 // Returns true when `Str` matches the `S` argument (case-insensitive), and
199 // stores the result.
200 bool CaseLowerImpl(T &Value, StringLiteral S) {
201 if (!Result && Str.equals_insensitive(S)) {
202 Result = std::move(Value);
203 return true;
204 }
205 return false;
206 }
207
208 template <typename... Args> StringSwitch &CasesImpl(T &Value, Args... Cases) {
209 // Stop matching after the string is found.
210 (... || CaseImpl(Value, Cases));
211 return *this;
212 }
213
214 template <typename... Args>
215 StringSwitch &CasesLowerImpl(T &Value, Args... Cases) {
216 // Stop matching after the string is found.
217 (... || CaseLowerImpl(Value, Cases));
218 return *this;
219 }
220};
221
222} // end namespace llvm
223
224#endif // LLVM_ADT_STRINGSWITCH_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
constexpr LLT S1
constexpr LLT S8
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition: StringRef.h:862
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:43
StringSwitch & CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, T Value)
Definition: StringSwitch.h:172
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, T Value)
Definition: StringSwitch.h:106
StringSwitch & EndsWithLower(StringLiteral S, T Value)
Definition: StringSwitch.h:144
StringSwitch & StartsWithLower(StringLiteral S, T Value)
Definition: StringSwitch.h:151
StringSwitch & CaseLower(StringLiteral S, T Value)
Definition: StringSwitch.h:139
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:68
StringSwitch & CasesLower(StringLiteral S0, StringLiteral S1, T Value)
Definition: StringSwitch.h:158
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, T Value)
Definition: StringSwitch.h:101
void operator=(const StringSwitch &)=delete
StringSwitch & CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, T Value)
Definition: StringSwitch.h:167
R Default(T Value)
Definition: StringSwitch.h:177
StringSwitch & StartsWith(StringLiteral S, T Value)
Definition: StringSwitch.h:80
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, StringLiteral S6, StringLiteral S7, StringLiteral S8, T Value)
Definition: StringSwitch.h:124
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
Definition: StringSwitch.h:87
StringSwitch(const StringSwitch &)=delete
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, T Value)
Definition: StringSwitch.h:96
StringSwitch & EndsWith(StringLiteral S, T Value)
Definition: StringSwitch.h:73
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, StringLiteral S6, StringLiteral S7, T Value)
Definition: StringSwitch.h:118
StringSwitch(StringSwitch &&other)
Definition: StringSwitch.h:62
void operator=(StringSwitch &&other)=delete
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, StringLiteral S6, T Value)
Definition: StringSwitch.h:112
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, T Value)
Definition: StringSwitch.h:91
StringSwitch(StringRef S)
Definition: StringSwitch.h:52
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, StringLiteral S6, StringLiteral S7, StringLiteral S8, StringLiteral S9, T Value)
Definition: StringSwitch.h:131
StringSwitch & CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, T Value)
Definition: StringSwitch.h:162
~StringSwitch()=default
LLVM Value Representation.
Definition: Value.h:75
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1886
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:856