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//===----------------------------------------------------------------------===/
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
21#include <initializer_list>
26/// A switch()-like statement whose cases are string literals.
28/// The StringSwitch class is a simple form of a switch() statement that
29/// determines whether the given string matches one of the given string
30/// literals. The template type parameter \p T is the type of the value that
31/// will be returned from the string-switch expression. For example,
32/// the following code switches on the name of a color in \c argv[i]:
35/// Color color = StringSwitch<Color>(argv[i])
37/// .Case("orange", Orange)
38/// .Case("yellow", Yellow)
39/// .Case("green", Green)
40/// .Case("blue", Blue)
41/// .Case("indigo", Indigo)
42/// .Cases({"violet", "purple"}, Violet)
43/// .Default(UnknownColor);
45template<
typename T,
typename R = T>
47 /// The string we are matching.
50 /// The pointer to the result of this switch statement, once known,
52 std::optional<T> Result;
56 : Str(S), Result() { }
60 // StringSwitch is not copyable.
63 // StringSwitch is not assignable due to 'Str' being 'const'.
67 // Case-sensitive case matchers
74 if (!Result && Str.ends_with(S)) {
75 Result = std::move(
Value);
81 if (!Result && Str.starts_with(S)) {
82 Result = std::move(
Value);
89 return CasesImpl(CaseStrings,
Value);
93 return CasesImpl({S0,
S1},
Value);
96 [[deprecated(
"Pass cases in std::initializer_list instead")]]
99 return CasesImpl({S0,
S1, S2},
Value);
102 [[deprecated(
"Pass cases in std::initializer_list instead")]]
105 return CasesImpl({S0,
S1, S2, S3},
Value);
108 [[deprecated(
"Pass cases in std::initializer_list instead")]]
111 return CasesImpl({S0,
S1, S2, S3, S4},
Value);
114 [[deprecated(
"Pass cases in std::initializer_list instead")]]
118 return CasesImpl({S0,
S1, S2, S3, S4, S5},
Value);
121 [[deprecated(
"Pass cases in std::initializer_list instead")]]
125 return CasesImpl({S0,
S1, S2, S3, S4, S5, S6},
Value);
128 [[deprecated(
"Pass cases in std::initializer_list instead")]]
132 return CasesImpl({S0,
S1, S2, S3, S4, S5, S6, S7},
Value);
135 [[deprecated(
"Pass cases in std::initializer_list instead")]]
140 return CasesImpl({S0,
S1, S2, S3, S4, S5, S6, S7,
S8},
Value);
143 [[deprecated(
"Pass cases in std::initializer_list instead")]]
148 return CasesImpl({S0,
S1, S2, S3, S4, S5, S6, S7,
S8, S9},
Value);
151 // Case-insensitive case matchers.
153 CaseLowerImpl(S,
Value);
158 if (!Result && Str.ends_with_insensitive(S))
165 if (!Result && Str.starts_with_insensitive(S))
166 Result = std::move(
Value);
173 return CasesLowerImpl(CaseStrings,
Value);
177 return CasesLowerImpl({S0,
S1},
Value);
180 [[deprecated(
"Pass cases in std::initializer_list instead")]]
183 return CasesLowerImpl({S0,
S1, S2},
Value);
186 [[deprecated(
"Pass cases in std::initializer_list instead")]]
189 return CasesLowerImpl({S0,
S1, S2, S3},
Value);
192 [[deprecated(
"Pass cases in std::initializer_list instead")]]
195 return CasesLowerImpl({S0,
S1, S2, S3, S4},
Value);
200 return std::move(*Result);
204 /// Declare default as unreachable, making sure that all cases were handled.
206 const char *Message =
"Fell off the end of a string-switch") {
208 return std::move(*Result);
215 // Returns true when `Str` matches the `S` argument, and stores the result.
217 if (!Result && Str == S) {
218 Result = std::move(
Value);
224 // Returns true when `Str` matches the `S` argument (case-insensitive), and
225 // stores the result.
226 bool CaseLowerImpl(StringLiteral S,
T &
Value) {
227 if (!Result && Str.equals_insensitive(S)) {
228 Result = std::move(
Value);
236 // Stop matching after the string is found.
237 for (StringLiteral S :
Cases)
238 if (CaseImpl(S,
Value))
245 // Stop matching after the string is found.
246 for (StringLiteral S :
Cases)
247 if (CaseLowerImpl(S,
Value))
253}
// end namespace llvm
255#endif // LLVM_ADT_STRINGSWITCH_H
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringRef - Represent a constant reference to a string, i.e.
StringSwitch & CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, T Value)
StringSwitch & EndsWithLower(StringLiteral S, T Value)
StringSwitch & StartsWithLower(StringLiteral S, T Value)
StringSwitch & CaseLower(StringLiteral S, T Value)
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & CasesLower(StringLiteral S0, StringLiteral S1, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, T Value)
void operator=(StringSwitch &&)=delete
void operator=(const StringSwitch &)=delete
StringSwitch & CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, T Value)
R DefaultUnreachable(const char *Message="Fell off the end of a string-switch")
Declare default as unreachable, making sure that all cases were handled.
StringSwitch & CasesLower(std::initializer_list< StringLiteral > CaseStrings, T Value)
StringSwitch & StartsWith(StringLiteral S, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, StringLiteral S6, StringLiteral S7, StringLiteral S8, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
StringSwitch(const StringSwitch &)=delete
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, T Value)
StringSwitch & EndsWith(StringLiteral S, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, StringLiteral S6, StringLiteral S7, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, StringLiteral S6, T Value)
StringSwitch(StringSwitch &&)=default
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, T Value)
StringSwitch & Cases(std::initializer_list< StringLiteral > CaseStrings, T Value)
StringSwitch(StringRef S)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, StringLiteral S6, StringLiteral S7, StringLiteral S8, StringLiteral S9, T Value)
StringSwitch & CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, T Value)
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value