//===----------------------------------------------------------------------===/
//
// This file implements the StringSwitch template, which mimics a switch()
-// statements whose cases are string literals.
+// statement whose cases are string literals.
//
//===----------------------------------------------------------------------===/
#ifndef LLVM_ADT_STRINGSWITCH_H
/// .Cases("violet", "purple", Violet)
/// .Default(UnknownColor);
/// \endcode
-template<typename T>
+template<typename T, typename R = T>
class StringSwitch {
/// \brief The string we are matching.
StringRef Str;
- /// \brief The result of this switch statement, once known.
- T Result;
-
- /// \brief Set true when the result of this switch is already known; in this
- /// case, Result is valid.
- bool ResultKnown;
+ /// \brief The pointer to the result of this switch statement, once known,
+ /// null before that.
+ const T *Result;
public:
- explicit StringSwitch(StringRef Str)
- : Str(Str), ResultKnown(false) { }
+ explicit StringSwitch(StringRef S)
+ : Str(S), Result(nullptr) { }
template<unsigned N>
StringSwitch& Case(const char (&S)[N], const T& Value) {
- if (!ResultKnown && N-1 == Str.size() &&
+ if (!Result && N-1 == Str.size() &&
(std::memcmp(S, Str.data(), N-1) == 0)) {
- Result = Value;
- ResultKnown = true;
+ Result = &Value;
+ }
+
+ return *this;
+ }
+
+ template<unsigned N>
+ StringSwitch& EndsWith(const char (&S)[N], const T &Value) {
+ if (!Result && Str.size() >= N-1 &&
+ std::memcmp(S, Str.data() + Str.size() + 1 - N, N-1) == 0) {
+ Result = &Value;
+ }
+
+ return *this;
+ }
+
+ template<unsigned N>
+ StringSwitch& StartsWith(const char (&S)[N], const T &Value) {
+ if (!Result && Str.size() >= N-1 &&
+ std::memcmp(S, Str.data(), N-1) == 0) {
+ Result = &Value;
}
return *this;
.Case(S4, Value);
}
- T Default(const T& Value) {
- if (ResultKnown)
- return Result;
+ R Default(const T& Value) const {
+ if (Result)
+ return *Result;
return Value;
}
- operator T() {
- assert(ResultKnown && "Fell off the end of a string-switch");
- return Result;
+ operator R() const {
+ assert(Result && "Fell off the end of a string-switch");
+ return *Result;
}
};