Skip to content

Commit d4f4871

Browse files
committed
stdlib: add StringSwitch to LLVMSupport fork
This is used in the standard library for the reflection. Add the missing header. Somehow this was missed in the dynamic version of the standard library.
1 parent 98fd1b2 commit d4f4871

File tree

1 file changed

+198
-0
lines changed

1 file changed

+198
-0
lines changed
+198
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
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+
// This file implements the StringSwitch template, which mimics a switch()
9+
// statement whose cases are string literals.
10+
//
11+
//===----------------------------------------------------------------------===/
12+
#ifndef LLVM_ADT_STRINGSWITCH_H
13+
#define LLVM_ADT_STRINGSWITCH_H
14+
15+
#include "llvm/ADT/StringRef.h"
16+
#include "llvm/Support/Compiler.h"
17+
#include <cassert>
18+
#include <cstring>
19+
20+
inline namespace __swift { inline namespace __runtime {
21+
namespace 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
42+
template<typename T, typename R = T>
43+
class StringSwitch {
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+
Optional<T> Result;
50+
51+
public:
52+
explicit StringSwitch(StringRef S)
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+
62+
StringSwitch(StringSwitch &&other)
63+
: Str(other.Str), Result(std::move(other.Result)) { }
64+
65+
~StringSwitch() = default;
66+
67+
// Case-sensitive case matchers
68+
StringSwitch &Case(StringLiteral S, T Value) {
69+
if (!Result && Str == S) {
70+
Result = std::move(Value);
71+
}
72+
return *this;
73+
}
74+
75+
StringSwitch& EndsWith(StringLiteral S, T Value) {
76+
if (!Result && Str.endswith(S)) {
77+
Result = std::move(Value);
78+
}
79+
return *this;
80+
}
81+
82+
StringSwitch& StartsWith(StringLiteral S, T Value) {
83+
if (!Result && Str.startswith(S)) {
84+
Result = std::move(Value);
85+
}
86+
return *this;
87+
}
88+
89+
StringSwitch &Cases(StringLiteral S0, StringLiteral S1, T Value) {
90+
return Case(S0, Value).Case(S1, Value);
91+
}
92+
93+
StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
94+
T Value) {
95+
return Case(S0, Value).Cases(S1, S2, Value);
96+
}
97+
98+
StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
99+
StringLiteral S3, T Value) {
100+
return Case(S0, Value).Cases(S1, S2, S3, Value);
101+
}
102+
103+
StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
104+
StringLiteral S3, StringLiteral S4, T Value) {
105+
return Case(S0, Value).Cases(S1, S2, S3, S4, Value);
106+
}
107+
108+
StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
109+
StringLiteral S3, StringLiteral S4, StringLiteral S5,
110+
T Value) {
111+
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, Value);
112+
}
113+
114+
StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
115+
StringLiteral S3, StringLiteral S4, StringLiteral S5,
116+
StringLiteral S6, T Value) {
117+
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, Value);
118+
}
119+
120+
StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
121+
StringLiteral S3, StringLiteral S4, StringLiteral S5,
122+
StringLiteral S6, StringLiteral S7, T Value) {
123+
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, Value);
124+
}
125+
126+
StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
127+
StringLiteral S3, StringLiteral S4, StringLiteral S5,
128+
StringLiteral S6, StringLiteral S7, StringLiteral S8,
129+
T Value) {
130+
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, Value);
131+
}
132+
133+
StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
134+
StringLiteral S3, StringLiteral S4, StringLiteral S5,
135+
StringLiteral S6, StringLiteral S7, StringLiteral S8,
136+
StringLiteral S9, T Value) {
137+
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, S9, Value);
138+
}
139+
140+
// Case-insensitive case matchers.
141+
StringSwitch &CaseLower(StringLiteral S, T Value) {
142+
if (!Result && Str.equals_lower(S))
143+
Result = std::move(Value);
144+
145+
return *this;
146+
}
147+
148+
StringSwitch &EndsWithLower(StringLiteral S, T Value) {
149+
if (!Result && Str.endswith_lower(S))
150+
Result = Value;
151+
152+
return *this;
153+
}
154+
155+
StringSwitch &StartsWithLower(StringLiteral S, T Value) {
156+
if (!Result && Str.startswith_lower(S))
157+
Result = std::move(Value);
158+
159+
return *this;
160+
}
161+
162+
StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, T Value) {
163+
return CaseLower(S0, Value).CaseLower(S1, Value);
164+
}
165+
166+
StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
167+
T Value) {
168+
return CaseLower(S0, Value).CasesLower(S1, S2, Value);
169+
}
170+
171+
StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
172+
StringLiteral S3, T Value) {
173+
return CaseLower(S0, Value).CasesLower(S1, S2, S3, Value);
174+
}
175+
176+
StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
177+
StringLiteral S3, StringLiteral S4, T Value) {
178+
return CaseLower(S0, Value).CasesLower(S1, S2, S3, S4, Value);
179+
}
180+
181+
LLVM_NODISCARD
182+
R Default(T Value) {
183+
if (Result)
184+
return std::move(*Result);
185+
return Value;
186+
}
187+
188+
LLVM_NODISCARD
189+
operator R() {
190+
assert(Result && "Fell off the end of a string-switch");
191+
return std::move(*Result);
192+
}
193+
};
194+
195+
} // end namespace llvm
196+
}}
197+
198+
#endif // LLVM_ADT_STRINGSWITCH_H

0 commit comments

Comments
 (0)